// AGENTS view — terminal-style live ops feed.

const { useState: useStateA, useEffect: useEffectA } = React;

function Agents({ data }) {
  const [tick, setTick] = useStateA(0);
  const [filter, setFilter] = useStateA("all");

  // Live approval queue from the orchestrator manager. Hardcoded mock data
  // was previously used here — buttons looked clickable but did nothing,
  // which is why the user reported "APPROVE button not working". Now we
  // poll /api/admin/manager/pending and wire the buttons to the real
  // /api/admin/manager/decide endpoint.
  const [pending, setPending] = useStateA([]);
  const [pendingState, setPendingState] = useStateA('loading'); // loading | empty | ready | error
  const [busyId, setBusyId] = useStateA(null);   // the approval id mid-decision
  const [errMsg, setErrMsg] = useStateA(null);

  // Live event-bus tail. Was a 13-line hardcoded fake (stripe.com / probe.gemini /
  // cited:7,n:8 etc) — same class of bug as the now-killed status-tag mocks.
  // Now fetched from /api/admin/orchestrator/bus and re-rendered every 5s.
  const [events, setEvents] = useStateA([]);
  const [eventsState, setEventsState] = useStateA('loading');
  const fetchEvents = React.useCallback(async () => {
    try {
      const r = await fetch('/api/admin/orchestrator/bus?limit=30');
      const j = await r.json();
      if (!j?.ok) throw new Error(j?.error || 'fetch failed');
      const items = Array.isArray(j.events) ? j.events : [];
      setEvents(items);
      setEventsState(items.length ? 'ready' : 'empty');
    } catch (e) {
      setEventsState('error');
    }
  }, []);

  const fetchPending = React.useCallback(async () => {
    try {
      const r = await fetch('/api/admin/manager/pending');
      const j = await r.json();
      if (!j?.ok) throw new Error(j?.error || 'fetch failed');
      const items = Array.isArray(j.pending) ? j.pending : [];
      setPending(items);
      setPendingState(items.length ? 'ready' : 'empty');
      setErrMsg(null);
    } catch (e) {
      setPendingState('error');
      setErrMsg(String(e?.message || e));
    }
  }, []);

  const decide = React.useCallback(async (id, decision) => {
    setBusyId(id);
    try {
      const r = await fetch('/api/admin/manager/decide', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ id, decision, by: 'admin-ui' })
      });
      const j = await r.json();
      if (!j?.ok) throw new Error(j?.error || 'decide failed');
      // Optimistically remove from the local list, then refresh from server.
      setPending(p => p.filter(x => x.id !== id));
      fetchPending();
    } catch (e) {
      setErrMsg(`${decision} failed: ${String(e?.message || e)}`);
    } finally {
      setBusyId(null);
    }
  }, [fetchPending]);

  useEffectA(() => {
    fetchPending();
    const poll = setInterval(fetchPending, 30000);
    return () => clearInterval(poll);
  }, [fetchPending]);

  useEffectA(() => {
    fetchEvents();
    const poll = setInterval(fetchEvents, 5000);  // fast poll — bus changes often
    return () => clearInterval(poll);
  }, [fetchEvents]);

  useEffectA(() => {
    const id = setInterval(() => setTick(t => t + 1), 2000);
    return () => clearInterval(id);
  }, []);

  const agents = [
    { id: "spider.retrieval",     icon: "▣", name: "Spider · Retrieval",     interval: "6h",  score: 0.82 },
    { id: "spider.citation",      icon: "❝", name: "Spider · Citation",      interval: "12h", score: 0.71 },
    { id: "spider.intent",        icon: "◎", name: "Spider · Intent",        interval: "12h", score: 0.69 },
    { id: "spider.entity",        icon: "✦", name: "Spider · Entity",        interval: "24h", score: 0.94 },
    { id: "spider.trust",         icon: "△", name: "Spider · Trust",         interval: "24h", score: 0.88 },
    { id: "spider.freshness",     icon: "↻", name: "Spider · Freshness",     interval: "1h",  score: 0.42 },
    { id: "spider.actionability", icon: "▶", name: "Spider · Actionability", interval: "12h", score: 0.86 },
    { id: "spider.multimodal",    icon: "▤", name: "Spider · Multimodal",    interval: "24h", score: 0.55 },
    { id: "probe.chatgpt",        icon: "◐", name: "Probe · ChatGPT",        interval: "6h",  score: 0.84 },
    { id: "probe.claude",         icon: "◑", name: "Probe · Claude",         interval: "6h",  score: 0.76 },
    { id: "probe.gemini",         icon: "◒", name: "Probe · Gemini",         interval: "6h",  score: 0.61 },
    { id: "probe.perplexity",     icon: "◓", name: "Probe · Perplexity",     interval: "6h",  score: 0.91 },
    { id: "meta.learner",         icon: "Σ", name: "Meta · Learner",         interval: "1d",  score: 0.78 },
    { id: "guard.hard-filter",    icon: "✕", name: "Guard · Hard Filter",    interval: "on-scan", score: 1.00 },
  ];

  const filteredFeed = data.feed.filter(f => filter === "all" || f.sev === filter);

  return (
    <div className="view">
      {/* status strip */}
      <div style={{ padding: "10px 24px", borderBottom: "1px solid var(--line)", display: "flex", justifyContent: "space-between", fontSize: 11, color: "var(--ink-dim)" }}>
        <div style={{ display: "flex", gap: 24 }}>
          <span><span className="cap" style={{ color: "var(--accent)" }}>● LIVE</span> AGENT OPS</span>
          <span><span className="cap">SESSION:</span> {String(tick).padStart(4,"0")}</span>
          <span><span className="cap">UPTIME:</span> 14d 06h 22m</span>
          <span><span className="cap">QUEUE:</span> 7</span>
          <span><span className="cap">PENDING APPROVALS:</span> <span style={{ color: "var(--warn)" }}>2</span></span>
        </div>
        <div className="muted">REFRESH 2s · MANAGER: <span className="up">ONLINE</span> · BUS: <span className="up">ONLINE</span></div>
      </div>

      {/* KPIs */}
      <div className="kpis">
        <div><div className="k">AGENTS</div><div className="v tabular">{agents.length}<small>online</small></div></div>
        <div><div className="k">ENROLLED</div><div className="v tabular">{data.enrolledDomains.length}<small>domains</small></div></div>
        <div><div className="k">FINDINGS · 24H</div><div className="v tabular" style={{ color: "var(--warn)" }}>347</div></div>
        <div><div className="k">CRITICAL · 24H</div><div className="v tabular" style={{ color: "var(--crit)" }}>03</div></div>
      </div>

      {/* enrolled domains strip */}
      <section style={{ borderTop: "1px solid var(--line)", borderBottom: "1px solid var(--line)", padding: "14px 24px", display: "flex", gap: 12, flexWrap: "wrap", alignItems: "center" }}>
        <span className="cap muted">ENROLLED ▸</span>
        {data.enrolledDomains.map((d) => (
          <span key={d} style={{ border: "1px solid var(--line-bright)", padding: "4px 10px", color: "var(--ink)", fontSize: 11 }}>
            <span style={{ color: "var(--accent)" }}>●</span> {d}
          </span>
        ))}
        <span style={{ border: "1px dashed var(--line-bright)", padding: "4px 10px", color: "var(--ink-mute)", fontSize: 11 }}>
          + add domain
        </span>
      </section>

      {/* main grid */}
      <section style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", borderBottom: "1px solid var(--line)" }}>

        {/* live feed */}
        <div style={{ borderRight: "1px solid var(--line)" }}>
          <div className="section-h">
            <div>
              <div className="lbl">// LIVE FINDING FEED</div>
              <h2>tail -f /var/log/answena/findings</h2>
            </div>
            <div style={{ display: "flex", gap: 6 }}>
              {["all", "info", "warn", "crit"].map(s => (
                <button key={s}
                  onClick={() => setFilter(s)}
                  style={{
                    background: filter === s ? "var(--accent)" : "transparent",
                    color: filter === s ? "var(--bg)" : "var(--ink-dim)",
                    border: "1px solid var(--line-bright)",
                    padding: "3px 10px", fontSize: 10, letterSpacing: ".12em",
                    textTransform: "uppercase", cursor: "pointer", fontFamily: "var(--font-mono)"
                  }}>
                  {s}
                </button>
              ))}
            </div>
          </div>
          <div className="feed">
            {filteredFeed.map((f, i) => (
              <div key={i} className={`row sev-${f.sev}`}>
                <span className="ts tabular">{f.ts}</span>
                <span className="dot" />
                <span className="agent">{f.agent}</span>
                <span className="msg">{f.msg}</span>
                <span className="dom">{f.domain}</span>
              </div>
            ))}
            <div className="row" style={{ gridTemplateColumns: "64px 14px 1fr", color: "var(--accent)" }}>
              <span className="ts tabular">{new Date().toTimeString().slice(0,8)}</span>
              <span />
              <span>awaiting next event<Caret /></span>
            </div>
          </div>
        </div>

        {/* agents grid */}
        <div>
          <div className="section-h">
            <div>
              <div className="lbl">// AGENT REGISTRY</div>
              <h2>14 workers · health & schedule</h2>
            </div>
          </div>
          <div style={{ maxHeight: 600, overflow: "auto" }}>
            {agents.map((a) => (
              <div key={a.id} style={{ display: "grid", gridTemplateColumns: "32px 1fr auto", gap: 10, alignItems: "center", padding: "12px 18px", borderBottom: "1px solid var(--line)" }}>
                <span style={{ fontSize: 18, color: "var(--accent)", textAlign: "center" }}>{a.icon}</span>
                <div>
                  <div style={{ color: "var(--ink)", fontWeight: 600, fontSize: 12 }}>{a.name}</div>
                  <div className="muted" style={{ fontSize: 10, marginTop: 2 }}>
                    every <span style={{ color: "var(--ink)" }}>{a.interval}</span> · last run <span style={{ color: "var(--ink)" }}>{Math.floor(Math.random() * 60) + 1}m ago</span>
                  </div>
                </div>
                <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  <Segments value={a.score} total={8} />
                  <span className="tabular" style={{ color: "var(--accent)", fontWeight: 700, fontSize: 12, minWidth: 26, textAlign: "right" }}>
                    {(a.score * 100).toFixed(0)}
                  </span>
                </div>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* manager + bus */}
      <section style={{ display: "grid", gridTemplateColumns: "1fr 1fr", borderBottom: "1px solid var(--line)" }}>
        <div style={{ borderRight: "1px solid var(--line)" }}>
          <div className="section-h">
            <div>
              <div className="lbl">// PENDING HUMAN APPROVALS</div>
              <h2>Manager queue · {String(pending.length).padStart(2, "0")} awaiting</h2>
            </div>
            <button
              type="button"
              onClick={fetchPending}
              disabled={pendingState === 'loading'}
              style={{
                background: "transparent", color: "var(--ink-dim)",
                border: "1px solid var(--line-bright)",
                padding: "3px 10px", cursor: "pointer",
                fontFamily: "var(--font-mono)", fontSize: 10, fontWeight: 600,
                letterSpacing: ".1em", textTransform: "uppercase"
              }}>
              [refresh]
            </button>
          </div>
          <div style={{ padding: 18 }}>
            {errMsg && (
              <div style={{ color: "var(--crit)", border: "1px solid var(--crit)", padding: "8px 12px", marginBottom: 10, fontSize: 12, fontFamily: "var(--font-mono)" }}>
                {errMsg}
              </div>
            )}

            {pendingState === 'loading' && (
              <div className="muted" style={{ padding: "20px 0", textAlign: "center", fontSize: 12, fontFamily: "var(--font-mono)" }}>
                Loading approval queue…
              </div>
            )}

            {pendingState === 'empty' && (
              <div className="muted" style={{ padding: "24px 0", textAlign: "center", fontSize: 12, fontFamily: "var(--font-mono)" }}>
                No pending approvals.
                <br/>
                <span style={{ fontSize: 11 }}>Background agents queue items here when they hit a decision gate the auto-rules can't resolve.</span>
              </div>
            )}

            {pendingState === 'error' && (
              <div className="muted" style={{ padding: "20px 0", textAlign: "center", fontSize: 12, fontFamily: "var(--font-mono)" }}>
                Could not load queue. Click [refresh] to retry.
              </div>
            )}

            {pendingState === 'ready' && pending.map((p) => (
              <div key={p.id} style={{ border: "1px solid var(--line-bright)", borderLeft: "3px solid var(--warn)", padding: 14, marginBottom: 10 }}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                  <span style={{ color: "var(--warn)", fontWeight: 700, fontSize: 12, letterSpacing: ".08em", textTransform: "uppercase" }}>{p.kind}</span>
                  <span className="muted" style={{ fontSize: 10 }}>
                    by {p.requestedBy || p.by || 'unknown'}{p.domain ? ` · ${p.domain}` : ''}
                  </span>
                </div>
                <pre style={{ margin: "8px 0", fontSize: 11, color: "var(--ink-dim)", background: "var(--bg)", padding: 8, border: "1px solid var(--line)", overflow: "auto", whiteSpace: "pre-wrap" }}>
                  {typeof p.payload === 'string' ? p.payload : JSON.stringify(p.payload || {}, null, 2)}
                </pre>
                <div style={{ display: "flex", gap: 8, marginTop: 8 }}>
                  <button
                    type="button"
                    disabled={busyId === p.id}
                    onClick={() => decide(p.id, 'approve')}
                    style={{ background: "var(--accent)", color: "var(--bg)", border: 0, padding: "6px 14px", fontSize: 11, fontWeight: 700, letterSpacing: ".1em", cursor: busyId === p.id ? "wait" : "pointer", fontFamily: "var(--font-mono)", opacity: busyId === p.id ? 0.5 : 1 }}>
                    {busyId === p.id ? '…' : 'APPROVE'}
                  </button>
                  <button
                    type="button"
                    disabled={busyId === p.id}
                    onClick={() => decide(p.id, 'reject')}
                    style={{ background: "transparent", color: "var(--crit)", border: "1px solid var(--crit)", padding: "6px 14px", fontSize: 11, fontWeight: 700, letterSpacing: ".1em", cursor: busyId === p.id ? "wait" : "pointer", fontFamily: "var(--font-mono)", opacity: busyId === p.id ? 0.5 : 1 }}>
                    REJECT
                  </button>
                  <button
                    type="button"
                    onClick={() => setPending(list => list.filter(x => x.id !== p.id))}
                    title="Hide locally; the server keeps it pending so it'll come back on next refresh."
                    style={{ background: "transparent", color: "var(--ink-dim)", border: "1px solid var(--line-bright)", padding: "6px 14px", fontSize: 11, letterSpacing: ".1em", cursor: "pointer", fontFamily: "var(--font-mono)" }}>
                    DEFER
                  </button>
                </div>
              </div>
            ))}
          </div>
        </div>

        <div>
          <div className="section-h">
            <div>
              <div className="lbl">// EVENT BUS</div>
              <h2>orchestrator broadcast · last 30</h2>
            </div>
          </div>
          <div style={{ padding: "14px 18px", maxHeight: 380, overflow: "auto", fontSize: 11, lineHeight: 1.7 }}>
            {eventsState === 'loading' && (
              <div className="muted" style={{ padding: "16px 0", textAlign: "center", fontFamily: "var(--font-mono)" }}>
                Loading event bus…
              </div>
            )}
            {eventsState === 'empty' && (
              <div className="muted" style={{ padding: "20px 0", textAlign: "center", fontFamily: "var(--font-mono)", fontSize: 11.5 }}>
                Event bus empty — no orchestrator activity yet.
                <br/>
                <span style={{ fontSize: 10.5 }}>Run a scan or trigger a background agent to populate.</span>
              </div>
            )}
            {eventsState === 'error' && (
              <div className="muted" style={{ padding: "16px 0", textAlign: "center", fontFamily: "var(--font-mono)" }}>
                Could not reach /api/admin/orchestrator/bus.
              </div>
            )}
            {eventsState === 'ready' && events.map((e, i) => {
              const ts = e.at ? new Date(e.at).toTimeString().slice(0, 8) : '—';
              const payloadStr = e.payload == null
                ? ''
                : (typeof e.payload === 'string' ? e.payload : JSON.stringify(e.payload));
              return (
                <div key={i} style={{ display: "grid", gridTemplateColumns: "70px 180px 1fr", gap: 10, padding: "3px 0", borderBottom: "1px dashed var(--line)" }}>
                  <span className="muted tabular">{ts}</span>
                  <span style={{ color: "var(--accent)" }}>{e.topic}</span>
                  <span className="muted" style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }} title={payloadStr}>{payloadStr}</span>
                </div>
              );
            })}
          </div>
        </div>
      </section>

      {/* spider memory chart */}
      <section style={{ borderBottom: "1px solid var(--line)" }}>
        <div className="section-h">
          <div>
            <div className="lbl">// SPIDER SWARM · LEARNING TIMELINE</div>
            <h2>Percentile memory rebuilds every 10 scans.</h2>
          </div>
          <div className="muted">corpus: 2,847 · rebuilds recorded: 284 · top predictor: claim-evidence (r=0.71)</div>
        </div>
        <div style={{ padding: 24 }}>
          <SwarmChart />
        </div>
      </section>
    </div>
  );
}

