/* inspector.jsx — AIRS Security Inspector. Presenter-facing real-time
   security console. Follows the shell theme (dark console / light console).
   Verdict colors (green/amber/red) stay constant across themes. */

const VERDICT_META = {
  allow: { label: "ALLOWED", color: "#1fae63", bg: "rgba(52,210,123,0.14)", border: "rgba(52,210,123,0.42)", icon: "ShieldCheck" },
  flag: { label: "FLAGGED", color: "#e0951c", bg: "rgba(245,181,61,0.16)", border: "rgba(245,181,61,0.45)", icon: "ShieldAlert" },
  block: { label: "BLOCKED", color: "#e2453a", bg: "rgba(255,91,110,0.15)", border: "rgba(255,91,110,0.45)", icon: "ShieldX" },
};

const CAT_ICON = {
  "Prompt Injection": "Syringe",
  "Sensitive Data Leakage": "DatabaseZap",
  "Database/Code Injection": "Braces",
  "Malicious URL": "Link2",
  "Toxic Content": "TriangleAlert",
};

const SHORT_CAT = {
  "Prompt Injection": "Injection",
  "Sensitive Data Leakage": "Data Leak",
  "Database/Code Injection": "Code Inj.",
  "Malicious URL": "Mal. URL",
  "Toxic Content": "Toxic",
};

/* dark + light console palettes — only chrome switches, not verdict colors */
const INSPECTOR_THEMES = {
  dark: {
    panel: "#0c0e16",
    headerBg: "linear-gradient(180deg,#11131d,#0c0e16)",
    footerBg: "linear-gradient(0deg,#0c0e16,rgba(12,14,22,0.4))",
    border: "rgba(255,255,255,0.08)",
    inkStrong: "#eef0f4",
    ink: "#cdd2df",
    ink2: "#aeb4c6",
    sub: "#9ca2b6",
    faint: "#7e8499",
    faint2: "#6c7385",
    cardBg: "rgba(255,255,255,0.025)",
    statBg: "rgba(255,255,255,0.035)",
    statBorder: "rgba(255,255,255,0.07)",
    payloadBg: "rgba(0,0,0,0.25)",
    chipBg: "rgba(255,255,255,0.05)",
    chipBorder: "rgba(255,255,255,0.08)",
    btnBg: "rgba(255,255,255,0.03)",
    inMono: "#6f86c9",
    outOk: "#5fb98f",
    shadow: "-30px 0 70px -30px rgba(0,0,0,0.7)",
  },
  light: {
    panel: "#f4f3f7",
    headerBg: "linear-gradient(180deg,#ffffff,#f4f3f7)",
    footerBg: "linear-gradient(0deg,#f4f3f7,rgba(244,243,247,0.4))",
    border: "rgba(24,20,32,0.10)",
    inkStrong: "#1b1822",
    ink: "#3c3848",
    ink2: "#4a4556",
    sub: "#5f5a6c",
    faint: "#7b7686",
    faint2: "#938e9e",
    cardBg: "#ffffff",
    statBg: "#ffffff",
    statBorder: "rgba(24,20,32,0.10)",
    payloadBg: "rgba(24,20,32,0.05)",
    chipBg: "rgba(24,20,32,0.045)",
    chipBorder: "rgba(24,20,32,0.11)",
    btnBg: "#ffffff",
    inMono: "#3457b8",
    outOk: "#1f8a5b",
    shadow: "-30px 0 70px -30px rgba(40,30,50,0.22)",
  },
};

function Stat({ label, value, color, insp }) {
  return (
    <div className="flex flex-col rounded-xl px-3 py-2.5" style={{ background: insp.statBg, border: `1px solid ${insp.statBorder}` }}>
      <span className="text-[19px] font-bold leading-none" style={{ color: color || insp.inkStrong, fontFamily: "'JetBrains Mono', monospace" }}>{value}</span>
      <span className="mt-1 text-[10px] font-semibold uppercase tracking-wider" style={{ color: insp.faint }}>{label}</span>
    </div>
  );
}

