import React from "react";
import {
  CheckCircle2, AlertTriangle, ShieldAlert, Bot, ScrollText, Flame, Coins,
  Wrench, RefreshCw, Info, Clock, Cpu, GitBranch, Layers, MessageSquare,
  Network, Map, Code2, Sparkles, ArrowRight, Link2, ChevronRight, Lightbulb, ShieldCheck,
  Rocket, Database, Boxes, Server, Gauge, Scissors,
} from "lucide-react";
import { C, FD, FB, FM, fmt, fmtWhen } from "../theme.js";
import { BinaryLogo, GeneratedTag } from "./Primitives.jsx";

// SESSION REPORT — the executive cover page for a session (the simplified default
// view). It unifies every deterministic signal Her produces — cost, outcome, the
// real binaries run, the high-impact actions + risk, timestamps, and the cited
// recommendations — and is the jumping-off point to the Journey Graph (Mode A) and
// the turn-by-turn detail (Mode B). Numbers are the engine; the only GENERATED
// prose is the "What happened" overview (labelled). Suggest, never assert.

const COST_W = { in: 1.0, cacheCreate: 1.25, cacheRead: 0.1, out: 5.0 };

const RISK = {
  High: { c: C.red, note: "high-impact actions detected" },
  Medium: { c: C.amber, note: "review the flagged actions" },
  Low: { c: C.cyan, note: "minor actions only" },
  None: { c: C.muted, note: "nothing high-impact" },
};
const TAG = {
  LIVE: { c: C.red, icon: Rocket },
  PRODUCTION: { c: C.red, icon: Rocket },   // legacy alias
  SECURITY: { c: C.orange, icon: ShieldAlert },
  DATA: { c: "#f472b6", icon: Database },
  NETWORK: { c: C.cyan, icon: Network },
  CONFIG: { c: C.amber, icon: Code2 },
  DEV: { c: C.blue, icon: Server },
};

function durationStr(a, b) {
  if (!a || !b) return "—";
  const ms = new Date(b).getTime() - new Date(a).getTime();
  if (isNaN(ms) || ms < 0) return "—";
  const s = Math.round(ms / 1000);
  const h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60), ss = s % 60;
  return h ? `${h}h ${m}m` : m ? `${m}m ${ss}s` : `${ss}s`;
}

// A friendly type tag for a binary in "Tools Discovered".
function binKind(b) {
  const blob = `${b.product || ""} ${b.blurb || ""} ${b.security || ""}`.toLowerCase();
  if (/\b(database|postgres|sql|mongo|redis|sqlite|db client)\b/.test(blob)) return "DB CLI";
  if (b.via && b.via !== "direct") return "pkg";
  if (/\bcli\b/.test(blob) || b.identified) return "CLI";
  return "binary";
}

