// admin-mission-control.jsx — Mission Control v2 (Trello #186)
// LIVE multi-agent monitoring. All data comes from the agent-runs edge
// function (agent_runs table — every GHA workflow, Cowork scheduled task and
// edge cron writes a heartbeat at start + finish).
//
// Tabs:
//   • Agents     — 6 personas, expandable to the real automations under each:
//                  live "running now" rows with elapsed timers, utilization,
//                  success rate, avg duration, cost.
//   • Live Tasks — Trello mirror of 🔄 Building + 🧪 Ready to Test with
//                  claimer + elapsed time (needs trello creds synced by the
//                  Daily PM workflow; falls back to agent_runs-derived view).

(function () {
  const { useState: useS, useEffect: useE, useMemo: useM } = React;
  const Icon = window.Icon;

  const SUPABASE_URL = 'https://iwvlmpgeodctctmaacja.supabase.co';
  const REFRESH_MS = 45000;

  // ── Personas ──────────────────────────────────────────────────────
  const AGENT_META = {
    'Coordinator':    { color: '#6366F1', short: 'CO', desc: 'Orchestration & deploys' },
    'Email Agent':    { color: '#F97316', short: 'EM', desc: 'Newsletters & email sends' },
    'Content Agent':  { color: '#10B981', short: 'CA', desc: 'Blog posts & video scripts' },
    'Project Agent':  { color: '#3B82F6', short: 'PA', desc: 'Trello PM, prompts & briefings' },
    'Funnel Builder': { color: '#EC4899', short: 'FB', desc: 'Templates & niche scouting' },
    'Ops Agent':      { color: '#8B5CF6', short: 'OA', desc: 'Health checks, reports & watchdogs' },
  };
  const AGENT_ORDER = Object.keys(AGENT_META);

  // Known runners → where they run (shown even before their first heartbeat).
  const KNOWN_RUNNERS = {
    'gha:daily-pm':                { agent: 'Project Agent', label: 'Daily PM Workflow', where: 'GitHub Actions · 5am ET' },
    'cowork:prompt-writer':        { agent: 'Project Agent', label: 'Prompt Writer', where: 'Cowork task · ~9am ET' },
    'gha:daily-dev-summary':       { agent: 'Project Agent', label: 'Daily Dev Summary', where: 'GitHub Actions · daily' },
    'cowork:daily-blog':           { agent: 'Content Agent', label: 'Daily Blog Post', where: 'Cowork task · ~3am ET' },
    'cowork:daily-video-script':   { agent: 'Content Agent', label: 'Daily Video Script', where: 'Cowork task · ~4am ET' },
    'gha:niche-scout':             { agent: 'Funnel Builder', label: 'Daily Niche Scout', where: 'GitHub Actions · daily' },
    'cowork:lead-routing-health-check': { agent: 'Ops Agent', label: 'Lead Routing Health Check', where: 'Cowork task · ~6am ET' },
    'gha:daily-user-summary':      { agent: 'Ops Agent', label: 'Daily User Summary', where: 'GitHub Actions · 11:05pm ET' },
    'gha:weekly-speed-audit':      { agent: 'Ops Agent', label: 'Weekly Funnel Speed Audit', where: 'GitHub Actions · Mon 5am ET' },
    'gha:routing-regression':      { agent: 'Ops Agent', label: 'Routing Regression Suite', where: 'GitHub Actions · on routing PRs' },
    'gha:site-health-check':       { agent: 'Ops Agent', label: 'Site Health Check', where: 'GitHub Actions' },
    'edge:distribution-watchdog':  { agent: 'Ops Agent', label: 'Distribution Watchdog', where: 'Supabase cron · 9:15pm ET' },
    'edge:daily-distribution-report': { agent: 'Ops Agent', label: 'Daily Distribution Report', where: 'Supabase cron · 8am ET' },
    'edge:weekly-funnel-digest':   { agent: 'Ops Agent', label: 'Weekly Funnel Digest', where: 'Supabase cron · Mon 9am ET' },
    'execute-queue':               { agent: 'Coordinator', label: 'Execute Queue (build cards)', where: 'Cowork session' },
  };

  // ── Helpers ───────────────────────────────────────────────────────
  const fmtDur = (sec) => {
    if (sec == null) return '—';
    sec = Math.round(sec);
    if (sec < 60) return `${sec}s`;
    if (sec < 3600) return `${Math.floor(sec / 60)}m ${sec % 60}s`;
    return `${Math.floor(sec / 3600)}h ${Math.floor((sec % 3600) / 60)}m`;
  };
  const fmtAgo = (iso) => {
    if (!iso) return '—';
    const s = (Date.now() - new Date(iso).getTime()) / 1000;
    if (s < 60) return 'just now';
    if (s < 3600) return `${Math.floor(s / 60)}m ago`;
    if (s < 86400) return `${Math.floor(s / 3600)}h ago`;
    return `${Math.floor(s / 86400)}d ago`;
  };
  const fmtTime = (iso) => iso ? new Date(iso).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : '—';
  const runnerLabel = (runner) => KNOWN_RUNNERS[runner]?.label || runner;

  function Badge({ children, color, bg, border }) {
    return <span style={{ fontSize: 10, fontWeight: 800, color, background: bg, border: `1px solid ${border}`, borderRadius: 999, padding: '2px 8px', whiteSpace: 'nowrap' }}>{children}</span>;
  }
  function StatusBadge({ status }) {
    if (status === 'running') return <Badge color="#1D4ED8" bg="#EFF6FF" border="#BFDBFE">● RUNNING</Badge>;
    if (status === 'failed') return <Badge color="#991B1B" bg="#FEF2F2" border="#FECACA">✕ FAILED</Badge>;
    return <Badge color="#065F46" bg="#ECFDF5" border="#A7F3D0">✓ OK</Badge>;
  }
  function Card({ children, style }) {
    return <div style={{ background: '#fff', border: '1px solid #E5E7EB', borderRadius: 14, padding: 20, ...style }}>{children}</div>;
  }
  function Stat({ label, value, sub }) {
    return (
      <div style={{ minWidth: 90 }}>
        <div style={{ fontSize: 20, fontWeight: 900, color: '#1A2B3B', lineHeight: 1.1 }}>{value}</div>
        <div style={{ fontSize: 10, fontWeight: 700, color: '#9CA3AF', textTransform: 'uppercase', letterSpacing: '.05em', marginTop: 3 }}>{label}</div>
        {sub && <div style={{ fontSize: 10, color: '#C4C9D0' }}>{sub}</div>}
      </div>
    );
  }

  // ── Page ──────────────────────────────────────────────────────────
  function MissionControlPage() {
    const [tab, setTab] = useS('agents');
    const [days, setDays] = useS(7);
    const [data, setData] = useS(null);        // overview payload
    const [tasks, setTasks] = useS(null);      // live_tasks payload
    const [err, setErr] = useS(null);
    const [loading, setLoading] = useS(true);
    const [expanded, setExpanded] = useS({});  // persona → bool
    const [, setTick] = useS(0);               // 1s tick for elapsed timers
    const [lastSync, setLastSync] = useS(null);

    const adminEmail = window.AdminAuth?.get()?.email || window.MOCK?.admin?.email || '';

    const call = async (action, extra = {}) => {
      const r = await fetch(`${SUPABASE_URL}/functions/v1/agent-runs`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ action, admin_email: adminEmail, ...extra }),
      });
      const d = await r.json();
      if (!r.ok) throw new Error(d.error || `${action} failed`);
      return d;
    };

    const load = async () => {
      try {
        setErr(null);
        const [ov, lt] = await Promise.all([call('overview', { days }), call('live_tasks')]);
        setData(ov); setTasks(lt); setLastSync(new Date());
      } catch (e) { setErr(e.message); }
      finally { setLoading(false); }
    };

    useE(() => { if (adminEmail) { setLoading(true); load(); } }, [adminEmail, days]);
    useE(() => { const t = setInterval(() => { if (adminEmail) load(); }, REFRESH_MS); return () => clearInterval(t); }, [adminEmail, days]);
    useE(() => { const t = setInterval(() => setTick(x => x + 1), 1000); return () => clearInterval(t); }, []);

    const running = data?.running || [];
    const recent = data?.recent || [];
    const agents = data?.agents || {};
    const runnersAgg = data?.runners || {};

    // Merge known runners with observed ones, grouped by persona.
    const runnersByAgent = useM(() => {
      const map = {};
      AGENT_ORDER.forEach(a => { map[a] = {}; });
      Object.entries(KNOWN_RUNNERS).forEach(([runner, meta]) => {
        map[meta.agent][runner] = { runner, label: meta.label, where: meta.where, agg: null };
      });
      Object.entries(runnersAgg).forEach(([key, agg]) => {
        const parts = key.split('|');
        const agent = parts[0], runner = parts[1];
        if (!map[agent]) map[agent] = {};
        if (!map[agent][runner]) map[agent][runner] = { runner, label: runnerLabel(runner), where: (KNOWN_RUNNERS[runner] || {}).where || '', agg: null };
        map[agent][runner].agg = agg;
      });
      return map;
    }, [runnersAgg]);

    const totals = useM(() => {
      const finished = recent.filter(r => r.status !== 'running');
      const ok = finished.filter(r => r.status === 'succeeded').length;
      const cost = recent.reduce((s, r) => s + (Number(r.cost_usd) || 0), 0);
      const busy = Object.values(agents).reduce((s, a) => s + (a.busy_seconds || 0), 0);
      return {
        running: running.length,
        runs: recent.length === 200 ? '200+' : recent.length,
        success: finished.length ? `${Math.round((ok / finished.length) * 100)}%` : '—',
        busy: fmtDur(busy),
        cost: cost > 0 ? `$${cost.toFixed(2)}` : '—',
      };
    }, [data]);

    const elapsed = (iso) => fmtDur((Date.now() - new Date(iso).getTime()) / 1000);

    // ── Render pieces ─────────────────────────────────────────────
    const renderRunningRow = (r) => (
      <div key={r.id} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 12px', background: '#EFF6FF', border: '1px solid #BFDBFE', borderRadius: 10, flexWrap: 'wrap' }}>
        <span style={{ width: 8, height: 8, borderRadius: '50%', background: '#3B82F6', animation: 'mcpulse 1.5s infinite' }} />
        <span style={{ fontSize: 12, fontWeight: 800, color: '#1A2B3B' }}>{r.task_title}</span>
        <span style={{ fontSize: 11, color: '#6B7280' }}>{runnerLabel(r.runner)}</span>
        {r.trello_card && <a href={`https://trello.com/c/${r.trello_card}`} target="_blank" rel="noreferrer" style={{ fontSize: 11, color: '#F97316', fontWeight: 700, textDecoration: 'none' }}>#{r.trello_card}</a>}
        <div style={{ flex: 1 }} />
        <span style={{ fontSize: 12, fontWeight: 900, color: '#1D4ED8', fontVariantNumeric: 'tabular-nums' }}>⏱ {elapsed(r.started_at)}</span>
      </div>
    );

    const renderAgentCard = (agent) => {
      const meta = AGENT_META[agent];
      const agg = agents[agent];
      const agentRunning = running.filter(r => r.agent === agent);
      const isOpen = !!expanded[agent];
      const runnerList = Object.values(runnersByAgent[agent] || {});
      const agentRecent = recent.filter(r => r.agent === agent).slice(0, 8);
      return (
        <Card key={agent} style={{ padding: 0, overflow: 'hidden' }}>
          <div onClick={() => setExpanded(e => ({ ...e, [agent]: !isOpen }))}
               style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '16px 20px', cursor: 'pointer', flexWrap: 'wrap' }}>
            <div style={{ width: 38, height: 38, borderRadius: 10, background: meta.color, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 900, fontSize: 13, flexShrink: 0 }}>{meta.short}</div>
            <div style={{ minWidth: 0 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                <span style={{ fontSize: 14, fontWeight: 800, color: '#1A2B3B' }}>{agent}</span>
                {agentRunning.length > 0
                  ? <Badge color="#1D4ED8" bg="#EFF6FF" border="#BFDBFE">● {agentRunning.length} RUNNING</Badge>
                  : <Badge color="#6B7280" bg="#F9FAFB" border="#E5E7EB">idle · last {fmtAgo(agg && agg.last_run_at)}</Badge>}
              </div>
              <div style={{ fontSize: 11, color: '#9CA3AF', marginTop: 2 }}>{meta.desc}</div>
            </div>
            <div style={{ flex: 1 }} />
            <div style={{ display: 'flex', gap: 22, alignItems: 'center', flexWrap: 'wrap' }}>
              <Stat label="Runs" value={(agg && agg.runs) || 0} />
              <Stat label="Success" value={agg && agg.success_rate != null ? `${agg.success_rate}%` : '—'} />
              <Stat label="Busy" value={fmtDur((agg && agg.busy_seconds) || 0)} />
              <Stat label="Avg" value={fmtDur(agg && agg.avg_duration_seconds)} />
              <Stat label="Cost" value={agg && agg.cost_usd ? `$${agg.cost_usd.toFixed(2)}` : '—'} />
            </div>
            <span style={{ fontSize: 11, color: '#9CA3AF', transform: isOpen ? 'rotate(90deg)' : 'none', transition: 'transform .15s' }}>▶</span>
          </div>

          {agentRunning.length > 0 && (
            <div style={{ padding: '0 20px 12px', display: 'flex', flexDirection: 'column', gap: 6 }}>
              {agentRunning.map(renderRunningRow)}
            </div>
          )}

          {isOpen && (
            <div style={{ borderTop: '1px solid #F3F4F6', padding: '14px 20px 18px', background: '#FAFBFC' }}>
              <div style={{ fontSize: 10, fontWeight: 800, color: '#9CA3AF', textTransform: 'uppercase', letterSpacing: '.05em', marginBottom: 8 }}>Automations</div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 4, marginBottom: 14 }}>
                {runnerList.map(rn => (
                  <div key={rn.runner} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, padding: '5px 0', borderBottom: '1px solid #F3F4F6', flexWrap: 'wrap' }}>
                    <span style={{ fontWeight: 700, color: '#1A2B3B' }}>{rn.label}</span>
                    <span style={{ fontSize: 10, color: '#9CA3AF' }}>{rn.where}</span>
                    <div style={{ flex: 1 }} />
                    {rn.agg ? (
                      <span style={{ fontSize: 11, color: '#6B7280', fontVariantNumeric: 'tabular-nums' }}>
                        {rn.agg.runs} runs · {rn.agg.success_rate != null ? `${rn.agg.success_rate}% ok` : '—'} · avg {fmtDur(rn.agg.avg_duration_seconds)} · last {fmtAgo(rn.agg.last_run_at)}
                      </span>
                    ) : (
                      <span style={{ fontSize: 11, color: '#C4C9D0' }}>no runs yet in window</span>
                    )}
                  </div>
                ))}
                {runnerList.length === 0 && <div style={{ fontSize: 12, color: '#9CA3AF' }}>No automations registered yet.</div>}
              </div>
              {agentRecent.length > 0 && <React.Fragment>
                <div style={{ fontSize: 10, fontWeight: 800, color: '#9CA3AF', textTransform: 'uppercase', letterSpacing: '.05em', marginBottom: 8 }}>Recent runs</div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                  {agentRecent.map(r => (
                    <div key={r.id} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 11, color: '#6B7280', flexWrap: 'wrap' }}>
                      <StatusBadge status={r.status} />
                      <span style={{ fontWeight: 700, color: '#374151' }}>{r.task_title}</span>
                      <span>{fmtTime(r.started_at)}</span>
                      {r.finished_at && <span>· {fmtDur((new Date(r.finished_at) - new Date(r.started_at)) / 1000)}</span>}
                      {r.detail && <span style={{ color: '#9CA3AF' }}>· {r.detail}</span>}
                      {r.log_url && <a href={r.log_url} target="_blank" rel="noreferrer" style={{ color: '#3B82F6', textDecoration: 'none', fontWeight: 700 }}>logs ↗</a>}
                      {r.trello_card && <a href={`https://trello.com/c/${r.trello_card}`} target="_blank" rel="noreferrer" style={{ color: '#F97316', textDecoration: 'none', fontWeight: 700 }}>card ↗</a>}
                    </div>
                  ))}
                </div>
              </React.Fragment>}
            </div>
          )}
        </Card>
      );
    };

    const renderLiveTasks = () => {
      if (!tasks) return null;
      if (!tasks.trello) {
        return (
          <Card style={{ background: '#FFFBEB', border: '1px solid #FDE68A' }}>
            <div style={{ fontSize: 13, fontWeight: 800, color: '#92400E', marginBottom: 6 }}>⏳ Trello mirror not connected yet</div>
            <p style={{ fontSize: 12, color: '#78350F', lineHeight: 1.6, margin: 0 }}>
              The Daily PM workflow (5am ET) syncs Trello credentials automatically — or trigger it manually in GitHub Actions to connect now.
              Until then, here's what agents report they're building:
            </p>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: 12 }}>
              {running.length > 0 ? running.map(renderRunningRow) : <span style={{ fontSize: 12, color: '#9CA3AF' }}>Nothing running right now.</span>}
            </div>
          </Card>
        );
      }
      return (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, alignItems: 'start' }}>
          {tasks.lists.map(list => (
            <Card key={list.listName} style={{ padding: 16 }}>
              <div style={{ fontSize: 13, fontWeight: 800, color: '#1A2B3B', marginBottom: 10 }}>{list.listName} <span style={{ color: '#9CA3AF', fontWeight: 600 }}>({list.cards.length})</span></div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                {list.cards.map(c => (
                  <a key={c.shortLink} href={c.url} target="_blank" rel="noreferrer" style={{ display: 'block', padding: '10px 12px', background: '#FAFBFC', border: '1px solid #EDF0F3', borderRadius: 10, textDecoration: 'none' }}>
                    <div style={{ fontSize: 12, fontWeight: 700, color: '#1A2B3B' }}>{c.name}</div>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 5, flexWrap: 'wrap' }}>
                      {c.claimed_by ? (
                        <Badge color="#1D4ED8" bg="#EFF6FF" border="#BFDBFE">● {c.claimed_by.agent} · {elapsed(c.claimed_by.started_at)}</Badge>
                      ) : (
                        <span style={{ fontSize: 10, color: '#9CA3AF' }}>last activity {fmtAgo(c.last_activity)}</span>
                      )}
                      {(c.labels || []).slice(0, 3).map((l, i) => <Badge key={i} color="#6B7280" bg="#F9FAFB" border="#E5E7EB">{l}</Badge>)}
                    </div>
                  </a>
                ))}
                {list.cards.length === 0 && <span style={{ fontSize: 12, color: '#C4C9D0' }}>Empty</span>}
              </div>
            </Card>
          ))}
        </div>
      );
    };

    // ── Layout ────────────────────────────────────────────────────
    return (
      <div style={{ maxWidth: 960, display: 'flex', flexDirection: 'column', gap: 16 }}>
        <style>{`@keyframes mcpulse { 0%,100% { opacity: 1 } 50% { opacity: .35 } }`}</style>

        <div style={{ display: 'flex', alignItems: 'flex-end', gap: 14, flexWrap: 'wrap' }}>
          <div>
            <h2 style={{ fontSize: 18, fontWeight: 800, color: '#1A2B3B', marginBottom: 4 }}>Mission Control</h2>
            <p style={{ fontSize: 13, color: '#6B7280', margin: 0 }}>Live view of every agent — what's executing, by whom, and how long it takes.</p>
          </div>
          <div style={{ flex: 1 }} />
          <div style={{ display: 'flex', gap: 6 }}>
            {[7, 30].map(d => (
              <button key={d} onClick={() => setDays(d)} style={{ padding: '5px 12px', borderRadius: 8, fontSize: 11, fontWeight: 800, cursor: 'pointer', fontFamily: 'inherit', border: '1px solid', borderColor: days === d ? '#F97316' : '#E5E7EB', background: days === d ? '#FFF7ED' : '#fff', color: days === d ? '#C2410C' : '#6B7280' }}>{d}d</button>
            ))}
          </div>
          {lastSync && <span style={{ fontSize: 10, color: '#C4C9D0' }}>synced {fmtAgo(lastSync.toISOString())} · auto-refresh 45s</span>}
        </div>

        {err && <Card style={{ background: '#FEF2F2', border: '1px solid #FECACA' }}><span style={{ fontSize: 12, color: '#991B1B', fontWeight: 600 }}>⚠️ {err}</span></Card>}
        {loading && <Card><span style={{ fontSize: 13, color: '#9CA3AF' }}>Loading live data…</span></Card>}

        {!loading && data && <React.Fragment>
          <Card style={{ display: 'flex', gap: 28, flexWrap: 'wrap', alignItems: 'center' }}>
            <Stat label="Running now" value={totals.running} />
            <Stat label={`Runs (${days}d)`} value={totals.runs} />
            <Stat label="Success rate" value={totals.success} />
            <Stat label="Total busy" value={totals.busy} />
            <Stat label="Cost tracked" value={totals.cost} />
            <div style={{ flex: 1 }} />
            {running.length === 0 && <span style={{ fontSize: 12, color: '#9CA3AF' }}>😴 All agents idle</span>}
          </Card>

          <div style={{ display: 'flex', gap: 6 }}>
            {[['agents', '🤖 Agents'], ['tasks', '📋 Live Tasks']].map(([id, label]) => (
              <button key={id} onClick={() => setTab(id)} style={{ padding: '8px 16px', borderRadius: 10, fontSize: 12, fontWeight: 800, cursor: 'pointer', fontFamily: 'inherit', border: '1px solid', borderColor: tab === id ? '#1A2B3B' : '#E5E7EB', background: tab === id ? '#1A2B3B' : '#fff', color: tab === id ? '#fff' : '#6B7280' }}>{label}</button>
            ))}
          </div>

          {tab === 'agents' && (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
              {AGENT_ORDER.map(renderAgentCard)}
            </div>
          )}
          {tab === 'tasks' && renderLiveTasks()}
        </React.Fragment>}
      </div>
    );
  }

  window.MissionControlPage = MissionControlPage;
})();
