// Case detail view — drill-down into a single alert/case.

const { useState: useStateC, useEffect: useEffectC, useMemo: useMemoC } = React;

// ── Network graph ───────────────────────────────────────────────────────────
function formatNetworkLabel(id) {
  if (!id) return "—";
  if (id.length > 12) return id.slice(0, 6) + "…" + id.slice(-4);
  return id;
}

function NetworkGraph({ network }) {
  // SVG-rendered entity relationship graph
  const W = 720, H = 420;
  const { nodes: rawNodes = [], edges: rawEdges = [] } = network || {};

  const cx = W / 2;
  const cy = H / 2;

  const placedNodes = useMemoC(() => {
    const subject = rawNodes.find(n => n.kind === "subject");
    const others = rawNodes.filter(n => n.kind !== "subject");
    const nodes = [];
    if (subject) {
      nodes.push({ ...subject, x: cx, y: cy, r: subject.r || 28 });
    }
    const count = others.length || 1;
    // Scale radius by number of nodes so labels don't overlap
    const baseRadius = Math.min(W, H) / 2 - 100;
    const radius = Math.max(baseRadius, 140 + count * 10);
    others.forEach((n, i) => {
      const angle = (2 * Math.PI * i) / count - Math.PI / 2;
      nodes.push({
        ...n,
        x: cx + radius * Math.cos(angle),
        y: cy + radius * Math.sin(angle),
        r: n.r || 18,
      });
    });
    return nodes;
  }, [rawNodes]);

  const N = Object.fromEntries(placedNodes.map(n => [n.id, n]));
  const colorFor = (k) => ({
    subject: "var(--fg)",
    counterparty: "var(--fg-2)",
    high:    "var(--risk-high)",
    low:     "var(--risk-low)",
    cash:    "var(--risk-med)",
    link:    "var(--info)",
    normal:  "var(--fg-3)",
    neutral: "var(--fg-3)",
  }[k] || "var(--fg-3)");

  if (!rawNodes.length) {
    return (
      <div style={{ height: 420, display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fg-3)", fontSize: 12 }}>
        No network data available for this alert.
      </div>
    );
  }

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={H}
         style={{ display: "block" }}>
      {/* Grid */}
      <defs>
        <pattern id="grid" width="24" height="24" patternUnits="userSpaceOnUse">
          <circle cx="0.5" cy="0.5" r="0.5" fill="var(--border)" />
        </pattern>
        <marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto-start-reverse">
          <path d="M0 0 L10 5 L0 10 z" fill="var(--fg-3)" />
        </marker>
        <marker id="arr-high" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto-start-reverse">
          <path d="M0 0 L10 5 L0 10 z" fill="var(--risk-high)" />
        </marker>
      </defs>
      <rect width={W} height={H} fill="url(#grid)" opacity="0.6" />

      {/* Edges */}
      {rawEdges.map((e, i) => {
        const a = N[e.from], b = N[e.to];
        if (!a || !b) return null;
        const dx = b.x - a.x, dy = b.y - a.y;
        const len = Math.hypot(dx, dy) || 1;
        const ux = dx / len, uy = dy / len;
        const x1 = a.x + ux * a.r, y1 = a.y + uy * a.r;
        const x2 = b.x - ux * b.r, y2 = b.y - uy * b.r;
        const stroke = e.kind === "high" ? "var(--risk-high)" : "var(--fg-3)";
        const weight = Math.max(1.5, Math.min(5, Math.log10((e.amount || 1) + 1)));
        const mid = { x: (x1 + x2) / 2, y: (y1 + y2) / 2 };
        return (
          <g key={i} opacity={e.kind === "high" ? 0.95 : 0.55}>
            <line x1={x1} y1={y1} x2={x2} y2={y2}
                  stroke={stroke}
                  strokeWidth={weight}
                  markerEnd={e.kind === "high" ? "url(#arr-high)" : "url(#arr)"} />
            {e.label && (e.kind === "high" || rawNodes.length <= 8) && (
              <g>
                <rect x={mid.x - e.label.length * 2.8} y={mid.y - 8}
                      width={e.label.length * 5.6} height={14}
                      fill="var(--bg)" rx="3" />
                <text x={mid.x} y={mid.y + 2.5}
                      fontSize="10" fontFamily="var(--font-mono)"
                      fill={e.kind === "high" ? "var(--risk-high)" : "var(--fg-2)"}
                      textAnchor="middle">{e.label}</text>
              </g>
            )}
          </g>
        );
      })}

      {/* Nodes */}
      {placedNodes.map(n => {
        const c = colorFor(n.kind);
        const isSubj = n.kind === "subject";
        const label = formatNetworkLabel(n.label);
        const sub = n.sub || "";
        return (
          <g key={n.id}>
            <circle cx={n.x} cy={n.y} r={n.r + 6}
                    fill={isSubj ? "var(--bg)" : "transparent"}
                    stroke={c} strokeOpacity="0.15" strokeWidth="0.5" />
            <circle cx={n.x} cy={n.y} r={n.r}
                    fill={isSubj ? c : "var(--bg)"}
                    stroke={c} strokeWidth={isSubj ? 0 : 1.5} />
            {isSubj && (
              <text x={n.x} y={n.y + 4} fontSize="10" fontFamily="var(--font-mono)"
                    fill="var(--bg)" textAnchor="middle" fontWeight="600">S</text>
            )}
            {!isSubj && (
              <text x={n.x} y={n.y + 4} fontSize="10" fontFamily="var(--font-mono)"
                    fill={c} textAnchor="middle" fontWeight="600">CP</text>
            )}
            <text x={n.x} y={n.y + n.r + 12}
                  fontSize="10.5" fontFamily="var(--font-sans)"
                  fill="var(--fg)" textAnchor="middle" fontWeight={isSubj ? 600 : 500}>
              {label}
            </text>
            <text x={n.x} y={n.y + n.r + 23}
                  fontSize="9" fontFamily="var(--font-mono)"
                  fill="var(--fg-3)" textAnchor="middle">
              {sub}
            </text>
          </g>
        );
      })}
    </svg>
  );
}

