/**
 * /h/[hypothesisId] — Hypothesis dossier.
 *
 * Renders one H-NNNN as a full case file:
 *   - question + position
 *   - prior + posterior with delta + Tetlock band
 *   - argument_for vs argument_against side-by-side (responsive)
 *   - evidence chain cards (each E-NNNN supporting/refuting)
 *   - red-team review (Schneier) from the .md case file, parsed live
 *
 * Adjacent action panel: "Red-team this hypothesis" → POST to chat or
 * direct enqueue to investigation_jobs.
 */
import { notFound } from "next/navigation";
import Link from "next/link";
import { readFile } from "node:fs/promises";
import path from "node:path";
import { pgQuery } from "@/lib/retrieval/db";
import { AuthBar } from "@/components/auth-bar";
import { BureauNav } from "@/components/bureau-nav";
import { RedTeamRequestButton } from "@/components/red-team-request-button";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";

interface HypothesisRow {
  hypothesis_id: string;
  question: string;
  question_pt_br: string | null;
  position: string;
  position_pt_br: string | null;
  argument_for: string | null;
  argument_for_pt_br: string | null;
  argument_against: string | null;
  argument_against_pt_br: string | null;
  prior: number | string | null;
  posterior: number | string | null;
  confidence_band: string | null;
  status: string;
  evidence_refs: unknown;
  created_by: string;
  reviewed_by: string | null;
  created_at: string;
  updated_at: string;
}

interface EvidenceRow {
  evidence_id: string;
  grade: string;
  source_page_id: string;
  doc_id: string | null;
  page: number | null;
  chunk_id: string | null;
  verbatim_excerpt: string | null;
  confidence_band: string | null;
}

const BAND_COLOR: Record<string, string> = {
  high: "text-[#06d6a0] border-[#06d6a0]",
  medium: "text-[#3fde6a] border-[#3fde6a]",
  low: "text-[#ffa500] border-[#ffa500]",
  speculation: "text-[#ff6ec7] border-[#ff6ec7]",
};

const GRADE_COLOR: Record<string, string> = {
  A: "text-[#06d6a0] border-[#06d6a0]",
  B: "text-[#3fde6a] border-[#3fde6a]",
  C: "text-[#ffa500] border-[#ffa500]",
};

const SEVERITY_COLOR: Record<string, string> = {
  high: "text-[#ff3344] border-[#ff3344]",
  medium: "text-[#ff8a4d] border-[#ff8a4d]",
  low: "text-[#9aa6b8] border-[#9aa6b8]",
};

function asNumber(n: number | string | null): number | null {
  if (n === null || n === undefined) return null;
  const v = typeof n === "string" ? parseFloat(n) : n;
  return Number.isFinite(v) ? v : null;
}

const CASE_ROOT = process.env.CASE_ROOT || "/data/ufo/case";

interface ParsedRedTeam {
  severity: "low" | "medium" | "high" | null;
  reviewer: string | null;
  reviewed_at: string | null;
  job_id: string | null;
  verdict: string | null;
  hidden_assumptions: string[];
  failure_modes: string[];
  alternative_explanations: string[];
  recommended_tests: string[];
}

/**
 * Parse the "## Red-team review (Schneier · X severity)" section from a
 * hypothesis case file. The section is structured (we wrote it ourselves
 * in write_red_team_review.ts), so we can extract with light regex.
 */