export default function SessionReport({
  session, turns, binaries, entities, impact, recommendations, advice,
  overview, narrated, onOpenTurn, onOpenJourney, onOpenRaw, onAskHer, chatOpen,
}) {
  const S = session;
  const tk = S.tokens || {};
  // point-in-time window occupancy ("fuel gauge") — distinct from the cumulative tk.*
  const ctx = S.context || { peak: 0, limit: 1e6, peakPct: 0, trajectory: [], compactions: [], overLimit: [] };
  const reqs = turns.reduce((s, t) => s + (t.reqs || 0), 0);
  const im = impact || { riskLevel: "None", actions: [], outcome: null };
  const outcome = im.outcome || { label: "—", detail: "" };
  const risk = RISK[im.riskLevel] || RISK.None;
  const agentPct = Math.round(100 * (S.indirectRatio || 0));

  // cost breakdown (by COST contribution — this is "why this COST so much")
  const parts = [
    { label: "Cache re-reads", raw: tk.cacheRead || 0, cost: (tk.cacheRead || 0) * COST_W.cacheRead, c: C.orange },
    { label: "Generated (agent output)", raw: tk.out || 0, cost: (tk.out || 0) * COST_W.out, c: C.cyan },
    { label: "Cache write", raw: tk.cacheCreate || 0, cost: (tk.cacheCreate || 0) * COST_W.cacheCreate, c: C.amber },
    { label: "Fresh input", raw: tk.in || 0, cost: (tk.in || 0) * COST_W.in, c: C.blue },
  ];
  const totalCost = parts.reduce((s, p) => s + p.cost, 0) || 1;
  const driver = parts.reduce((a, b) => (b.cost > a.cost ? b : a), parts[0]);

  // most important turns — by cost
  const ranked = [...turns]
    .filter((t) => (t.tokens?.cost ?? 0) > 0)
    .sort((a, b) => (b.tokens.cost ?? 0) - (a.tokens.cost ?? 0))
    .slice(0, 4);

  // tools discovered = binaries (real CLIs/pkgs) + skills/plugins + sub-agents + MCP
  const bins = (binaries || []).map((b) => ({ ...b, glyph: "binary", kind: binKind(b) }));
  const skills = (entities?.skills || []).map((s) => ({ name: s.name, turns: s.turns, glyph: "skill", kind: "skill" }));
  const agents = (entities?.subAgents || []).map((a) => ({ name: a.name, turns: a.turns, glyph: "agent", kind: a.via === "workflow" ? "workflow" : "agent" }));
  const mcp = (entities?.mcpServers || []).map((m) => ({ name: m.name, turns: m.turns, glyph: "mcp", kind: "MCP" }));
  const tools = [...bins, ...skills, ...agents, ...mcp];

  const recs = (advice?.recommendations?.length ? advice.recommendations : recommendations) || [];

  function copySummary() {
    const lines = [
      `Her · session report — ${S.sessionId ? S.sessionId.slice(0, 8) : ""}`,
      `${S.cwd || ""}`,
      `Outcome: ${outcome.label} (${outcome.detail})`,
      `Token cost: ${fmt(S.cost || 0)} cost-weighted tokens (not $) · cache re-reads ${fmt(tk.cacheRead || 0)} cumulative across ${reqs} round-trips · agent-driven ${agentPct}%`,
      `Peak context: ${fmt(ctx.peak || 0)} / ${fmt(ctx.limit || 0)} (${Math.round((ctx.peakPct || 0) * 100)}% of the window)${ctx.compactions?.length ? ` · ${ctx.compactions.length} compaction(s)` : ""}`,
      `Risk: ${im.riskLevel} (${im.riskReason || ""})`,
      `Tools: ${tools.map((t) => t.product || t.name).join(", ")}`,
      im.actions?.length ? `Actions: ${im.actions.map((a) => `${a.title} [${a.tag}]`).join("; ")}` : "",
      `Started ${fmtWhen(S.startedAt)} · ${durationStr(S.startedAt, S.endedAt)} · ${S.model || ""}`,
    ].filter(Boolean);
    try { navigator.clipboard.writeText(lines.join("\n")); } catch { /* ignore */ }
  }

  return (
    <div style={{ flex: 1, minWidth: 0, overflowY: "auto", padding: "22px 26px 40px" }}>
      {/* title + actions */}
      <div style={{ display: "flex", alignItems: "flex-start", gap: 16, flexWrap: "wrap" }}>
        <div style={{ flex: 1, minWidth: 280 }}>
          <div style={{ fontFamily: FD, fontWeight: 700, fontSize: 26, letterSpacing: 0.2 }}>Session Report</div>
          <div style={{ fontSize: 13, color: C.text2, marginTop: 4, lineHeight: 1.5, maxWidth: 640 }}>
            Executive summary for this coding-agent session — what happened, why it cost, and what to review.
          </div>
        </div>
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
          <ReportBtn icon={Map} text="Open Journey Graph" onClick={onOpenJourney} />
          <ReportBtn icon={Code2} text="Open Raw Trace" onClick={onOpenRaw} />
          <ReportBtn icon={Sparkles} text="Ask Her" onClick={onAskHer} primary active={chatOpen} />
        </div>
      </div>

      {/* stat band */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(190px,1fr))", gap: 12, marginTop: 18 }}>
        <StatCard label="OUTCOME" icon={outcome.label === "Succeeded" ? CheckCircle2 : AlertTriangle}
          iconColor={outcome.label === "Succeeded" ? C.cyan : C.amber}
          value={outcome.label} valueColor={outcome.label === "Succeeded" ? C.cyan : C.amber}
          sub={outcome.detail} big />
        <StatCard label="TOKEN COST" value={fmt(S.cost || 0)} valueColor={C.orange} grad sub="cost-weighted tokens · not $ (cacheRead ×0.1 · out ×5)" />
        <PeakContextCard ctx={ctx} />
        <StatCard label="CACHE RE-READS" value={fmt(tk.cacheRead || 0)}
          sub={`cumulative across ${reqs} round-trips · ~${Math.round(S.cacheReadOverOut || 0)}× generated · not window size`} />
        <StatCard label="RISK LEVEL" icon={ShieldAlert} iconColor={risk.c} value={im.riskLevel} valueColor={risk.c}
          sub={im.riskReason || risk.note} />
        <StatCard label="AGENT-DRIVEN" icon={Bot} iconColor={C.orange} value={`${agentPct}%`}
          sub={`${S.indirect || 0} of ${S.tools || 0} tool calls`} />
      </div>

      {/* main grid */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(260px,1fr))", gap: 12, marginTop: 12 }}>
        {/* WHAT HAPPENED */}
        <Card icon={ScrollText} title="WHAT HAPPENED">
          {overview?.text ? (
            <>
              <div style={{ marginBottom: 8 }}><GeneratedTag cites={overview.label} /></div>
              <ul style={{ margin: 0, paddingLeft: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: 8 }}>
                {sentences(overview.text).map((s, i) => (
                  <li key={i} style={{ display: "flex", gap: 8, fontSize: 12.5, color: C.text2, lineHeight: 1.5 }}>
                    <CheckCircle2 size={13} color={C.cyan} style={{ flexShrink: 0, marginTop: 2 }} /> <span>{s}</span>
                  </li>
                ))}
              </ul>
            </>
          ) : (
            <div style={{ fontSize: 12.5, color: C.muted, lineHeight: 1.5 }}>
              {S.turns} queries · {S.tools} tool calls · {S.humanTurns} human / {S.systemTurns} system turns. (Plain-English summary appears when the local model is running.)
            </div>
          )}
        </Card>

        {/* ACTIONS WORTH REVIEWING */}
        <Card icon={AlertTriangle} title="ACTIONS WORTH REVIEWING" accent={C.amber}>
          {im.actions?.length ? im.actions.map((a, i) => {
            const tg = TAG[a.tag] || { c: C.muted, icon: Info };
            const Ic = tg.icon;
            return (
              <div key={i} className="row lift" onClick={() => a.turns?.length && onOpenTurn(a.turns[0])}
                style={{ display: "flex", gap: 10, alignItems: "center", cursor: a.turns?.length ? "pointer" : "default", background: C.card, border: `1px solid ${C.borderSoft}`, borderRadius: 8, padding: "9px 11px", marginTop: i ? 7 : 0 }}>
                <div style={{ width: 26, height: 26, borderRadius: 7, background: C.elevated, border: `1px solid ${tg.c}`, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
                  <Ic size={13} color={tg.c} />
                </div>
                <div style={{ minWidth: 0, flex: 1 }}>
                  <div style={{ fontSize: 12.5, fontWeight: 600, color: C.text }}>{a.title}</div>
                  <div style={{ fontSize: 11, color: C.muted, lineHeight: 1.4, marginTop: 1 }}>{a.detail}</div>
                </div>
                <span style={{ fontFamily: FM, fontSize: 8.5, letterSpacing: 0.5, color: tg.c, border: `1px solid ${tg.c}`, borderRadius: 4, padding: "1px 6px", flexShrink: 0 }}>{a.tag}</span>
              </div>
            );
          }) : (
            <div className="row" style={{ display: "flex", gap: 9, alignItems: "center", fontSize: 12.5, color: C.text2, lineHeight: 1.5 }}>
              <ShieldCheck size={16} color={C.cyan} style={{ flexShrink: 0 }} />
              <span>No high-impact actions detected — no deploys, config/secret changes, tunnels, or privilege changes.</span>
            </div>
          )}
        </Card>

        {/* TOOLS DISCOVERED */}
        <Card icon={Wrench} title="TOOLS DISCOVERED">
          {tools.length ? (
            <>
              <div style={{ display: "flex", flexWrap: "wrap", gap: 7 }}>
                {tools.map((t) => {
                  const clickable = t.turns && t.turns.length;
                  return (
                  <span key={t.glyph + ":" + t.name}
                    onClick={() => clickable && onOpenTurn(t.turns[0])}
                    className={clickable ? "lift" : ""}
                    title={`${t.product || t.name}${t.blurb ? " — " + t.blurb : ""}${t.security ? "  ⚠ " + t.security : ""}${t.turns?.length ? "  · turn(s) " + t.turns.join(", ") : ""}`}
                    style={{ display: "inline-flex", alignItems: "center", gap: 6, fontFamily: FM, fontSize: 10.5, color: C.text2, border: `1px solid ${C.borderSoft}`, borderRadius: 7, padding: "4px 8px 4px 6px", cursor: clickable ? "pointer" : "default" }}>
                    {toolGlyph(t)}
                    <span style={{ color: C.text }}>{t.product || t.name}</span>
                    <span style={{ color: C.muted, fontSize: 9 }}>({t.kind})</span>
                    {t.security && <ShieldAlert size={10} color={C.amber} />}
                  </span>
                  );
                })}
              </div>
              <div onClick={onOpenJourney} className="lift" style={{ cursor: "pointer", fontFamily: FM, fontSize: 10.5, color: C.orange, marginTop: 12, display: "inline-flex", alignItems: "center", gap: 5 }}>
                See all {S.tools} tool calls <ArrowRight size={12} />
              </div>
            </>
          ) : <Empty text="No external binaries or MCP servers detected." />}
        </Card>
      </div>

      {/* COST & CONTEXT — one widget, two halves of the same token story: cumulative
          spend (left, no ceiling) vs the point-in-time window gauge (right, ≤1M). Side
          by side so the two quantities can't be mistaken for each other. */}
      <CostContextCard S={S} parts={parts} totalCost={totalCost} driver={driver}
        ctx={ctx} reqs={reqs} onOpenTurn={onOpenTurn} />

      {/* bottom grid */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(300px,1fr))", gap: 12, marginTop: 12 }}>
        {/* MOST IMPORTANT TURNS */}
        <Card icon={Flame} title="MOST IMPORTANT TURNS">
          <div style={{ display: "flex", flexDirection: "column", gap: 7 }}>
            {ranked.map((t) => {
              const errs = (t.tools || []).filter((tc) => tc.errored).length;
              const title = t.guide?.head || (t.heavy ? "Heaviest turn" : firstClause(t.prompt));
              const detail = t.guide?.body ? clip(t.guide.body, 90) : `${(t.tools || []).length} tools${errs ? `, ${errs} errored` : ""}`;
              const pct = Math.round((100 * (t.tokens.cost ?? 0)) / Math.max(1, S.cost || 1));
              return (
                <div key={t.i} className="row lift" onClick={() => onOpenTurn(t.i)}
                  style={{ display: "flex", gap: 10, alignItems: "flex-start", cursor: "pointer", background: C.card, border: `1px solid ${C.borderSoft}`, borderRadius: 8, padding: "9px 11px" }}>
                  <span style={{ fontFamily: FM, fontSize: 10, color: C.muted, background: C.black, borderRadius: 5, padding: "2px 6px", flexShrink: 0 }}>#{String(t.i).padStart(2, "0")}</span>
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{ fontSize: 12.5, fontWeight: 600, color: C.text, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{title}</div>
                    <div style={{ fontSize: 11, color: C.muted, lineHeight: 1.4, marginTop: 2 }}>{detail}</div>
                  </div>
                  <div style={{ textAlign: "right", flexShrink: 0 }}>
                    <div style={{ fontFamily: FM, fontSize: 12, color: t.heavy ? C.orange : C.text2, fontWeight: 600 }}>{fmt(t.tokens.cost ?? 0)}</div>
                    <div style={{ fontFamily: FM, fontSize: 9, color: C.muted }}>{pct}% of cost</div>
                  </div>
                  <ChevronRight size={14} color={C.muted} style={{ flexShrink: 0, marginTop: 2 }} />
                </div>
              );
            })}
            {ranked.length === 0 && <Empty text="No costed turns." />}
          </div>
        </Card>

        {/* RECOMMENDED NEXT RUN */}
        <Card icon={RefreshCw} title="RECOMMENDED NEXT RUN">
          {recs.length ? recs.slice(0, 4).map((r, i) => (
            <div key={i} className="row lift" onClick={() => r.turns?.length && onOpenTurn(r.turns[0])}
              style={{ display: "flex", gap: 10, alignItems: "flex-start", cursor: r.turns?.length ? "pointer" : "default", background: C.card, border: `1px solid ${C.borderSoft}`, borderRadius: 8, padding: "9px 11px", marginTop: i ? 7 : 0 }}>
              <Lightbulb size={14} color={C.amber} style={{ flexShrink: 0, marginTop: 2 }} />
              <div style={{ minWidth: 0, flex: 1 }}>
                <div style={{ fontSize: 12.5, fontWeight: 600, color: C.text, display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }}>
                  {r.headline}
                  <AttrBadge attribution={r.attribution} scoped={!!r.scoped} />
                </div>
                <div style={{ fontSize: 11.5, color: C.muted, lineHeight: 1.45, marginTop: 2 }}>{clip(r.scoped || r.advice || "", 120)}</div>
              </div>
              <ChevronRight size={14} color={C.muted} style={{ flexShrink: 0, marginTop: 2 }} />
            </div>
          )) : (
            <div className="row" style={{ display: "flex", gap: 9, alignItems: "center", fontSize: 12.5, color: C.text2, lineHeight: 1.5 }}>
              <CheckCircle2 size={16} color={C.cyan} style={{ flexShrink: 0 }} />
              <span>Nothing stands out to change — expensive but clean. No loops, avoidable re-reads, or CLI flailing.</span>
            </div>
          )}
        </Card>

        {/* SESSION AT A GLANCE */}
        <Card icon={Info} title="SESSION AT A GLANCE">
          <Glance icon={Clock} label="Started" value={fmtWhen(S.startedAt) || "—"} />
          <Glance icon={Clock} label="Duration" value={durationStr(S.startedAt, S.endedAt)} />
          <Glance icon={Cpu} label="Model" value={modelLabel(S.model)} />
          <Glance icon={Layers} label="Mode" value={`${S.humanTurns || 0} human + ${S.systemTurns || 0} system`} />
          <Glance icon={GitBranch} label="Branch" value={S.gitBranch || "—"} />
          <Glance icon={MessageSquare} label="Queries" value={String(S.turns ?? "—")} />
          <Glance icon={Wrench} label="Tools called" value={String(S.tools ?? "—")} />
          <div onClick={copySummary} className="lift" style={{ cursor: "pointer", marginTop: 12, display: "flex", alignItems: "center", justifyContent: "center", gap: 7, background: C.black, border: `1px solid ${C.borderSoft}`, borderRadius: 8, padding: "8px 10px", fontFamily: FM, fontSize: 11, color: C.text2 }}>
            <Link2 size={13} color={C.orange} /> Copy summary
          </div>
        </Card>
      </div>
    </div>
  );
}

// ---------- small presentational atoms (Tactical Grey) ----------------------
function ReportBtn({ icon: Icon, text, onClick, primary, active }) {
  // `active` (panel open) gives a pressed look so it reads as a toggle — click again to close.
  const bg = primary ? (active ? C.orangeHi : C.orange) : (active ? C.orangeMut : "transparent");
  const fg = primary ? "#fff" : (active ? C.orange : C.text2);
  return (
    <div onClick={onClick} className="row lift" title={active ? "click to close the panel" : undefined}
      style={{ display: "flex", alignItems: "center", gap: 7, cursor: "pointer", fontFamily: FM, fontSize: 11.5, color: fg, background: bg, border: `1px solid ${primary || active ? (active && !primary ? C.orangeBd : C.orange) : C.border}`, borderRadius: 8, padding: "8px 13px", boxShadow: active ? "inset 0 1px 4px rgba(0,0,0,.35)" : "none" }}>
      <Icon size={14} color={primary ? "#fff" : C.orange} /> {text}
    </div>
  );
}

function StatCard({ label, icon: Icon, iconColor, value, valueColor, sub, grad, big }) {
  return (
    <div style={{ background: `linear-gradient(135deg,${C.card},${C.panel})`, border: `1px solid ${C.borderSoft}`, borderRadius: 10, padding: "13px 15px" }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <span style={{ fontFamily: FM, fontSize: 9, letterSpacing: 0.6, color: C.muted }}>{label}</span>
        {Icon && <Icon size={14} color={iconColor || C.muted} />}
      </div>
      <div className={grad ? "hb" : ""} style={{ fontFamily: FD, fontWeight: 700, fontSize: big ? 22 : 26, color: grad ? undefined : (valueColor || C.text), marginTop: 6, lineHeight: 1.1, display: "flex", alignItems: "center", gap: 8 }}>
        {big && Icon && <Icon size={20} color={iconColor} />}{value}
      </div>
      {sub && <div style={{ fontSize: 10.5, color: C.muted, marginTop: 5, lineHeight: 1.4 }}>{sub}</div>}
    </div>
  );
}

// PEAK CONTEXT — the "fuel gauge" headline: the fullest the live window ever got,
// over the model's limit. Point-in-time, bounded by the window (≤1M) — the opposite
// kind of number from the cumulative cost/cache stats beside it.
function PeakContextCard({ ctx }) {
  const pct = Math.round((ctx.peakPct || 0) * 100);
  const over = (ctx.overLimit || []).length > 0;
  const near = pct >= 80;
  const c = over ? C.red : near ? C.amber : C.cyan;
  return (
    <div style={{ background: `linear-gradient(135deg,${C.card},${C.panel})`, border: `1px solid ${C.borderSoft}`, borderRadius: 10, padding: "13px 15px" }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <span style={{ fontFamily: FM, fontSize: 9, letterSpacing: 0.6, color: C.muted }}>PEAK CONTEXT</span>
        <Gauge size={14} color={c} />
      </div>
      <div style={{ fontFamily: FD, fontWeight: 700, fontSize: 22, color: c, marginTop: 6, lineHeight: 1.1 }}>
        {fmt(ctx.peak || 0)}<span style={{ fontSize: 13, color: C.muted, fontWeight: 500 }}> / {fmt(ctx.limit || 0)}</span>
      </div>
      <div style={{ height: 6, background: C.black, borderRadius: 3, marginTop: 7, overflow: "hidden" }}>
        <div style={{ width: `${Math.min(100, Math.max(2, pct))}%`, height: "100%", background: `linear-gradient(90deg,${c},${c}aa)` }} />
      </div>
      <div style={{ fontSize: 10.5, color: C.muted, marginTop: 5, lineHeight: 1.4 }}>
        {over ? "⚠ a request exceeded the window — data suspect" : `${pct}% of the window · point-in-time, not cumulative`}
      </div>
    </div>
  );
}

// COST & CONTEXT — the unified token story in one card. LEFT: cumulative cost
// breakdown (no ceiling). RIGHT: the point-in-time window gauge + trajectory (≤1M).
// The side-by-side contrast IS the point — cumulative ≠ window occupancy.
function CostContextCard({ S, parts, totalCost, driver, ctx, reqs, onOpenTurn }) {
  return (
    <div style={{ marginTop: 12 }}>
      <Card icon={Coins} title="COST & CONTEXT — THE TOKEN STORY">
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(290px,1fr))", gap: 22 }}>
          {/* LEFT — cumulative spend */}
          <div>
            <SubHead text="WHY IT COST · cumulative tokens" />
            {/* Whole phrase is the hover target — the native `title` lives on this
                <span> (a `title` on an inline <svg> icon does NOT show a tooltip in
                Chrome). Dotted underline signals it's hoverable. */}
            <div style={{ fontSize: 12.5, color: C.text2, margin: "8px 0 10px" }}>
              Total: <b style={{ color: C.orange }}>{fmt(S.cost || 0)}</b>{" "}
              <span
                title={
                  `HOW IT'S COMPUTED\n` +
                  `cost-weighted tokens = fresh-input ×1  +  cache-write ×1.25  +  cache-read ×0.1  +  generated ×5\n` +
                  `(Anthropic's uniform price ratios), summed across all ${reqs} round-trips.\n` +
                  `A relative spend proxy in input-token-equivalents — multiply by your input $/token for dollars.\n\n` +
                  `WHY IT'S NOT THE CONTEXT WINDOW\n` +
                  `This is CUMULATIVE and has no ceiling, so it routinely dwarfs the window. ` +
                  `The context window here is ${fmt(ctx.limit || 0)} (point-in-time, bounded — see the gauge on the right). ` +
                  `${fmt(S.cost || 0)} cost-weighted tokens is the running sum over every round-trip, NOT how full the ${fmt(ctx.limit || 0)} window got — different quantities.`
                }
                style={{ color: C.muted, cursor: "help", borderBottom: `1px dotted ${C.muted}` }}>
                cost-weighted tokens (not $) <Info size={11} color={C.muted} style={{ verticalAlign: "-1px" }} />
              </span>
            </div>
            {parts.map((p) => {
              const pct = Math.round((100 * p.cost) / totalCost);
              return (
                <div key={p.label} style={{ marginTop: 8 }}>
                  <div style={{ display: "flex", justifyContent: "space-between", fontSize: 11.5 }}>
                    <span style={{ color: C.text2 }}>{p.label}</span>
                    <span style={{ fontFamily: FM, color: C.muted }}>{fmt(p.raw)} <span style={{ color: p.c }}>({pct}%)</span></span>
                  </div>
                  <div style={{ height: 6, background: C.black, borderRadius: 3, marginTop: 4, overflow: "hidden" }}>
                    <div style={{ width: `${Math.max(1, pct)}%`, height: "100%", background: `linear-gradient(90deg,${p.c},${p.c}aa)` }} />
                  </div>
                </div>
              );
            })}
            <div style={{ display: "flex", gap: 7, marginTop: 12, fontSize: 11.5, color: C.text2, lineHeight: 1.5, background: C.black, border: `1px solid ${C.borderSoft}`, borderRadius: 7, padding: "9px 10px" }}>
              <Lightbulb size={13} color={C.amber} style={{ flexShrink: 0, marginTop: 1 }} />
              <span><b style={{ color: driver.c }}>{driver.label}</b> dominates cost ({Math.round((100 * driver.cost) / totalCost)}%){driver.label === "Cache re-reads" ? ` — the conversation re-read from cache on every round-trip, summed across all ${reqs}. Cumulative spend, not window size.` : "."}</span>
            </div>
          </div>
          {/* RIGHT — point-in-time window */}
          <div style={{ borderLeft: `1px solid ${C.borderSoft}`, paddingLeft: 22 }}>
            <SubHead text="CONTEXT WINDOW · point-in-time fill" />
            <div style={{ marginTop: 8 }}>
              <ContextTrajectory ctx={ctx} reqs={reqs} onOpenTurn={onOpenTurn} />
            </div>
          </div>
        </div>
      </Card>
    </div>
  );
}

function SubHead({ text }) {
  return <div style={{ fontFamily: FM, fontSize: 9.5, letterSpacing: 0.6, color: C.muted, textTransform: "uppercase" }}>{text}</div>;
}

// CONTEXT WINDOW trajectory — an area chart of how full the live window got per turn
// (the gauge over time), with compaction markers (sharp drops) and the 1M ceiling.
function ContextTrajectory({ ctx, reqs, onOpenTurn }) {
  const traj = ctx.trajectory || [];
  const limit = ctx.limit || 1e6;
  const compactTurns = new Set((ctx.compactions || []).map((c) => c.atTurn));
  const W = 300, H = 84, n = traj.length;
  if (!n) return <Empty text="No per-request token usage in this session." />;
  const x = (i) => (n === 1 ? W / 2 : (i / (n - 1)) * W);
  const y = (v) => H - Math.min(1, v / limit) * H;
  const pts = traj.map((e, i) => `${x(i).toFixed(1)},${y(e.end).toFixed(1)}`);
  const area = `M0,${H} L${pts.join(" L")} L${W},${H} Z`;
  const line = `M${pts.join(" L")}`;
  const over = (ctx.overLimit || []).length > 0;
  const peakPct = Math.round((ctx.peakPct || 0) * 100);
  return (
    <div>
      <div style={{ fontSize: 11.5, color: C.text2, marginBottom: 8, lineHeight: 1.5 }}>
        Peak fill <b style={{ color: peakPct >= 80 ? C.amber : C.cyan }}>{fmt(ctx.peak || 0)}</b> of {fmt(limit)} (<b>{peakPct}%</b>). The live window — bounded by {fmt(limit)} — across {reqs} round-trips. Not the cumulative totals.
      </div>
      <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none" style={{ width: "100%", height: 84, display: "block" }}>
        {/* 1M ceiling */}
        <line x1="0" y1="1" x2={W} y2="1" stroke={C.red} strokeWidth="1" strokeDasharray="3 3" opacity="0.5" />
        {/* 80% line */}
        <line x1="0" y1={H * 0.2} x2={W} y2={H * 0.2} stroke={C.amber} strokeWidth="0.75" strokeDasharray="2 4" opacity="0.4" />
        <path d={area} fill={`${C.cyan}22`} />
        <path d={line} fill="none" stroke={over ? C.red : C.cyan} strokeWidth="1.5" />
        {/* compaction markers */}
        {traj.map((e, i) => compactTurns.has(e.i) ? (
          <line key={e.i} x1={x(i)} y1="0" x2={x(i)} y2={H} stroke={C.orange} strokeWidth="1.25" strokeDasharray="2 2" />
        ) : null)}
      </svg>
      <div style={{ display: "flex", justifyContent: "space-between", fontFamily: FM, fontSize: 9, color: C.muted, marginTop: 3 }}>
        <span>turn 00</span>
        <span>{fmt(limit)} ceiling</span>
        <span>turn {String(traj[n - 1].i).padStart(2, "0")}</span>
      </div>
      <div style={{ display: "flex", gap: 7, marginTop: 10, fontSize: 11.5, color: C.text2, lineHeight: 1.5, background: C.black, border: `1px solid ${C.borderSoft}`, borderRadius: 7, padding: "9px 10px" }}>
        <Scissors size={13} color={C.orange} style={{ flexShrink: 0, marginTop: 1 }} />
        {ctx.compactions?.length ? (
          <span><b style={{ color: C.orange }}>{ctx.compactions.length} compaction{ctx.compactions.length === 1 ? "" : "s"}</b> detected — the window was trimmed where it dips.{" "}
            {ctx.compactions.map((c) => (
              <span key={c.atTurn} onClick={() => onOpenTurn(c.atTurn)} className="lift" style={{ cursor: "pointer", color: C.orange, fontFamily: FM }}>
                #{String(c.atTurn).padStart(2, "0")} ({fmt(c.before)}→{fmt(c.after)}){" "}
              </span>
            ))}
          </span>
        ) : (
          <span>No compactions — the window climbed to {peakPct}% and never had to be trimmed.</span>
        )}
      </div>
    </div>
  );
}

function Card({ icon: Icon, title, accent, children }) {
  return (
    <div style={{ background: C.panel, border: `1px solid ${C.borderSoft}`, borderRadius: 10, padding: "14px 15px" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 11 }}>
        <Icon size={14} color={accent || C.cyan} />
        <span style={{ fontFamily: FM, fontSize: 10.5, letterSpacing: 0.7, color: accent || C.cyan, fontWeight: 600 }}>{title}</span>
      </div>
      {children}
    </div>
  );
}

function Glance({ icon: Icon, label, value }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 9, padding: "5px 0", borderBottom: `1px solid ${C.borderSoft}` }}>
      <Icon size={13} color={C.muted} />
      <span style={{ fontSize: 12, color: C.muted, flex: 1 }}>{label}</span>
      <span style={{ fontFamily: FM, fontSize: 11.5, color: C.text2, textAlign: "right", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", maxWidth: 200 }}>{value}</span>
    </div>
  );
}

function AttrBadge({ attribution, scoped }) {
  const generally = attribution && attribution !== "Anthropic";
  return (
    <span title={generally ? "A widely-recommended practice (not Anthropic-specific)" : "From Anthropic's Claude Code best practices"}
      style={{ fontFamily: FM, fontSize: 8, letterSpacing: 0.3, color: generally ? C.amber : C.cyan, border: `1px solid ${generally ? C.amber : C.cyan}`, borderRadius: 4, padding: "1px 5px" }}>
      {generally ? "GENERALLY RECOMMENDED" : "ANTHROPIC"}
    </span>
  );
}

function Empty({ text }) {
  return <div style={{ fontSize: 12, color: C.muted, padding: "4px 0" }}>{text}</div>;
}

// ---------- helpers ---------------------------------------------------------
function sentences(text) {
  return String(text || "")
    .split(/(?<=[.!?])\s+/)
    .map((s) => s.trim())
    .filter((s) => s.length > 2)
    .slice(0, 6);
}
function firstClause(p) {
  const s = String(p || "").replace(/\s+/g, " ").trim();
  return s.length > 48 ? s.slice(0, 48) + "…" : s || "(turn)";
}
function clip(s, n) {
  s = String(s || "");
  return s.length > n ? s.slice(0, n).trimEnd() + "…" : s;
}
function modelLabel(m) {
  if (!m) return "—";
  return String(m).replace(/^claude-/, "Claude ").replace(/-(\d{8})$/, "").replace(/-/g, " ");
}
// Leading glyph for a Tools-Discovered chip: binaries get their logo (monogram
// fallback); skills/plugins, sub-agents, and MCP servers get a typed icon.
function toolGlyph(t) {
  if (t.glyph === "binary") return <BinaryLogo b={t} size={14} />;
  if (t.glyph === "mcp") return <Network size={13} color={C.cyan} />;
  if (t.glyph === "skill") return <Boxes size={13} color={C.amber} />;
  return <Bot size={13} color={C.blue} />; // agent / workflow
}