// ── Timeline / activity histogram ───────────────────────────────────────────
function VolumeHistogram() {
  // Daily volume across 30 days, with structuring spike highlighted
  const data = [
    2,3,2,4,3,5,4,3,4,6,5,4,7,6,5,4,6,8,7,5,4,6,8,9,7,6,9,11,9, 18, // last day = spike
  ];
  const max = Math.max(...data);
  const W = 720, H = 96;
  const bw = (W - 20) / data.length;
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={H}>
      <line x1="10" y1={H - 16} x2={W - 10} y2={H - 16} stroke="var(--border)" />
      {data.map((v, i) => {
        const h = (v / max) * (H - 24);
        const x = 10 + i * bw + 1;
        const isLast = i === data.length - 1;
        const isHigh = v > 12;
        return (
          <g key={i}>
            <rect x={x} y={H - 16 - h} width={bw - 2} height={h}
                  fill={isHigh ? "var(--risk-high)" : "var(--fg-2)"}
                  opacity={isLast ? 1 : 0.55} rx="1" />
            {isLast && (
              <text x={x + bw / 2} y={H - 16 - h - 6}
                    fontSize="10" fontFamily="var(--font-mono)"
                    fill="var(--risk-high)" textAnchor="middle" fontWeight="600">{v}</text>
            )}
          </g>
        );
      })}
      <text x="10" y={H - 4} fontSize="10" fontFamily="var(--font-mono)" fill="var(--fg-3)">Apr 15</text>
      <text x={W / 2} y={H - 4} fontSize="10" fontFamily="var(--font-mono)" fill="var(--fg-3)" textAnchor="middle">Apr 30</text>
      <text x={W - 10} y={H - 4} fontSize="10" fontFamily="var(--font-mono)" fill="var(--fg-3)" textAnchor="end">May 14</text>
    </svg>
  );
}