function SwarmChart() {
  const W = 1200, H = 260, PL = 50, PR = 20, PT = 16, PB = 32;
  const plotW = W - PL - PR, plotH = H - PT - PB;
  const N = 60;
  const spiders = [
    { id: "retrieval",     color: "#5cd1ff", base: 0.65, drift: 0.18 },
    { id: "citation",      color: "#5cff9d", base: 0.55, drift: 0.16 },
    { id: "intent",        color: "#ffb454", base: 0.60, drift: 0.10 },
    { id: "entity",        color: "#b388ff", base: 0.78, drift: 0.06 },
    { id: "trust",         color: "#ff7ad9", base: 0.70, drift: 0.12 },
    { id: "freshness",     color: "#ffd54a", base: 0.42, drift: 0.20 },
    { id: "actionability", color: "#ff9f40", base: 0.72, drift: 0.08 },
    { id: "multimodal",    color: "#aaffe0", base: 0.45, drift: 0.14 },
  ];
  // deterministic pseudo-noise
  const noise = (s, i) => Math.sin(i * 0.23 + s) * 0.5 + Math.cos(i * 0.41 + s * 1.7) * 0.3;
  const xAt = (i) => PL + (i / (N - 1)) * plotW;
  const yAt = (v) => PT + plotH - Math.max(0, Math.min(1, v)) * plotH;

  return (
    <div>
      <svg viewBox={`0 0 ${W} ${H}`} style={{ width: "100%", height: 260, display: "block" }}>
        {/* gridlines */}
        {[0.25, 0.5, 0.75].map(g => (
          <g key={g}>
            <line x1={PL} y1={yAt(g)} x2={W - PR} y2={yAt(g)} stroke="var(--line)" strokeDasharray="2 4" />
            <text x={PL - 8} y={yAt(g) + 4} textAnchor="end" fill="var(--ink-mute)" fontSize="9" fontFamily="var(--font-mono)">{(g*100).toFixed(0)}%</text>
          </g>
        ))}
        {/* x axis ticks */}
        {[0, 0.25, 0.5, 0.75, 1].map(t => {
          const x = PL + t * plotW;
          return <text key={t} x={x} y={H - 10} textAnchor="middle" fill="var(--ink-mute)" fontSize="9" fontFamily="var(--font-mono)">T-{Math.round((1-t) * 60)}d</text>;
        })}
        {/* lines */}
        {spiders.map((s, si) => {
          const pts = Array.from({ length: N }, (_, i) => {
            const v = s.base + s.drift * (i / N) + noise(si, i) * 0.04;
            return `${xAt(i).toFixed(1)},${yAt(v).toFixed(1)}`;
          }).join(" ");
          return <polyline key={s.id} points={pts} fill="none" stroke={s.color} strokeWidth="1.4" opacity="0.9" />;
        })}
      </svg>
      <div style={{ display: "flex", flexWrap: "wrap", gap: 14, marginTop: 8, fontSize: 11 }}>
        {spiders.map(s => (
          <span key={s.id} style={{ color: "var(--ink-dim)", display: "inline-flex", alignItems: "center", gap: 6 }}>
            <span style={{ width: 14, height: 2, background: s.color, display: "inline-block" }} />
            {s.id}
          </span>
        ))}
      </div>
    </div>
  );
}

window.Agents = Agents;
