/* eagle-charts.jsx — lightweight, theme-aware SVG data-viz for the SOC
   dashboard. Every chart reads colors via useE() so it adapts to light/dark.
   Animations are CSS-driven and respect prefers-reduced-motion. */

function useReveal(delay = 80) {
  const [on, setOn] = React.useState(false);
  React.useEffect(() => { const id = setTimeout(() => setOn(true), delay); return () => clearTimeout(id); }, []);
  return on;
}

/* ---- sparkline ---------------------------------------------- */
function Sparkline({ data, ck = "cost", w = 120, h = 34 }) {
  const E = useE(); const c = E[ck];
  const max = Math.max(...data), min = Math.min(...data), rng = max - min || 1;
  const pts = data.map((v, i) => [i / (data.length - 1) * w, h - ((v - min) / rng) * (h - 6) - 3]);
  const line = pts.map((p, i) => (i ? "L" : "M") + p[0].toFixed(1) + " " + p[1].toFixed(1)).join(" ");
  const area = line + ` L${w} ${h} L0 ${h} Z`;
  const gid = "spk" + ck;
  return (
    <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      <defs><linearGradient id={gid} x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor={c} stopOpacity="0.28" /><stop offset="1" stopColor={c} stopOpacity="0" /></linearGradient></defs>
      <path d={area} fill={`url(#${gid})`} />
      <path d={line} fill="none" stroke={c} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
      <circle cx={pts[pts.length - 1][0]} cy={pts[pts.length - 1][1]} r="2.2" fill={c} />
    </svg>
  );
}

/* ---- stacked area: alerts over 24h -------------------------- */
function AreaStack({ data, height = 200 }) {
  const E = useE(); const on = useReveal();
  const W = 720, H = height, padB = 22, padL = 28, plotH = H - padB, plotW = W - padL;
  const maxTot = Math.max(...data.map((d) => d.total)) * 1.18 || 1;
  const n = data.length;
  const x = (i) => padL + i / (n - 1) * plotW;
  const y = (v) => plotH - (v / maxTot) * plotH;
  const layers = [["low", E.low], ["med", E.med], ["high", E.high], ["crit", E.crit]];
  let cum = data.map(() => 0);
  const paths = layers.map(([key, color]) => {
    const top = data.map((d, i) => cum[i] + d[key]);
    const bot = cum.slice();
    const path = "M" + data.map((d, i) => x(i) + " " + y(top[i])).join(" L ") + " L " + data.map((d, i) => x(n - 1 - i) + " " + y(bot[n - 1 - i])).join(" L ") + " Z";
    cum = top;
    return { key, color, path };
  });
  const peak = data.reduce((m, d, i) => d.total > data[m].total ? i : m, 0);
  return (
    <svg width="100%" viewBox={`0 0 ${W} ${H}`} style={{ display: "block" }}>
      {[0.25, 0.5, 0.75, 1].map((f, i) => <line key={i} x1={padL} x2={W} y1={plotH - f * plotH} y2={plotH - f * plotH} stroke={E.grid} strokeWidth="1" />)}
      {[0, 0.5, 1].map((f, i) => <text key={i} x={padL - 6} y={plotH - f * plotH + 3} textAnchor="end" fontSize="9" fill={E.muted} fontFamily={E.mono}>{Math.round(f * maxTot)}</text>)}
      <g style={{ transform: on ? "scaleX(1)" : "scaleX(0)", transformOrigin: "left center", transition: "transform 1s cubic-bezier(.22,1,.36,1)" }}>
        {paths.map((p) => <path key={p.key} d={p.path} fill={p.color} fillOpacity={E.isDark ? 0.42 : 0.5} stroke={p.color} strokeWidth="1.2" strokeOpacity="0.9" />)}
      </g>
      <line x1={x(peak)} x2={x(peak)} y1={y(data[peak].total)} y2={plotH} stroke={E.high} strokeWidth="1" strokeDasharray="2 3" opacity={on ? 1 : 0} style={{ transition: "opacity .6s .8s" }} />
      <circle cx={x(peak)} cy={y(data[peak].total)} r="3" fill={E.high} opacity={on ? 1 : 0} style={{ transition: "opacity .6s .9s" }} />
      {[0, 6, 12, 18, 23].map((h) => <text key={h} x={x(h)} y={H - 6} textAnchor="middle" fontSize="9" fill={E.muted} fontFamily={E.mono}>{String(h).padStart(2, "0")}</text>)}
    </svg>
  );
}