// ── Score breakdown ─────────────────────────────────────────────────────────
function ScoreBreakdown({ score }) {
  const items = [
    { label: "Volume",   value: score.volume,   note: "deposit count + sum" },
    { label: "Velocity", value: score.velocity, note: "txns / 48h window" },
    { label: "Geographic", value: score.geo,    note: "corridor risk" },
    { label: "Peer group", value: score.peer,   note: "vs. similar SMB" },
  ];
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
      {items.map(it => (
        <div key={it.label}>
          <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 4 }}>
            <span style={{ fontSize: 12 }}>{it.label}
              <span className="muted" style={{ marginLeft: 6, fontSize: 11 }}>{it.note}</span>
            </span>
            <span className="mono" style={{ fontWeight: 500, color: riskColor(it.value) }}>{it.value}</span>
          </div>
          <div style={{ height: 3, background: "var(--bg-3)", borderRadius: 2, overflow: "hidden" }}>
            <div style={{ width: `${it.value}%`, height: "100%", background: riskColor(it.value) }} />
          </div>
        </div>
      ))}
    </div>
  );
}

// ── Transaction table for the case ──────────────────────────────────────────
function formatTxnChannel(type) {
  const map = { wire: "Wire", ach: "ACH", card: "Card", atm: "ATM", crypto: "Crypto", cash: "Cash" };
  return map[type] || (type || "").replace(/_/g, " ").replace(/\b\w/g, c => c.toUpperCase());
}

function formatDate(ts) {
  if (!ts) return "—";
  const d = new Date(ts);
  return d.toLocaleDateString() + " " + d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
}

function CaseTxnTable({ transactions, primaryId, loading }) {
  if (loading) {
    return <div style={{ padding: 24, textAlign: "center", color: "var(--fg-3)", fontSize: 12 }}>Loading transactions…</div>;
  }
  if (!transactions || transactions.length === 0) {
    return <div style={{ padding: 24, textAlign: "center", color: "var(--fg-3)", fontSize: 12 }}>No transactions found.</div>;
  }

  return (
    <table className="tbl">
      <thead>
        <tr>
          <th style={{ width: 28 }}></th>
          <th style={{ width: 120 }}>Txn ID</th>
          <th style={{ width: 150 }}>Timestamp</th>
          <th style={{ width: 50 }}>Dir</th>
          <th>Counterparty</th>
          <th style={{ width: 120 }}>Account</th>
          <th className="right" style={{ width: 120 }}>Amount</th>
          <th style={{ width: 80 }}>Channel</th>
        </tr>
      </thead>
      <tbody>
        {transactions.map(t => {
          const subjectId = primaryId || t.originator_id;
          const isOut = t.originator_id === subjectId;
          const cpId = isOut ? t.beneficiary_id : t.originator_id;
          const cpType = isOut ? t.beneficiary_type : t.originator_type;
          const account = isOut ? (t.originator_account || "—") : (t.beneficiary_account || "—");
          const isPrimary = primaryId ? t.id === primaryId : false;
          return (
            <tr key={t.id} className={isPrimary ? "flagged" : ""}>
              <td>{isPrimary && <Icon.Flag size={11} style={{ color: "var(--risk-high)" }} title="Primary triggering transaction" />}</td>
              <td><span className="mono" style={{ fontSize: 11.5 }}>{t.external_id || t.id.slice(0, 8)}</span></td>
              <td><span className="mono" style={{ fontSize: 11.5, color: "var(--fg-2)" }}>{formatDate(t.timestamp)}</span></td>
              <td>
                <span style={{
                  display: "inline-flex", alignItems: "center", gap: 3,
                  color: isOut ? "var(--risk-med)" : "var(--risk-low)",
                  fontSize: 11.5, fontWeight: 500,
                }}>
                  {isOut ? <Icon.ArrowUp size={10} /> : <Icon.ArrowDn size={10} />}
                  {isOut ? "OUT" : "IN"}
                </span>
              </td>
              <td>
                <span className="mono">{cpId}</span>
                {cpType && <span className="muted" style={{ marginLeft: 6, fontSize: 11 }}>({cpType})</span>}
              </td>
              <td className="mono muted" style={{ fontSize: 11.5 }}>{account}</td>
              <td className="right mono" style={{ fontWeight: 500 }}>
                ${Number(t.amount || 0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
                <span className="muted" style={{ fontSize: 10.5, marginLeft: 3 }}>{t.currency || "USD"}</span>
              </td>
              <td><span className="pill outline">{formatTxnChannel(t.transaction_type)}</span></td>
            </tr>
          );
        })}
      </tbody>
    </table>
  );
}

// ── Simulation / backtesting panel ──────────────────────────────────────────
// ── Timeline / activity feed ────────────────────────────────────────────────
function ActivityFeed() {
  const ico = {
    alert:   <Icon.Bell size={10} />,
    assign:  <Icon.Person size={10} />,
    view:    <Icon.Eye size={10} />,
    note:    <Icon.Note size={10} />,
    request: <Icon.Bolt size={10} />,
    link:    <Icon.Link size={10} />,
    edit:    <Icon.Flag size={10} />,
  };
  const bg = {
    alert:   "var(--risk-high-bg)",
    note:    "var(--accent-tint)",
    link:    "var(--info-bg)",
  };
  const fg = {
    alert:   "var(--risk-high)",
    note:    "var(--accent)",
    link:    "var(--info)",
  };
  return (
    <div style={{ position: "relative", paddingLeft: 26 }}>
      <div style={{
        position: "absolute", left: 9, top: 8, bottom: 8,
        width: 1, background: "var(--border)",
      }} />
      {CASE_TIMELINE.slice().reverse().map((e, i) => (
        <div key={i} style={{ display: "flex", marginBottom: 14, position: "relative" }}>
          <div style={{
            position: "absolute", left: -26,
            width: 18, height: 18, borderRadius: "50%",
            background: bg[e.kind] || "var(--bg-3)",
            color: fg[e.kind] || "var(--fg-2)",
            display: "grid", placeItems: "center",
            border: "1px solid var(--bg)",
          }}>
            {ico[e.kind]}
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ display: "flex", alignItems: "baseline", gap: 8, marginBottom: 1 }}>
              <span style={{ fontWeight: 500, fontSize: 12.5 }}>{e.who}</span>
              <span className="mono" style={{ fontSize: 10.5, color: "var(--fg-3)" }}>{e.ts}</span>
            </div>
            <div style={{ fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5 }}>{e.text}</div>
          </div>
        </div>
      ))}
    </div>
  );
}