function parseRedTeam(md: string): ParsedRedTeam | null {
  const header = md.match(/##\s+Red-team review\s+\(([^)\n]+)\)/i);
  if (!header) return null;
  const meta = header[1];
  const severityMatch = meta.match(/\b(low|medium|high)\b\s+severity/i);
  const severity = severityMatch ? (severityMatch[1].toLowerCase() as "low" | "medium" | "high") : null;

  const section = md.slice(header.index ?? 0);

  // _Reviewed by X on Y — job `Z`._
  const review = section.match(/Reviewed by\s+([^\n]+?)\s+on\s+([^\n—]+?)\s*—\s*job\s+`([^`]+)`/);
  const reviewer = review?.[1]?.trim() ?? null;
  const reviewedAt = review?.[2]?.trim() ?? null;
  const jobId = review?.[3]?.trim() ?? null;

  const verdictMatch = section.match(/\*\*Verdict\.\*\*\s+([^\n]+)/);
  const verdict = verdictMatch?.[1]?.trim() ?? null;

  function pickSection(name: string): string[] {
    const re = new RegExp(`###\\s+${name}([\\s\\S]+?)(?=\\n###|\\n##|$)`, "i");
    const m = section.match(re);
    if (!m) return [];
    const body = m[1];
    if (/_\(none flagged\)_/i.test(body)) return [];
    return body
      .split("\n")
      .map((l) => l.trim())
      .filter((l) => l.startsWith("- "))
      .map((l) => l.slice(2).trim())
      .filter((l) => l.length > 0);
  }

  return {
    severity,
    reviewer,
    reviewed_at: reviewedAt,
    job_id: jobId,
    verdict,
    hidden_assumptions: pickSection("Hidden assumptions"),
    failure_modes: pickSection("Failure modes"),
    alternative_explanations: pickSection("Alternative explanations not addressed"),
    recommended_tests: pickSection("Recommended discriminating tests"),
  };
}