/* ---- donut: severity distribution --------------------------- */
function Donut({ data, size = 168 }) {
  const E = useE(); const on = useReveal();
  const total = data.reduce((s, d) => s + d.value, 0);
  const r = size / 2 - 14, C = 2 * Math.PI * r, cx = size / 2;
  let acc = 0;
  return (
    <div className="flex items-center gap-5">
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        <g transform={`rotate(-90 ${cx} ${cx})`}>
          {data.map((d) => {
            const frac = d.value / total, seg = frac * C, off = -acc * C; acc += frac;
            return <circle key={d.key} cx={cx} cy={cx} r={r} fill="none" stroke={E[d.key]} strokeWidth="14" strokeLinecap="butt"
              strokeDasharray={`${on ? seg : 0} ${C}`} strokeDashoffset={off} style={{ transition: "stroke-dasharray .9s cubic-bezier(.22,1,.36,1)" }} />;
          })}
        </g>
        <text x={cx} y={cx - 3} textAnchor="middle" fontSize="30" fontWeight="800" fill={E.text} fontFamily={E.mono}>{total}</text>
        <text x={cx} y={cx + 16} textAnchor="middle" fontSize="10" fill={E.muted} letterSpacing="1.5">ALERTS</text>
      </svg>
      <div className="space-y-1.5">
        {data.map((d) => (
          <div key={d.key} className="flex items-center gap-2 text-[12.5px]">
            <span className="h-2.5 w-2.5 rounded-sm" style={{ background: E[d.key] }} />
            <span className="w-16" style={{ color: E.text2 }}>{d.label}</span>
            <span className="font-semibold tabular-nums" style={{ fontFamily: E.mono, color: E.text }}>{d.value}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---- horizontal bars: top hosts / users --------------------- */
function HBars({ items, unit = "" }) {
  const E = useE(); const on = useReveal();
  const max = Math.max(...items.map((i) => i.value));
  return (
    <div className="space-y-2.5">
      {items.map((it, i) => {
        const c = it.hot ? E.guard : E.cost;
        return (
          <div key={it.name} className="flex items-center gap-2.5">
            <span className="w-28 shrink-0 truncate text-[11.5px]" style={{ fontFamily: E.mono, color: it.hot ? E.text : E.text2 }}>{it.name}</span>
            <div className="relative h-5 flex-1 overflow-hidden rounded" style={{ background: E.fill }}>
              <div className="absolute inset-y-0 left-0 rounded" style={{ width: on ? (it.value / max * 100) + "%" : "0%", background: `linear-gradient(90deg, ${c}cc, ${c})`, transition: `width .8s cubic-bezier(.22,1,.36,1) ${i * 70}ms` }} />
            </div>
            <span className="w-6 shrink-0 text-right text-[12px] font-semibold tabular-nums" style={{ fontFamily: E.mono, color: c }}>{it.value}</span>
          </div>
        );
      })}
    </div>
  );
}

/* ---- radial gauge: MTTR / SLA ------------------------------- */
function RadialGauge({ g, size = 124 }) {
  const E = useE(); const on = useReveal(); const c = E[g.ck];
  const r = size / 2 - 12, cx = size / 2, sweep = 270;
  const circ = 2 * Math.PI * r, arcLen = circ * (sweep / 360);
  const frac = Math.min(1, g.value / g.max);
  return (
    <div className="flex flex-col items-center">
      <svg width={size} height={size * 0.82} viewBox={`0 0 ${size} ${size * 0.82}`}>
        <g transform={`rotate(135 ${cx} ${cx})`}>
          <circle cx={cx} cy={cx} r={r} fill="none" stroke={E.fill} strokeWidth="9" strokeLinecap="round" strokeDasharray={`${arcLen} ${circ}`} />
          <circle cx={cx} cy={cx} r={r} fill="none" stroke={c} strokeWidth="9" strokeLinecap="round" strokeDasharray={`${on ? arcLen * frac : 0} ${circ}`} style={{ transition: "stroke-dasharray 1s cubic-bezier(.22,1,.36,1)" }} />
        </g>
        <text x={cx} y={cx - 2} textAnchor="middle" fontSize="22" fontWeight="800" fill={E.text} fontFamily={E.mono}>{g.value}<tspan fontSize="11" fill={E.muted}>{g.unit}</tspan></text>
      </svg>
      <div className="-mt-1 text-center"><div className="text-[12px] font-bold" style={{ color: E.text }}>{g.label}</div><div className="text-[10px]" style={{ color: E.muted }}>{g.sub}</div></div>
    </div>
  );
}

/* ---- MITRE ATT&CK coverage heatmap -------------------------- */
function MitreHeatmap({ data }) {
  const E = useE(); const on = useReveal();
  const op = [0, 0.34, 0.66, 1];
  return (
    <div className="lr-scroll overflow-x-auto pb-1">
      <div className="flex gap-2" style={{ minWidth: 640 }}>
        {data.map((col, ci) => (
          <div key={col.tactic} className="flex-1" style={{ minWidth: 92 }}>
            <div className="mb-1.5 h-8 text-[10px] font-bold uppercase leading-tight tracking-wide" style={{ color: E.muted, fontFamily: E.mono }}>{col.tactic}</div>
            <div className="space-y-1.5">
              {col.techs.map(([name, lvl], ti) => (
                <div key={name} title={`${name} · ${lvl} detection${lvl === 1 ? "" : "s"}`}
                  className="flex h-9 items-center justify-between rounded-md px-2 transition-all"
                  style={{ background: lvl ? E.gateway + Math.round(op[lvl] * 255).toString(16).padStart(2, "0") : E.fill, border: `1px solid ${lvl >= 2 ? E.gateway + "88" : E.border}`, opacity: on ? 1 : 0, transform: on ? "none" : "scale(.9)", transitionDelay: (ci * 40 + ti * 30) + "ms" }}>
                  <span className="truncate text-[10.5px] font-medium" style={{ color: lvl >= 2 ? (E.isDark ? "#04110f" : "#fff") : E.text2 }}>{name}</span>
                  {lvl > 0 && <span className="ml-1 text-[10px] font-bold tabular-nums" style={{ fontFamily: E.mono, color: lvl >= 2 ? (E.isDark ? "#04110f" : "#fff") : E.gateway }}>{lvl}</span>}
                </div>
              ))}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---- threat topology map (sources → org → internal targets) - */
function ThreatMap({ origins, targets = [], size = 320 }) {
  const E = useE(); const on = useReveal();
  const cx = size / 2, cy = size / 2, R = size / 2 - 30, rT = R * 0.36;
  const polar = (ang, r) => [cx + Math.cos(ang * Math.PI / 180) * r, cy + Math.sin(ang * Math.PI / 180) * r];
  const sevColor = { crit: E.crit, high: E.high, med: E.med, low: E.low };
  const arc = (ox, oy) => { const mx = (ox + cx) / 2, my = (oy + cy) / 2; const dx = oy - cy, dy = cx - ox; const k = 0.22; return `M${ox} ${oy} Q${mx + dx * k} ${my + dy * k} ${cx} ${cy}`; };
  return (
    <svg width="100%" viewBox={`0 0 ${size} ${size}`} style={{ display: "block" }}>
      {[0.4, 0.7, 1].map((f, i) => <circle key={i} cx={cx} cy={cy} r={R * f} fill="none" stroke={E.grid} strokeWidth="1" />)}
      {/* radar sweep */}
      <g style={{ transformOrigin: `${cx}px ${cy}px`, animation: "eagle-radar 8s linear infinite" }}>
        <path d={`M${cx} ${cy} L${cx + R} ${cy} A${R} ${R} 0 0 1 ${polar(40, R)[0]} ${polar(40, R)[1]} Z`} fill={E.gateway} opacity="0.05" />
      </g>
      {/* source → org arcs */}
      {origins.map((o, i) => {
        const [ox, oy] = polar(o.ang, R * (0.86 + o.r * 0.12)); const c = o.hero ? E.guard : E.gateway;
        return (
          <g key={"o" + i} opacity={on ? 1 : 0} style={{ transition: `opacity .5s ${i * 80}ms` }}>
            <path d={arc(ox, oy)} fill="none" stroke={c} strokeWidth={o.hero ? 1.8 : 1.1} strokeOpacity={o.hero ? 0.8 : 0.45} strokeDasharray="4 6" style={{ animation: `eagle-flow 1.${2 + i}s linear infinite` }} />
            {o.hero && <circle cx={ox} cy={oy} r="8" fill="none" stroke={c} strokeWidth="1.4" style={{ transformOrigin: `${ox}px ${oy}px`, animation: "eagle-ping 1.8s ease-out infinite" }} />}
            <circle cx={ox} cy={oy} r={3 + o.intensity} fill={c} />
            <text x={ox} y={oy < cy ? oy - 9 : oy + 16} textAnchor="middle" fontSize="8.5" fontWeight={o.hero ? 700 : 500} fill={o.hero ? c : E.muted} fontFamily={E.mono}>{o.ip}</text>
          </g>
        );
      })}
      {/* org → internal targets */}
      {targets.map((t, i) => {
        const [tx, ty] = polar(t.ang, rT); const c = sevColor[t.sev] || E.gateway;
        return (
          <g key={"t" + i} opacity={on ? 1 : 0} style={{ transition: `opacity .5s ${300 + i * 80}ms` }}>
            <line x1={cx} y1={cy} x2={tx} y2={ty} stroke={c} strokeWidth="1" strokeOpacity="0.5" />
            <rect x={tx - 3} y={ty - 3} width="6" height="6" rx="1" fill={c} />
            <text x={tx} y={ty < cy ? ty - 6 : ty + 12} textAnchor="middle" fontSize="7.5" fill={E.muted} fontFamily={E.mono}>{t.label}</text>
          </g>
        );
      })}
      {/* org core */}
      <circle cx={cx} cy={cy} r="26" fill="none" stroke={E.gateway} strokeWidth="1" strokeOpacity="0.35" style={{ transformOrigin: `${cx}px ${cy}px`, animation: "eagle-ping 2.6s ease-out infinite" }} />
      <circle cx={cx} cy={cy} r="16" fill={E.surface} stroke={E.gateway} strokeWidth="1.5" />
      <text x={cx} y={cy + 5} textAnchor="middle" fontSize="16" fill={E.gateway}>◉</text>
      <text x={cx} y={cy + 30} textAnchor="middle" fontSize="8" fontWeight="700" fill={E.text2} fontFamily={E.mono}>ACME · 10.0.0.0/8</text>
    </svg>
  );
}

/* ---- detections by kill-chain stage (mini funnel) ----------- */
function KillChain({ data, height = 150 }) {
  const E = useE(); const on = useReveal();
  const max = Math.max(...data.map((d) => d.count));
  return (
    <div className="flex items-end gap-1.5" style={{ height }}>
      {data.map((d, i) => {
        const h = (d.count / max) * (height - 30);
        const c = `color-mix(in oklab, ${E.gateway} ${100 - i * 9}%, ${E.guard})`;
        return (
          <div key={d.stage} className="flex flex-1 flex-col items-center justify-end gap-1" title={`${d.stage}: ${d.count} detections`}>
            <span className="text-[10px] font-bold tabular-nums" style={{ fontFamily: E.mono, color: E.text2 }}>{d.count}</span>
            <div className="w-full rounded-t" style={{ height: on ? h : 0, background: c, transition: `height .7s cubic-bezier(.22,1,.36,1) ${i * 50}ms`, minHeight: 4 }} />
            <span className="w-full truncate text-center text-[8.5px] uppercase tracking-wide" style={{ color: E.muted, fontFamily: E.mono }}>{d.short}</span>
          </div>
        );
      })}
    </div>
  );
}

/* ---- AI agent activity feed --------------------------------- */
function AgentActivity({ items }) {
  const E = useE();
  return (
    <div className="lr-scroll space-y-0 overflow-y-auto" style={{ maxHeight: 232 }}>
      {items.map((a, i) => {
        const c = E[a.ck] || E.agent;
        return (
          <div key={i} className="flex items-start gap-2.5 border-b py-2 last:border-0" style={{ borderColor: E.border }}>
            <span className="mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md" style={{ background: c + "1a", color: c }}><window.Icon name={a.icon} size={13} /></span>
            <span className="flex-1 text-[11.5px] leading-snug" style={{ color: E.text2 }}>{a.text}</span>
            <span className="shrink-0 text-[9.5px] tabular-nums" style={{ color: E.muted, fontFamily: E.mono }}>{a.time}</span>
          </div>
        );
      })}
    </div>
  );
}

/* ---- live event ticker -------------------------------------- */
function EventTicker({ events, rows = 5 }) {
  const E = useE();
  const list = [...events, ...events];
  return (
    <div className="relative overflow-hidden" style={{ height: rows * 34 }}>
      <div style={{ animation: `eagle-tickup ${events.length * 2.6}s linear infinite` }}>
        {list.map((ev, i) => (
          <div key={i} className="flex h-[34px] items-center gap-2.5 border-b text-[12px]" style={{ borderColor: E.border }}>
            <span className="w-20 shrink-0 text-[9.5px] font-bold uppercase tracking-wider" style={{ color: E[ev.ck], fontFamily: E.mono }}>{ev.t}</span>
            <span className="truncate" style={{ color: E.text2 }}>{ev.m}</span>
          </div>
        ))}
      </div>
      <div className="pointer-events-none absolute inset-x-0 bottom-0 h-8" style={{ background: `linear-gradient(transparent, ${E.surface})` }} />
    </div>
  );
}

Object.assign(window, { useReveal, Sparkline, AreaStack, Donut, HBars, RadialGauge, MitreHeatmap, ThreatMap, KillChain, AgentActivity, EventTicker });