// ── Decisioning rail ────────────────────────────────────────────────────────
function DecisionRail({ alert, onClose, onRefresh }) {
  const [note, setNote] = useStateC("");
  const [posting, setPosting] = useStateC(false);
  const [dismissing, setDismissing] = useStateC(false);
  const [creatingCase, setCreatingCase] = useStateC(false);
  const [message, setMessage] = useStateC(null);

  const createCase = async () => {
    setCreatingCase(true);
    setMessage(null);
    try {
      const result = await window.mossadApi.convertAlertToCase(alert._raw?.id || alert.id);
      setMessage({ type: "ok", text: `Case created · ${result.external_id || result.case_id}` });
      if (onRefresh) await onRefresh();
    } catch (err) {
      setMessage({ type: "error", text: "Failed to create case: " + err.message });
    } finally {
      setCreatingCase(false);
    }
  };

  const postNote = async () => {
    if (!note.trim()) return;
    setPosting(true);
    setMessage(null);
    try {
      await window.mossadApi.addAlertNote(alert._raw?.id || alert.id, note.trim());
      setNote("");
      setMessage({ type: "ok", text: "Note posted" });
      if (onRefresh) await onRefresh();
    } catch (err) {
      setMessage({ type: "error", text: "Failed to post note: " + err.message });
    } finally {
      setPosting(false);
    }
  };

  const dismiss = async (resolution) => {
    setDismissing(true);
    setMessage(null);
    try {
      await window.mossadApi.updateAlert(alert._raw?.id || alert.id, {
        status: "dismissed",
        resolution,
        resolution_note: note.trim() || resolution,
      });
      setMessage({ type: "ok", text: `Alert dismissed · ${resolution.replace(/_/g, " ")}` });
      if (onRefresh) await onRefresh();
      if (onClose) onClose();
    } catch (err) {
      setMessage({ type: "error", text: "Failed to dismiss alert: " + err.message });
    } finally {
      setDismissing(false);
    }
  };

  const notes = alert._raw?.notes || alert.notes || [];

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
      <div style={{ padding: "16px 18px", borderBottom: "1px solid var(--border)" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }}>
          <span className="kpi-label" style={{ margin: 0 }}>Decision</span>
          <span style={{ flex: 1 }} />
          {(() => {
            const sev = alert.severity === "medium" ? "med" : alert.severity || "low";
            return (
              <span className={`pill ${sev}`}>
                <span className={`dot dot-${sev}`} style={{ margin: "0 4px 0 0" }} />
                <span>{alert.status?.toUpperCase() || "OPEN"} · {alert.sla || "—"} SLA</span>
              </span>
            );
          })()}
        </div>
        {message && (
          <div style={{
            fontSize: 12, marginBottom: 10,
            color: message.type === "ok" ? "var(--risk-low)" : "var(--risk-high)",
            background: message.type === "ok" ? "var(--risk-low-bg)" : "var(--risk-high-bg)",
            padding: "6px 8px", borderRadius: 4,
          }}>
            {message.text}
          </div>
        )}
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 6 }}>
          <button className="btn success" onClick={() => dismiss("false_positive")} disabled={dismissing || alert.status === "dismissed"}>
            <Icon.Check size={12} /> {alert.status === "dismissed" ? "Dismissed" : "Clear · false positive"}
          </button>
          <button className="btn danger" onClick={() => dismiss("escalated")} disabled={dismissing || alert.status === "dismissed"}>
            <Icon.Flag size={12} /> Escalate to L3
          </button>
          <button className="btn" disabled><Icon.Note size={12} /> Request KYC</button>
          <button className="btn primary" onClick={createCase} disabled={creatingCase || alert.status === "converted"}>
            <Icon.Folder size={12} /> {creatingCase ? "Creating…" : alert.status === "converted" ? "Converted" : "Create case"}
          </button>
        </div>

      </div>

      <div style={{ padding: "14px 18px", borderBottom: "1px solid var(--border)" }}>
        <span className="kpi-label" style={{ marginBottom: 8 }}>Add note</span>
        <textarea value={note} onChange={e => setNote(e.target.value)}
                  placeholder="Findings, evidence, reasoning…"
                  style={{
                    width: "100%", minHeight: 60,
                    border: "1px solid var(--border)",
                    background: "var(--bg-2)",
                    color: "var(--fg)",
                    borderRadius: 6,
                    padding: 8,
                    font: "inherit", fontSize: 12.5,
                    resize: "vertical", outline: "none",
                  }} />
        <div style={{ display: "flex", gap: 6, marginTop: 6 }}>
          <span style={{ flex: 1 }} />
          <button className="btn sm primary" onClick={postNote} disabled={posting || !note.trim()}>
            {posting ? "Posting…" : "Post note"}
          </button>
        </div>
      </div>

      <div style={{ padding: "14px 18px", flex: 1, overflow: "auto" }}>
        <div style={{ display: "flex", alignItems: "center", marginBottom: 12 }}>
          <span className="kpi-label" style={{ margin: 0 }}>Activity</span>
          <span style={{ flex: 1 }} />
          <span className="mono" style={{ fontSize: 11, color: "var(--fg-3)" }}>{notes.length + CASE_TIMELINE.length} events</span>
        </div>
        {notes.length > 0 && (
          <div style={{ marginBottom: 16 }}>
            {notes.slice().reverse().map((n, i) => (
              <div key={i} style={{ display: "flex", gap: 10, marginBottom: 12, padding: 10, background: "var(--bg-2)", borderRadius: 6 }}>
                <div style={{ width: 18, height: 18, borderRadius: "50%", background: "var(--accent-tint)", color: "var(--accent)", display: "grid", placeItems: "center" }}>
                  <Icon.Note size={10} />
                </div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5 }}>{n.content}</div>
                  <div className="mono" style={{ fontSize: 10, color: "var(--fg-3)", marginTop: 4 }}>
                    {n.created_by_name || "Unknown"} · {new Date(n.created_at).toLocaleString()}
                  </div>
                </div>
              </div>
            ))}
          </div>
        )}
        <ActivityFeed />
      </div>
    </div>
  );
}