function VerdictCard({ event, insp }) {
  const m = VERDICT_META[event.airs.verdict];
  const scannedLabel = { prompt: "Prompt → in", response: "Response → out", both: "Prompt + Response" }[event.airs.scanned] || event.airs.scanned;
  return (
    <div className="relative overflow-hidden rounded-xl a-pop" style={{ background: insp.cardBg, border: `1px solid ${m.border}` }}>
      <div className="absolute left-0 top-0 h-full w-[3px]" style={{ background: m.color }} />
      <div className="px-3.5 py-3 pl-4">
        <div className="flex items-center justify-between">
          <span className="inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-[10.5px] font-bold tracking-wider" style={{ background: m.bg, color: m.color }}>
            <Icon name={m.icon} size={13} /> {m.label}
          </span>
          <span className="flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide" style={{ color: insp.faint }}>
            <Icon name="ScanLine" size={12} /> {scannedLabel}
          </span>
        </div>

        {/* categories */}
        {event.airs.categories.length > 0 ? (
          <div className="mt-2.5 flex flex-wrap gap-1.5">
            {event.airs.categories.map((c) => (
              <span key={c} className="inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-[10.5px] font-medium" style={{ background: insp.chipBg, border: `1px solid ${insp.chipBorder}`, color: insp.ink }}>
                <Icon name={CAT_ICON[c] || "Tag"} size={11} style={{ color: m.color }} /> {c}
              </span>
            ))}
          </div>
        ) : (
          <div className="mt-2.5 text-[11px]" style={{ color: insp.faint2 }}>No threats detected.</div>
        )}

        {/* payload preview */}
        <div className="mt-3 space-y-1.5 rounded-lg px-2.5 py-2" style={{ background: insp.payloadBg }}>
          <div className="flex gap-2 text-[11px]">
            <span className="shrink-0 font-bold" style={{ color: insp.inMono, fontFamily: "'JetBrains Mono', monospace" }}>IN </span>
            <span className="truncate" style={{ color: insp.ink2 }}>{event.userText}</span>
          </div>
          <div className="flex gap-2 text-[11px]">
            <span className="shrink-0 font-bold" style={{ color: event.blocked ? VERDICT_META.block.color : insp.outOk, fontFamily: "'JetBrains Mono', monospace" }}>OUT</span>
            <span className="truncate" style={{ color: event.blocked ? VERDICT_META.block.color : insp.ink2, fontStyle: event.blocked ? "italic" : "normal" }}>
              {event.blocked ? "⛔ replaced with safe response" : event.reply}
            </span>
          </div>
        </div>
      </div>
    </div>
  );
}

