import { useEffect, useMemo, useRef, useState } from 'react';
import { Link } from 'react-router-dom';
import { api } from '../../api/client';
import {
  atlasSkipDisplayLabel,
  buildAccessDepthModel,
  parseAccessDepthServerPolicy,
  type AccessDepthDiagnostics,
} from '../../help/accessDepth';
import {
  clearanceLabel,
  clearancePermissions,
  formatClearanceElevation,
} from '../../help/clearance';
import { useWebSocket } from '../../hooks/useWebSocket';
import type { Agent } from '../../types';
import { HelpTip } from '../HelpTip';
import JoinLaneBadge from './JoinLaneBadge';
import LotlTierBadge from './LotlTierBadge';
import './AccessDepthPanel.css';
import './LotlVisuals.css';
import './ReconVisuals.css';

interface Props {
  agent: Agent;
  diagnostics?: AccessDepthDiagnostics;
}

function OnionList({ rows, empty }: { rows: ReturnType<typeof buildAccessDepthModel>['miningOnion']; empty: string }) {
  if (rows.length === 0) {
    return <div className="access-depth-empty">{empty}</div>;
  }
  return (
    <ol className="access-depth-onion-list">
      {rows.map((row) => (
        <li key={`${row.index}-${row.tier}`} className={`access-depth-onion-item access-depth-onion-item--${row.status}`}>
          <span className="access-depth-onion-idx">{row.index}.</span>
          <span className="access-depth-onion-label">{row.label}</span>
          {row.status === 'active' && <span className="access-depth-tag access-depth-tag--active">active</span>}
          {row.status === 'skipped' && <span className="access-depth-tag access-depth-tag--skip">skipped</span>}
          {row.status === 'skipped_by_atlas' && (
            <span className="access-depth-tag access-depth-tag--skip">atlas skip</span>
          )}
          {row.status === 'done' && <span className="access-depth-tag access-depth-tag--ok">ok</span>}
          {row.status === 'failed' && <span className="access-depth-tag access-depth-tag--fail">fail</span>}
          {row.status === 'pending' && <span className="access-depth-tag access-depth-tag--pending">pending</span>}
        </li>
      ))}
    </ol>
  );
}

function AttemptMiniList({
  rows,
  empty,
}: {
  rows: ReturnType<typeof buildAccessDepthModel>['succeeded'];
  empty: string;
}) {
  if (rows.length === 0) return <div className="access-depth-empty">{empty}</div>;
  return (
    <ul className="access-depth-attempt-list">
      {rows.map((row, i) => (
        <li key={`${row.tier}-${i}`} className="access-depth-attempt-row">
          <span className={`lotl-attempt-icon ${row.ok ? 'ok' : 'fail'}`}>{row.ok ? '✓' : '✗'}</span>
          <span className="access-depth-attempt-tier">{row.label}</span>
          {row.phase && <span className="access-depth-phase">{row.phase}</span>}
          {!row.ok && row.error && <span className="lotl-attempt-err">{row.error}</span>}
        </li>
      ))}
    </ul>
  );
}