// ── Case detail composition ─────────────────────────────────────────────────
function CaseDetailView({ alert, onClose, data, backLabel = "Back to queue" }) {
  const [tab, setTab] = useStateC("overview");
  const [network, setNetwork] = useStateC(null);
  const [networkLoading, setNetworkLoading] = useStateC(false);
  const [txns, setTxns] = useStateC([]);
  const [txnsLoading, setTxnsLoading] = useStateC(false);

  useEffectC(() => {
    let cancelled = false;
    const load = async () => {
      if (!alert?.id || !window.mossadApi) return;
      setNetworkLoading(true);
      try {
        const n = await window.mossadApi.fetchAlertNetwork(alert.id);
        if (!cancelled) setNetwork(n);
      } catch (err) {
        console.error("Failed to load alert network:", err);
      } finally {
        if (!cancelled) setNetworkLoading(false);
      }
    };
    load();
    return () => { cancelled = true; };
  }, [alert?.id]);

  useEffectC(() => {
    let cancelled = false;
    const load = async () => {
      if (!alert?.id || !window.mossadApi) return;
      setTxnsLoading(true);
      try {
        const list = await window.mossadApi.fetchAlertTransactions(alert.id);
        if (!cancelled) setTxns(list || []);
      } catch (err) {
        console.error("Failed to load alert transactions:", err);
        if (!cancelled) setTxns([]);
      } finally {
        if (!cancelled) setTxnsLoading(false);
      }
    };
    load();
    return () => { cancelled = true; };
  }, [alert?.id]);

  return (
    <div className="detail-grid">
      <div className="detail-main">
        {/* Header card */}
        <div style={{ marginBottom: 14 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 6 }}>
            <button className="btn ghost sm" onClick={onClose}>
              <Icon.Chevron size={11} style={{ transform: "rotate(180deg)" }} />
              {backLabel}
            </button>
            <span className="muted" style={{ fontSize: 11.5 }}>·</span>
            <span className="mono" style={{ fontSize: 11.5, color: "var(--fg-3)" }}>{alert.case}</span>
            <span className="muted" style={{ fontSize: 11.5 }}>·</span>
            <span className="mono" style={{ fontSize: 11.5, color: "var(--fg-3)" }}>opened 2h 14m ago</span>
            <span style={{ flex: 1 }} />
            <button className="btn ghost sm"><Icon.Star size={12} /> Watch</button>
            <button className="btn ghost sm"><Icon.Link size={12} /> Copy link</button>
            <button className="btn ghost sm"><Icon.More size={12} /></button>
          </div>
          <div style={{ display: "flex", alignItems: "flex-start", gap: 16 }}>
            <div style={{ flex: 1 }}>
              <h1 style={{ margin: 0, fontSize: 22, fontWeight: 600, letterSpacing: "-0.02em" }}>
                {alert.subject}
              </h1>
              <div style={{ display: "flex", alignItems: "center", gap: 10, marginTop: 6, color: "var(--fg-3)", fontSize: 12.5 }}>
                <span className="pill high"><SeverityDot s="high" />{alert.typology}</span>
                <span className="mono">{alert.external_id}</span>
                <span>·</span>
                <span>{alert.rule}</span>
              </div>
            </div>
            <div style={{ textAlign: "right" }}>
              <div className="kpi-label" style={{ margin: 0 }}>Risk score</div>
              <div style={{ display: "flex", alignItems: "baseline", gap: 4, justifyContent: "flex-end" }}>
                <span className="mono" style={{ fontSize: 36, fontWeight: 500, color: riskColor(alert.risk), lineHeight: 1, letterSpacing: "-0.03em" }}>
                  {alert.risk}
                </span>
                <span className="muted" style={{ fontSize: 13 }}>/ 100</span>
              </div>
              <div className="mono" style={{ fontSize: 10.5, color: "var(--fg-3)", marginTop: 2 }}>
                +14 vs. baseline
              </div>
            </div>
          </div>
        </div>

        {/* Tabs */}
        <div style={{ display: "flex", gap: 0, borderBottom: "1px solid var(--border)", marginBottom: 14 }}>
          {["overview", "transactions", "entity", "documents"].map(t => (
            <button key={t} className={`tab ${tab === t ? "active" : ""}`}
                    onClick={() => setTab(t)}
                    style={{ padding: "0 12px", height: 34, textTransform: "capitalize", marginBottom: -1 }}>
              {t}
              {t === "transactions" && <span className="tab-count">{txnsLoading ? "…" : txns.length}</span>}
            </button>
          ))}
        </div>

        {tab === "overview" && (
          <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>

            {/* Score breakdown card + key facts */}
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
              <div className="card">
                <div className="card-hd">
                  <h3>Score breakdown</h3>
                  <span className="spacer" />
                  <span className="mono muted" style={{ fontSize: 11 }}>model · v4.2</span>
                </div>
                <div className="card-body">
                  <ScoreBreakdown score={alert.score} />
                </div>
              </div>
              <div className="card">
                <div className="card-hd">
                  <h3>Key facts</h3>
                </div>
                <div className="card-body">
                  <div style={{ display: "grid", gridTemplateColumns: "120px 1fr", gap: "10px 14px", fontSize: 12.5 }}>
                    <div className="muted">Entity type</div>
                    <div>SMB · LLC · Maritime services</div>
                    <div className="muted">Account opened</div>
                    <div className="mono">2024-02-11 <span className="muted">· 27 months</span></div>
                    <div className="muted">Owners</div>
                    <div>3 · all KYC-verified</div>
                    <div className="muted">PEP / sanctions</div>
                    <div style={{ color: "var(--risk-low)" }}>
                      <Icon.Check size={11} /> Clear · last refresh 41d ago
                    </div>
                    <div className="muted">Prior cases</div>
                    <div className="mono">CSE-25-3308 <span className="muted">closed · cleared</span></div>
                    <div className="muted">Watchlist</div>
                    <div style={{ color: "var(--risk-med)" }}>
                      Internal · since 2025-Q4
                    </div>
                  </div>
                </div>
              </div>
            </div>

            {/* Entity network */}
            <div className="card">
              <div className="card-hd">
                <h3>Entity network</h3>
                <span style={{ marginLeft: 10, display: "inline-flex", gap: 12, fontSize: 11.5, color: "var(--fg-3)" }}>
                  <span><span className="dot dot-high" />Suspicious flows</span>
                  <span><span className="dot dot-med" />Cash channel</span>
                  <span><span className="dot dot-low" />Normal flows</span>
                  <span><span className="dot dot-info" />Linked case</span>
                </span>
                <span className="spacer" />
                <button className="btn sm"><Icon.Plus size={11} /> Expand</button>
                <button className="btn sm"><Icon.Download size={11} /> Export</button>
              </div>
              <div className="card-body" style={{ padding: 8 }}>
                {networkLoading ? (
                  <div style={{ height: 420, display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fg-3)", fontSize: 12 }}>
                    Loading network…
                  </div>
                ) : (
                  <NetworkGraph network={network} />
                )}
              </div>
            </div>

            {/* Volume histogram */}
            <div className="card">
              <div className="card-hd">
                <h3>Daily transaction volume · 30d</h3>
                <span className="spacer" />
                <span className="mono muted" style={{ fontSize: 11 }}>peak <span style={{ color: "var(--risk-high)" }}>18 txns</span> on May 14</span>
              </div>
              <div className="card-body" style={{ padding: "12px 12px 4px" }}>
                <VolumeHistogram />
              </div>
            </div>
          </div>
        )}

        {tab === "transactions" && (
          <div className="card" style={{ overflow: "hidden" }}>
            <div className="card-hd">
              <h3>Transactions that triggered this alert</h3>
              <span className="spacer" />
              <span className="mono muted" style={{ fontSize: 11 }}>
                {txnsLoading ? "Loading…" : `${txns.length} transaction${txns.length !== 1 ? "s" : ""}`}
              </span>
              <button className="btn sm" disabled={txnsLoading || txns.length === 0}><Icon.Download size={11} /> CSV</button>
            </div>
            <CaseTxnTable transactions={txns} primaryId={alert._raw?.transaction_id || alert.transactionId} loading={txnsLoading} />
          </div>
        )}

        {tab === "entity" && (
          <div className="card">
            <div className="card-hd"><h3>Entity profile · Ardent Maritime LLC</h3></div>
            <div className="card-body">
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 20, fontSize: 12.5 }}>
                <div>
                  <div className="kpi-label">Legal</div>
                  <div style={{ display: "grid", gridTemplateColumns: "1fr", gap: 6 }}>
                    <Field k="EIN" v="••-•••7421" />
                    <Field k="Formed" v="2022-08-03 · DE" />
                    <Field k="NAICS" v="488330 · Navigational services" />
                    <Field k="Address" v="2814 Wharfside Rd, Newark NJ" />
                  </div>
                </div>
                <div>
                  <div className="kpi-label">Beneficial owners</div>
                  <Field k="J. Halberd" v="42% · CEO · KYC ✓" />
                  <Field k="M. Vance" v="38% · CFO · KYC ✓" />
                  <Field k="P. Krayton" v="20% · Director · KYC ⚠" extra="med" />
                </div>
                <div>
                  <div className="kpi-label">Account portfolio</div>
                  <Field k="Operating" v="•••• 1102 · checking" />
                  <Field k="Reserve" v="•••• 8419 · MMA" />
                  <Field k="FX" v="•••• 4419 · multi-currency" extra="info" />
                </div>
              </div>
            </div>
          </div>
        )}

        {tab === "documents" && (
          <div className="card">
            <div className="card-hd"><h3>Documents</h3><span className="spacer" /><button className="btn sm primary"><Icon.Plus size={11} /> Upload</button></div>
            <div className="card-body" style={{ color: "var(--fg-3)" }}>
              <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
                <DocRow name="KYC refresh request" date="2026-05-14" status="pending" />
                <DocRow name="Wire confirmation · TX-7740822" date="2026-05-14" status="filed" />
                <DocRow name="Beneficial ownership cert" date="2024-08-03" status="filed" />
                <DocRow name="EDD questionnaire 2025-Q4" date="2025-11-12" status="filed" />
              </div>
            </div>
          </div>
        )}

      </div>

      <div className="detail-rail">
        <DecisionRail alert={alert} onClose={onClose} onRefresh={data?.refresh} />
      </div>
    </div>
  );
}