function Inspector({ open, business, events, onClose, onSimulate, busy, mode = "dark" }) {
  const insp = INSPECTOR_THEMES[mode] || INSPECTOR_THEMES.dark;
  const stats = React.useMemo(() => {
    const total = events.length;
    const allowed = events.filter((e) => e.airs.verdict === "allow").length;
    const flagged = events.filter((e) => e.airs.verdict === "flag").length;
    const blocked = events.filter((e) => e.airs.verdict === "block").length;
    return { total, allowed, flagged, blocked };
  }, [events]);

  const ordered = [...events].reverse();

  return (
    <aside
      className="absolute right-0 top-0 z-40 flex h-full w-full flex-col sm:w-[400px]"
      style={{
        background: insp.panel,
        borderLeft: `1px solid ${insp.border}`,
        boxShadow: insp.shadow,
        transform: open ? "translateX(0)" : "translateX(105%)",
        transition: "transform .42s cubic-bezier(.22,1,.36,1)",
        fontFamily: "'Manrope', sans-serif",
      }}
    >
      {/* header */}
      <div className="z-10 px-4 py-4" style={{ background: insp.headerBg, borderBottom: `1px solid ${insp.border}` }}>
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-2.5">
            <div className="relative flex h-9 w-9 items-center justify-center rounded-xl" style={{ background: "linear-gradient(135deg,#E14D62,#7a2540)", color: "#fff", animation: "lr-pulse-ring 2.6s infinite" }}>
              <Icon name="Radar" size={19} />
            </div>
            <div className="leading-tight">
              <div className="flex items-center gap-2 text-[14px] font-bold" style={{ color: insp.inkStrong }}>AIRS Inspector</div>
              <div className="text-[10.5px] font-semibold uppercase tracking-[0.16em]" style={{ color: insp.faint }}>Presenter view · live</div>
            </div>
          </div>
          <button onClick={onClose} className="flex h-8 w-8 items-center justify-center rounded-lg transition-colors" style={{ color: insp.sub, background: insp.chipBg }}>
            <Icon name="X" size={18} />
          </button>
        </div>

        {/* stat grid */}
        <div className="mt-3.5 grid grid-cols-3 gap-2">
          <Stat label="Scanned" value={stats.total} insp={insp} />
          <Stat label="Flagged" value={stats.flagged} color={stats.flagged ? VERDICT_META.flag.color : undefined} insp={insp} />
          <Stat label="Blocked" value={stats.blocked} color={stats.blocked ? VERDICT_META.block.color : undefined} insp={insp} />
        </div>
      </div>

      {/* live feed (own scroll region) */}
      <div className="lr-scroll min-h-0 flex-1 overflow-y-auto px-4 py-4">
        <div className="mb-2.5 flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.18em]" style={{ color: insp.faint }}>
          <span className="inline-block h-1.5 w-1.5 rounded-full" style={{ background: busy ? VERDICT_META.flag.color : VERDICT_META.allow.color, boxShadow: `0 0 8px ${busy ? VERDICT_META.flag.color : VERDICT_META.allow.color}` }} />
          {busy ? "Scanning…" : "Live traffic"}
        </div>

        {ordered.length === 0 ? (
          <div className="mt-10 flex flex-col items-center text-center">
            <div className="flex h-12 w-12 items-center justify-center rounded-2xl" style={{ background: insp.chipBg, color: insp.faint2 }}>
              <Icon name="ScanSearch" size={22} />
            </div>
            <p className="mt-3 max-w-[15rem] text-[12.5px] leading-relaxed" style={{ color: insp.faint }}>
              No traffic yet. Send a message in the chat — or fire a malicious prompt below — to watch AIRS scan it in real time.
            </p>
          </div>
        ) : (
          <div className="space-y-2.5">
            {ordered.map((e) => (
              <VerdictCard key={e.id} event={e} insp={insp} />
            ))}
          </div>
        )}
      </div>

      {/* malicious prompts (own scroll region) */}
      <div className="flex flex-col" style={{ background: insp.footerBg, borderTop: `1px solid ${insp.border}`, maxHeight: "44%" }}>
        <div className="flex items-center justify-between px-4 pb-2 pt-3">
          <div className="flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-[0.16em]" style={{ color: insp.sub }}>
            <Icon name="Bug" size={13} style={{ color: "#E14D62" }} /> Malicious Prompts
          </div>
          <span className="text-[10.5px]" style={{ color: insp.faint2, fontFamily: "'JetBrains Mono', monospace" }}>{business.attacks.length}</span>
        </div>
        <div className="lr-scroll min-h-0 flex-1 overflow-y-auto px-4 pb-4">
          <div className="flex flex-col gap-2">
            {business.attacks.map((a, i) => (
              <button
                key={i}
                onClick={() => onSimulate(a)}
                disabled={busy}
                className="flex w-full items-center justify-between gap-2 rounded-lg px-3 py-2.5 text-left text-[12.5px] font-medium transition-all hover:translate-x-0.5 disabled:opacity-40"
                style={{ background: insp.btnBg, border: `1px solid ${insp.chipBorder}`, color: insp.ink }}
              >
                <span className="flex min-w-0 items-center gap-2">
                  <Icon name={CAT_ICON[a.category] || "Bug"} size={14} style={{ color: insp.faint }} />
                  <span className="truncate">{a.label}</span>
                </span>
                <span className="inline-flex shrink-0 items-center gap-1 rounded px-1.5 py-0.5 text-[9.5px] font-semibold" style={{ background: insp.chipBg, border: `1px solid ${insp.chipBorder}`, color: insp.sub }}>
                  {SHORT_CAT[a.category] || a.category}
                </span>
              </button>
            ))}
          </div>
        </div>
      </div>
    </aside>
  );
}

window.Inspector = Inspector;