export default function AccessDepthPanel({ agent, diagnostics }: Props) {
  const { latestMessage } = useWebSocket();
  const [policyLoaded, setPolicyLoaded] = useState(false);
  const [serverPolicy, setServerPolicy] = useState(parseAccessDepthServerPolicy({}));
  const [elevationFlash, setElevationFlash] = useState<string | null>(null);
  const flashTimerRef = useRef<number | null>(null);

  const clearanceLevel = agent.clearance_level ?? 1;

  useEffect(() => {
    if (!latestMessage || latestMessage.type !== 'clearance_elevated') return;
    const p = latestMessage.payload as {
      agent_id?: string;
      to_level?: number;
      source?: string;
      reason?: string;
    };
    if (p.agent_id !== agent.id || typeof p.to_level !== 'number') return;
    const text = formatClearanceElevation({
      to_level: p.to_level,
      source: p.source,
      reason: p.reason,
    });
    setElevationFlash(text);
    if (flashTimerRef.current != null) window.clearTimeout(flashTimerRef.current);
    flashTimerRef.current = window.setTimeout(() => setElevationFlash(null), 6000);
  }, [latestMessage, agent.id]);

  useEffect(() => {
    return () => {
      if (flashTimerRef.current != null) window.clearTimeout(flashTimerRef.current);
    };
  }, []);

  useEffect(() => {
    let cancelled = false;
    api
      .getConfig()
      .then((cfg) => {
        if (!cancelled) {
          setServerPolicy(parseAccessDepthServerPolicy(cfg));
          setPolicyLoaded(true);
        }
      })
      .catch(() => {
        if (!cancelled) setPolicyLoaded(true);
      });
    return () => {
      cancelled = true;
    };
  }, []);

  const model = useMemo(
    () => buildAccessDepthModel(agent, diagnostics, serverPolicy),
    [agent, diagnostics, serverPolicy],
  );

  return (
    <section className="access-depth-panel lotl-attempts-block" aria-label="Access depth">
      <div className="access-depth-header">
        <span className="lotl-attempts-title">
          ACCESS DEPTH <HelpTip field="crucible_access_depth" />
        </span>
        <span
          className="access-depth-clearance-badge"
          title={clearancePermissions(clearanceLevel)}
          aria-label={`Clearance ${clearanceLabel(clearanceLevel)}: ${clearancePermissions(clearanceLevel)}`}
        >
          {clearanceLabel(clearanceLevel)}
        </span>
        {elevationFlash && (
          <span className="access-depth-clearance-flash" role="status">
            {elevationFlash}
          </span>
        )}
        {!policyLoaded && <span className="access-depth-muted">loading policy…</span>}
      </div>

      <div className="access-depth-grid">
        <div className="access-depth-section">
          <div className="access-depth-section-title">OS &amp; posture</div>
          <div className="access-depth-os-line">{model.osLine}</div>
          {model.probes.length > 0 && (
            <div className="access-depth-probes">
              {model.probes.map((p) => (
                <span key={p.key} className={`access-depth-probe ${p.ok ? 'ok' : 'no'}`}>
                  {p.label}
                </span>
              ))}
            </div>
          )}
          {model.spreadCaps.length > 0 && (
            <div className="access-depth-meta">
              spread: {model.spreadCaps.join(', ')}
            </div>
          )}
          {model.privilegeHints.length > 0 && (
            <div className="access-depth-meta">
              {model.privilegeHints.join(' · ')}
            </div>
          )}
        </div>

        <div className="access-depth-section">
          <div className="access-depth-section-title">Active</div>
          {model.activeTier ? (
            <LotlTierBadge tier={model.activeTier} attempts={agent.lotl_attempts} variant="inline" />
          ) : (
            <div className="access-depth-empty">No active mining tier</div>
          )}
          {model.joinLane ? (
            <div className="access-depth-join">
              join lane <JoinLaneBadge lane={model.joinLane} />
            </div>
          ) : (
            <div className="access-depth-muted">No join lane yet</div>
          )}
          {model.phenotypeSource && (
            <div className="access-depth-phenotype">
              phenotype cloned from <strong>{model.phenotypeSource}</strong>
              {model.phenotypeSpreadLane ? (
                <>
                  {' '}
                  · spread <JoinLaneBadge lane={model.phenotypeSpreadLane} />
                </>
              ) : null}
            </div>
          )}
        </div>

        <div className="access-depth-section">
          <div className="access-depth-section-title">Succeeded</div>
          <AttemptMiniList rows={model.succeeded} empty="No successful tier attempts" />
        </div>

        <div className="access-depth-section">
          <div className="access-depth-section-title">Failed / in progress</div>
          <AttemptMiniList rows={model.failed} empty="No failed attempts" />
          {model.inProgressLabel && (
            <div className="access-depth-in-progress">
              trying <strong>{model.inProgressLabel}</strong>
            </div>
          )}
          {model.pendingLabels.length > 0 && (
            <div className="access-depth-pending">
              pending: {model.pendingLabels.slice(0, 6).join(' → ')}
              {model.pendingLabels.length > 6 ? ` +${model.pendingLabels.length - 6}` : ''}
            </div>
          )}
        </div>
      </div>

      {model.atlasSkips.length > 0 && (
        <div className="access-depth-section access-depth-atlas-block">
          <div className="access-depth-section-title">Atlas skips</div>
          <ul className="access-depth-atlas-list">
            {model.atlasSkips.map((skip) => (
              <li key={`${skip.tier}-${skip.condition}`} className="access-depth-atlas-row">
                {atlasSkipDisplayLabel(skip)}
              </li>
            ))}
          </ul>
        </div>
      )}

      {model.strategyReasoning.length > 0 && (
        <div className="access-depth-section access-depth-strategy-block">
          <div className="access-depth-section-title">
            Strategy
            {model.adaptiveActive && (
              <span className="access-depth-tag access-depth-tag--active access-depth-adaptive-badge">Adaptive</span>
            )}
          </div>
          <ul className="access-depth-strategy-list">
            {model.strategyReasoning.map((row, i) => (
              <li key={`${row.action}-${i}`} className="access-depth-strategy-row">
                <span className="access-depth-strategy-fact">{row.fact}</span>
                <span className="access-depth-strategy-inference">{row.inference}</span>
                <span className="access-depth-strategy-action">{row.action}</span>
              </li>
            ))}
          </ul>
          {typeof model.adaptiveConfidence === 'number' && (
            <div className="access-depth-meta">confidence {Math.round(model.adaptiveConfidence * 100)}%</div>
          )}
        </div>
      )}

      <div className="access-depth-section access-depth-onion-block">
        <div className="access-depth-section-title">
          Effective onion order
          <span className="access-depth-source">({model.miningOrderSource})</span>
          {model.adaptiveActive && (
            <span className="access-depth-tag access-depth-tag--active access-depth-adaptive-badge">AI path</span>
          )}
        </div>
        <div className="access-depth-onion-columns">
          <div>
            <div className="access-depth-onion-subtitle">Mining tiers</div>
            <OnionList rows={model.miningOnion} empty="No mining tier chain" />
          </div>
          <div>
            <div className="access-depth-onion-subtitle">
              Spread contingency{' '}
              <Link to="/settings" className="access-depth-calibrate-link">
                Calibrate
              </Link>
            </div>
            <OnionList rows={model.spreadOnion} empty="Default spread order" />
          </div>
        </div>
        {model.tripleOnionSummary && (
          <div className="access-depth-triple">
            Triple onion: {model.tripleOnionSummary}
          </div>
        )}
        <p className="access-depth-hint">
          <HelpTip field="crucible_access_depth_calibrate" label="?" />{' '}
          Calibrate → <Link to="/settings">lotl_onion_tiers</Link> changes spread order on next agent reconnect.
        </p>
      </div>
    </section>
  );
}