function Field({ k, v, extra }) {
  const ec = extra === "med" ? "var(--risk-med)"
           : extra === "high" ? "var(--risk-high)"
           : extra === "info" ? "var(--info)"
           : "var(--fg)";
  return (
    <div style={{ display: "flex", marginBottom: 6 }}>
      <span className="muted" style={{ width: 110, flexShrink: 0, fontSize: 12 }}>{k}</span>
      <span style={{ color: ec, fontSize: 12.5 }} className={k.startsWith("EIN") || k.startsWith("•") ? "mono" : ""}>{v}</span>
    </div>
  );
}

function DocRow({ name, date, status }) {
  const pill = { filed: "pill low", pending: "pill med", missing: "pill high" }[status] || "pill";
  return (
    <div style={{
      display: "flex", alignItems: "center",
      padding: "8px 10px",
      border: "1px solid var(--border)",
      borderRadius: 6,
      gap: 10,
    }}>
      <Icon.Note size={14} />
      <span style={{ color: "var(--fg)", fontWeight: 500 }}>{name}</span>
      <span className="mono muted" style={{ fontSize: 11 }}>{date}</span>
      <span style={{ flex: 1 }} />
      <span className={pill}>{status}</span>
      <button className="btn ghost icon sm"><Icon.More size={11} /></button>
    </div>
  );
}

Object.assign(window, { CaseDetailView });