export default async function HypothesisPage({
  params,
}: { params: Promise<{ hypothesisId: string }> }) {
  const { hypothesisId } = await params;
  if (!/^H-\d{4}$/.test(hypothesisId)) notFound();

  const rows = await pgQuery<HypothesisRow>(
    `SELECT hypothesis_id, question, question_pt_br, position, position_pt_br,
            argument_for, argument_for_pt_br, argument_against, argument_against_pt_br,
            prior, posterior, confidence_band, status, evidence_refs,
            created_by, reviewed_by, created_at, updated_at
       FROM public.hypotheses WHERE hypothesis_id = $1`,
    [hypothesisId],
  ).catch(() => [] as HypothesisRow[]);
  const h = rows[0];
  if (!h) notFound();

  const refIds: string[] = [];
  if (Array.isArray(h.evidence_refs)) {
    for (const r of h.evidence_refs as Array<Record<string, unknown>>) {
      if (typeof r?.evidence_id === "string") refIds.push(r.evidence_id);
    }
  }
  const evidence: EvidenceRow[] = refIds.length > 0
    ? await pgQuery<EvidenceRow>(
        `SELECT e.evidence_id, e.grade, e.source_page_id,
                split_part(e.source_page_id, '/p', 1)                  AS doc_id,
                NULLIF(split_part(e.source_page_id, '/p', 2), '')::int AS page,
                c.chunk_id, e.verbatim_excerpt, e.confidence_band
           FROM public.evidence e
      LEFT JOIN public.chunks c ON c.chunk_pk = e.source_chunk_pk
          WHERE e.evidence_id = ANY($1::text[])
          ORDER BY e.evidence_id`,
        [refIds],
      ).catch(() => [] as EvidenceRow[])
    : [];

  let redTeam: ParsedRedTeam | null = null;
  try {
    const file = path.join(CASE_ROOT, "hypotheses", `${hypothesisId}.md`);
    const md = await readFile(file, "utf-8");
    redTeam = parseRedTeam(md);
  } catch {
    redTeam = null;
  }

  const prior = asNumber(h.prior);
  const posterior = asNumber(h.posterior);
  const delta = prior !== null && posterior !== null ? posterior - prior : null;
  const bandTone = (h.confidence_band && BAND_COLOR[h.confidence_band]) || "text-[#9aa6b8] border-[#9aa6b8]";

  return (
    <div className="min-h-screen bg-[#0a0e1a] text-[#e7ecf3]">
      <BureauNav crumbs={[
        { label: "bureau", href: "/bureau" },
        { label: "hypotheses", href: "/bureau#hypotheses" },
        { label: hypothesisId },
      ]} />
      <AuthBar />
      <div className="mx-auto max-w-5xl px-4 py-6 pt-4">

        {/* Header */}
        <div className="rounded-lg border border-[rgba(127,219,255,0.18)] bg-gradient-to-br from-[rgba(127,219,255,0.08)] to-transparent p-5">
          <div className="flex items-baseline justify-between gap-4 flex-wrap">
            <div>
              <div className="text-[10px] font-mono text-[#5a6678] uppercase mb-1">
                {hypothesisId} · created by {h.created_by}
                {h.reviewed_by && <> · reviewed by <span className="text-[#ff3344]">{h.reviewed_by}</span></>}
              </div>
              <h1 className="text-xl font-mono text-[#e7ecf3] leading-snug">{h.position_pt_br || h.position}</h1>
              {h.position_pt_br && h.position_pt_br !== h.position && (
                <p className="text-[12px] text-[#5a6678] italic mt-0.5">{h.position}</p>
              )}
              <p className="text-[12px] text-[#9aa6b8] mt-1">Pergunta: {h.question_pt_br || h.question}</p>
            </div>
            {h.confidence_band && (
              <span className={`px-2 py-0.5 rounded text-[10px] font-mono uppercase border ${bandTone}`}>
                {h.confidence_band}
              </span>
            )}
          </div>

          {/* Probability bars */}
          {(prior !== null || posterior !== null) && (
            <div className="mt-4 grid grid-cols-2 gap-3 text-[11px] font-mono">
              <Bar label="prior" value={prior} color="#5a6678" />
              <Bar label="posterior" value={posterior} color="#7fdbff" />
            </div>
          )}
          {delta !== null && (
            <div className="mt-2 text-[10px] font-mono text-[#5a6678]">
              Δ {delta >= 0 ? "+" : ""}{delta.toFixed(3)} ·{" "}
              {delta > 0.05 ? <span className="text-[#06d6a0]">evidência reforçou</span> :
               delta < -0.05 ? <span className="text-[#ff6ec7]">evidência reduziu</span> :
               <span className="text-[#9aa6b8]">evidência ambígua</span>}
            </div>
          )}
        </div>

        {/* Argument grid */}
        <div className="mt-4 grid md:grid-cols-2 gap-3">
          <ArgumentPanel kind="for" body={h.argument_for_pt_br || h.argument_for} bodyEn={h.argument_for_pt_br ? h.argument_for : null} />
          <ArgumentPanel kind="against" body={h.argument_against_pt_br || h.argument_against} bodyEn={h.argument_against_pt_br ? h.argument_against : null} />
        </div>

        {/* Evidence chain */}
        {evidence.length > 0 && (
          <div className="mt-6">
            <div className="text-[12px] font-mono text-[#06d6a0] uppercase tracking-wider mb-2">
              Cadeia de evidência ({evidence.length})
            </div>
            <div className="space-y-3">
              {evidence.map((e) => <EvidenceMini key={e.evidence_id} e={e} />)}
            </div>
          </div>
        )}

        {/* Red-team review */}
        <div className="mt-6">
          <div className="flex items-baseline justify-between mb-2 flex-wrap gap-2">
            <div className="text-[12px] font-mono text-[#ff3344] uppercase tracking-wider">
              Revisão Red Team (Schneier)
            </div>
            <RedTeamRequestButton hypothesisId={hypothesisId} alreadyReviewed={Boolean(redTeam)} />
          </div>
          {redTeam ? <RedTeamPanel rt={redTeam} /> : (
            <div className="rounded-lg border border-dashed border-[rgba(255,51,68,0.18)] bg-[#0d1220] p-4 text-[12px] font-mono text-[#9aa6b8]">
              Nenhuma revisão red-team ainda. Click acima para acionar Schneier.
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function ArgumentPanel({ kind, body, bodyEn }: { kind: "for" | "against"; body: string | null; bodyEn?: string | null }) {
  const tone = kind === "for" ? "border-[#06d6a0] text-[#06d6a0]" : "border-[#ff6ec7] text-[#ff6ec7]";
  const label = kind === "for" ? "Argumento a favor (PT-BR)" : "Argumento contra (PT-BR)";
  const enLabel = kind === "for" ? "Argument for (EN)" : "Argument against (EN)";
  return (
    <div className={`rounded-lg border ${tone} bg-[#0d1220] p-4`}>
      <div className={`text-[10px] font-mono uppercase mb-2 ${tone}`}>{label}</div>
      <ArgumentBody text={body ?? ""} />
      {bodyEn && (
        <details className="mt-3 pt-3 border-t border-[rgba(127,219,255,0.08)]">
          <summary className="text-[10px] font-mono text-[#5a6678] cursor-pointer hover:text-[#9aa6b8]">{enLabel}</summary>
          <div className="mt-2"><ArgumentBody text={bodyEn} /></div>
        </details>
      )}
    </div>
  );
}

function EvidenceMini({ e }: { e: EvidenceRow }) {
  const gradeTone = (e.grade && GRADE_COLOR[e.grade]) || "text-[#9aa6b8] border-[#9aa6b8]";
  const bandTone = (e.confidence_band && BAND_COLOR[e.confidence_band]) || "text-[#9aa6b8] border-[#9aa6b8]";
  return (
    <div className="rounded-lg border border-[rgba(6,214,160,0.18)] bg-[#0d1220] p-3">
      <div className="flex items-baseline justify-between gap-2 mb-1">
        <div className="text-[10px] font-mono text-[#5a6678] uppercase">{e.evidence_id}</div>
        <div className="flex items-center gap-2">
          {e.grade && (
            <span className={`px-2 py-0.5 rounded text-[10px] font-mono uppercase border ${gradeTone}`}>
              Grade {e.grade}
            </span>
          )}
          {e.confidence_band && (
            <span className={`px-2 py-0.5 rounded text-[10px] font-mono uppercase border ${bandTone}`}>
              {e.confidence_band}
            </span>
          )}
        </div>
      </div>
      {e.verbatim_excerpt && (
        <blockquote className="text-[12px] text-[#e7ecf3] italic border-l-2 border-[#06d6a0] pl-2 my-1">
          “{e.verbatim_excerpt.slice(0, 360)}”
        </blockquote>
      )}
      {e.doc_id && e.page && (
        <Link
          href={`/d/${e.doc_id}/p${String(e.page).padStart(3, "0")}${e.chunk_id ? `#${e.chunk_id}` : ""}`}
          className="text-[10px] font-mono text-[#7fdbff] hover:underline"
        >
          {e.doc_id}/p{String(e.page).padStart(3, "0")}{e.chunk_id ? `#${e.chunk_id}` : ""}
        </Link>
      )}
    </div>
  );
}

function RedTeamPanel({ rt }: { rt: ParsedRedTeam }) {
  const tone = (rt.severity && SEVERITY_COLOR[rt.severity]) || "text-[#9aa6b8] border-[#9aa6b8]";
  return (
    <div className="rounded-lg border border-[rgba(255,51,68,0.18)] bg-[#0d1220] p-4 space-y-3">
      <div className="flex items-baseline justify-between gap-2 flex-wrap">
        <div className="text-[10px] font-mono text-[#5a6678]">
          {rt.reviewer ?? "—"}{rt.reviewed_at ? ` · ${rt.reviewed_at}` : ""}{rt.job_id ? ` · job ${rt.job_id.slice(0, 8)}…` : ""}
        </div>
        {rt.severity && (
          <span className={`px-2 py-0.5 rounded text-[10px] font-mono uppercase border ${tone}`}>
            {rt.severity} severity
          </span>
        )}
      </div>
      {rt.verdict && (
        <blockquote className="text-[14px] text-[#e7ecf3] italic border-l-2 border-[#ff3344] pl-3">
          {rt.verdict}
        </blockquote>
      )}
      <div className="grid md:grid-cols-2 gap-3">
        <BulletPanel title="Hidden assumptions" items={rt.hidden_assumptions} color="text-[#ff8a4d]" />
        <BulletPanel title="Failure modes" items={rt.failure_modes} color="text-[#ff3344]" />
        <BulletPanel title="Alternative explanations" items={rt.alternative_explanations} color="text-[#ff6ec7]" />
        <BulletPanel title="Recommended tests" items={rt.recommended_tests} color="text-[#7fdbff]" />
      </div>
    </div>
  );
}

function BulletPanel({ title, items, color }: { title: string; items: string[]; color: string }) {
  return (
    <div className="rounded border border-[rgba(255,51,68,0.1)] bg-[#060a13] p-3">
      <div className={`text-[10px] font-mono uppercase mb-1 ${color}`}>{title}</div>
      {items.length === 0 ? (
        <div className="text-[11px] font-mono text-[#5a6678]">_(none flagged)_</div>
      ) : (
        <ul className="text-[11px] text-[#cbd2dd] leading-relaxed list-disc pl-4 space-y-1">
          {items.map((x, i) => <li key={i}>{x}</li>)}
        </ul>
      )}
    </div>
  );
}

function Bar({ label, value, color }: { label: string; value: number | null; color: string }) {
  const pct = value !== null ? Math.round(value * 100) : 0;
  return (
    <div>
      <div className="flex items-center justify-between mb-1">
        <span className="text-[#5a6678]">{label}</span>
        <span className="text-[#e7ecf3]">{value !== null ? value.toFixed(3) : "—"}</span>
      </div>
      <div className="h-1.5 bg-[rgba(127,219,255,0.08)] rounded-full overflow-hidden">
        <div className="h-full rounded-full" style={{ width: `${pct}%`, background: color }} />
      </div>
    </div>
  );
}

function ArgumentBody({ text }: { text: string }) {
  if (!text.trim()) return <p className="text-[12px] text-[#5a6678]">_(none recorded)_</p>;
  const parts: Array<{ kind: "text" | "link"; raw: string; href?: string; label?: string }> = [];
  const re = /\[\[([^\]|]+?)(?:\|([^\]]+))?\]\]/g;
  let lastIdx = 0;
  let m: RegExpExecArray | null;
  while ((m = re.exec(text)) !== null) {
    if (m.index > lastIdx) parts.push({ kind: "text", raw: text.slice(lastIdx, m.index) });
    const target = m[1];
    const label = m[2] ?? m[1];
    let href: string | undefined;
    const chunkMatch = target.match(/^([a-z0-9][a-z0-9-]*)\/p(\d{3})#(c\d{4})$/);
    const pageMatch = target.match(/^([a-z0-9][a-z0-9-]*)\/p(\d{3})$/);
    if (chunkMatch) href = `/d/${chunkMatch[1]}/p${chunkMatch[2]}#${chunkMatch[3]}`;
    else if (pageMatch) href = `/d/${pageMatch[1]}/p${pageMatch[2]}`;
    parts.push({ kind: "link", raw: m[0], href, label });
    lastIdx = m.index + m[0].length;
  }
  if (lastIdx < text.length) parts.push({ kind: "text", raw: text.slice(lastIdx) });
  return (
    <div className="text-[13px] text-[#cbd2dd] leading-relaxed whitespace-pre-wrap">
      {parts.map((p, i) =>
        p.kind === "text" ? <span key={i}>{p.raw}</span> :
        p.href ? <Link key={i} href={p.href} className="text-[#7fdbff] hover:underline">{p.label}</Link> :
        <span key={i} className="text-[#5a6678]">{p.label}</span>
      )}
    </div>
  );
}
