// Findings panel — lists detected assumptions / risks / inconsistencies.
// Lives in the bottom-right corner above the IssuesPanel; collapsible;
// has a "detect" button that triggers a fresh background pass.
//
// Items are clickable: clicking focuses the first linked element across
// the rail + diagram (using the same setFocusBlockId path as the rail).

"use client";

import { useCallback, useEffect, useState } from "react";

export type FindingKind = "assumption" | "risk" | "inconsistency";

export interface FindingDTO {
  id: string;
  kind: FindingKind;
  text: string;
  linkedElementIds: string[];
  confidence: number;
  severity?: "low" | "medium" | "high" | null;
  validationCode?: string | null;
  modelVersion: number;
  provider?: string | null;
  llmModel?: string | null;
}

interface FindingsPanelProps {
  projectId: string;
  /** Re-fetch whenever this changes. Pass the model version so we know when to refresh. */
  modelVersion: number;
  onSelectAnchor?: (elementId: string) => void;
}

const KIND_GLYPH: Record<FindingKind, string> = {
  assumption: "●",
  risk: "▲",
  inconsistency: "!",
};

const KIND_LABEL: Record<FindingKind, string> = {
  assumption: "asm",
  risk: "risk",
  inconsistency: "inc",
};

export function FindingsPanel({ projectId, modelVersion, onSelectAnchor }: FindingsPanelProps) {
  const [findings, setFindings] = useState<FindingDTO[] | null>(null);
  const [collapsed, setCollapsed] = useState(false);
  const [running, setRunning] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [meta, setMeta] = useState<{ provider?: string; model?: string; durationMs?: number; modelVersion?: number } | null>(null);

  // Initial load
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const res = await fetch(`/api/projects/${encodeURIComponent(projectId)}/findings`);
        if (!res.ok) throw new Error(String(res.status));
        const data = (await res.json()) as { findings: FindingDTO[] };
        if (cancelled) return;
        setFindings(data.findings);
        if (data.findings.length > 0) {
          const first = data.findings[0]!;
          setMeta({ provider: first.provider ?? undefined, model: first.llmModel ?? undefined, modelVersion: first.modelVersion });
        }
      } catch (err) {
        if (!cancelled) setError((err as Error).message);
      }
    })();
    return () => { cancelled = true; };
  }, [projectId]);

  const detect = useCallback(async () => {
    if (running) return;
    setRunning(true);
    setError(null);
    try {
      const res = await fetch(`/api/projects/${encodeURIComponent(projectId)}/findings`, {
        method: "POST",
      });
      if (!res.ok) {
        const body = await res.json().catch(() => ({}));
        throw new Error(body.error ?? `HTTP ${res.status}`);
      }
      const data = (await res.json()) as {
        findings: FindingDTO[];
        meta: { provider: string; model: string; durationMs: number; strippedRefs: number; droppedFindings: number };
      };
      setFindings(data.findings);
      setMeta({
        provider: data.meta.provider,
        model: data.meta.model,
        durationMs: data.meta.durationMs,
        modelVersion,
      });
    } catch (err) {
      setError((err as Error).message);
    } finally {
      setRunning(false);
    }
  }, [projectId, modelVersion, running]);

  const counts = {
    assumption: findings?.filter(f => f.kind === "assumption").length ?? 0,
    risk: findings?.filter(f => f.kind === "risk").length ?? 0,
    inconsistency: findings?.filter(f => f.kind === "inconsistency").length ?? 0,
  };
  const total = counts.assumption + counts.risk + counts.inconsistency;
  const stale = meta?.modelVersion !== undefined && meta.modelVersion !== modelVersion;

  return (
    <div className={`findings-panel ${collapsed ? "findings-panel-collapsed" : ""}`}>
      <button
        type="button"
        className="findings-panel-head"
        onClick={() => setCollapsed(c => !c)}
      >
        <span className="findings-panel-counts">
          {counts.assumption > 0 && <span className="findings-count findings-count-asm">● {counts.assumption}</span>}
          {counts.risk > 0 && <span className="findings-count findings-count-risk">▲ {counts.risk}</span>}
          {counts.inconsistency > 0 && <span className="findings-count findings-count-inc">! {counts.inconsistency}</span>}
          {total === 0 && findings !== null && <span className="findings-count findings-count-none">no findings</span>}
          {findings === null && <span className="findings-count findings-count-none">loading…</span>}
        </span>
        <span className="findings-panel-title">
          {findings === null ? "findings" : total === 0 ? "no detected findings" : `${total} detected finding${total === 1 ? "" : "s"}`}
          {stale && <span className="findings-panel-stale" title="Model has changed since these were detected">· stale</span>}
        </span>
        <span className="findings-panel-caret">{collapsed ? "▴" : "▾"}</span>
      </button>

      {!collapsed && (
        <>
          <div className="findings-panel-actions">
            <button
              type="button"
              className="findings-panel-btn"
              onClick={detect}
              disabled={running}
            >
              {running ? "detecting…" : findings && findings.length > 0 ? "re-detect" : "detect"}
            </button>
            {meta?.durationMs && (
              <span className="findings-panel-meta">
                {meta.provider} · {meta.model?.split("/").pop()} · {(meta.durationMs / 1000).toFixed(1)}s
              </span>
            )}
          </div>

          {error && <div className="findings-panel-error">⚠ {error}</div>}

          {findings && findings.length > 0 && (
            <ul className="findings-panel-list">
              {(["inconsistency", "risk", "assumption"] as const).flatMap(kind =>
                findings.filter(f => f.kind === kind).map(f => (
                  <li
                    key={f.id}
                    className={`findings-item findings-item-${f.kind}`}
                    onClick={() => {
                      if (f.linkedElementIds.length > 0 && onSelectAnchor) {
                        onSelectAnchor(f.linkedElementIds[0]!);
                      }
                    }}
                    style={{ cursor: f.linkedElementIds.length > 0 ? "pointer" : "default" }}
                  >
                    <span className={`findings-item-glyph findings-item-glyph-${f.kind}`}>{KIND_GLYPH[f.kind]}</span>
                    <span className="findings-item-tag">{KIND_LABEL[f.kind]}</span>
                    {f.severity && <span className={`findings-item-sev findings-item-sev-${f.severity}`}>{f.severity}</span>}
                    {f.validationCode && <span className="findings-item-code">{f.validationCode}</span>}
                    <span className="findings-item-text">{f.text}</span>
                    <span className="findings-item-conf">{f.confidence.toFixed(2)}</span>
                    {f.linkedElementIds.length > 0 && (
                      <span className="findings-item-refs" title={f.linkedElementIds.join(", ")}>
                        [{f.linkedElementIds.slice(0, 3).join(", ")}{f.linkedElementIds.length > 3 ? "…" : ""}]
                      </span>
                    )}
                  </li>
                ))
              )}
            </ul>
          )}
        </>
      )}
    </div>
  );
}
