// Admin views: Dashboard, Domains, Keys, Firehose, Abuse, Health, Audit, Settings
// Wired to backend via window.tmApi (lib/tm-browser.js)

// ================= DASHBOARD =================
const AdminDashboard = ({ toast }) => {
  const [data, setData] = React.useState(null);
  const [err, setErr] = React.useState(null);
  React.useEffect(() => {
    let cancel = false;
    tmApi.admin.overview().then((d) => { if (!cancel) setData(d); }).catch((e) => !cancel && setErr(e));
    return () => { cancel = true; };
  }, []);
  if (err)  return <AdminEmpty title="Failed to load overview" detail={err.message} />;
  if (!data) return <AdminLoading />;
  const { stats, volumeHourly, topDomains } = data;
  return (
    <>
      <AdminPageHeader title="Overview" />
      <div style={{ flex: 1, overflowY: 'auto', padding: 24 }}>
        {/* Stats grid */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, marginBottom: 20 }}>
          {stats.map((s) => (
            <div key={s.label} style={{ background: '#111', border: '1px solid #1f1f1f', borderRadius: 8, padding: 14 }}>
              <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 10 }}>
                <div>
                  <div style={adminStyles.monoLabel}>{s.label}</div>
                  <div style={{ fontSize: 24, fontWeight: 500, color: '#EDEDED', marginTop: 6, fontFamily: "'JetBrains Mono', monospace", letterSpacing: '-0.02em' }}>{s.value}</div>
                </div>
                <Sparkline data={s.spark} width={88} height={32} color={s.trend === 'up' ? '#10B981' : '#F59E0B'} />
              </div>
              <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: s.trend === 'up' ? '#10B981' : '#F59E0B', letterSpacing: '0.05em' }}>
                {s.trend === 'up' ? '↗' : '↘'} {s.delta} <span style={{ color: '#565656' }}>24h</span>
              </div>
            </div>
          ))}
        </div>

        {/* Volume chart + Top domains */}
        <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 12, marginBottom: 20 }}>
          <div style={{ background: '#111', border: '1px solid #1f1f1f', borderRadius: 8, padding: 16 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 14 }}>
              <div>
                <div style={adminStyles.monoLabel}>EMAIL VOLUME · 24H</div>
                <div style={{ fontSize: 18, fontFamily: "'JetBrains Mono', monospace", color: '#EDEDED', marginTop: 4 }}>16,482</div>
              </div>
              <div style={{ display: 'flex', gap: 4 }}>
                {['1H', '24H', '7D', '30D'].map((t, i) => (
                  <span key={t} style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: '0.1em', padding: '3px 7px', borderRadius: 3, background: i === 1 ? '#262626' : 'transparent', color: i === 1 ? '#EDEDED' : '#565656', cursor: 'pointer' }}>{t}</span>
                ))}
              </div>
            </div>
            <Bars data={volumeHourly} width={560} height={120} color="#10B981" highlight={18} />
            <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: "'JetBrains Mono', monospace", fontSize: 9, color: '#404040', marginTop: 8, letterSpacing: '0.08em' }}>
              <span>00:00</span><span>06:00</span><span>12:00</span><span>18:00</span><span>NOW</span>
            </div>
          </div>

          <div style={{ background: '#111', border: '1px solid #1f1f1f', borderRadius: 8, padding: 16 }}>
            <div style={adminStyles.monoLabel}>TOP DOMAINS · 24H</div>
            <div style={{ marginTop: 14 }}>
              {topDomains.map((d) => (
                <div key={d.domain} style={{ marginBottom: 10 }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: "'JetBrains Mono', monospace", fontSize: 11, marginBottom: 4 }}>
                    <span style={{ color: '#EDEDED' }}>@{d.domain}</span>
                    <span style={{ color: '#8A8A8A' }}>{d.count.toLocaleString()}</span>
                  </div>
                  <div style={{ height: 4, background: '#1a1a1a', borderRadius: 2, overflow: 'hidden' }}>
                    <div style={{ height: '100%', width: `${d.pct}%`, background: '#10B981', borderRadius: 2 }} />
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>

        {/* Recent activity preview */}
        <div style={{ background: '#111', border: '1px solid #1f1f1f', borderRadius: 8 }}>
          <div style={{ padding: 16, borderBottom: '1px solid #1a1a1a', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <div style={adminStyles.monoLabel}>RECENT FIREHOSE</div>
            <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: '#10B981', letterSpacing: '0.15em', display: 'flex', alignItems: 'center', gap: 6 }}>
              <span style={{ width: 5, height: 5, borderRadius: '50%', background: '#10B981', animation: 'pulse 2s infinite' }} /> LIVE
            </span>
          </div>
          <DashboardRecentFirehose />
        </div>
      </div>
    </>
  );
};

const DashboardRecentFirehose = () => {
  const [items, setItems] = React.useState(null);
  React.useEffect(() => {
    let cancel = false;
    tmApi.admin.firehose.list({ limit: 5 }).then((r) => !cancel && setItems(r)).catch(() => !cancel && setItems([]));
    return () => { cancel = true; };
  }, []);
  if (!items) return <div style={{ padding: 16, color: '#565656', fontSize: 12 }}>Loading…</div>;
  if (items.length === 0) return <div style={{ padding: 16, color: '#565656', fontSize: 12 }}>No mail yet</div>;
  return (
    <div>
      {items.map((f) => (
        <div key={f.id} style={{ display: 'grid', gridTemplateColumns: '70px 1fr 1fr auto', gap: 12, padding: '9px 16px', borderBottom: '1px solid #151515', alignItems: 'center', fontSize: 12 }}>
          <span style={{ fontFamily: "'JetBrains Mono', monospace", color: '#565656', fontSize: 11 }}>{f.ts}</span>
          <span style={{ fontFamily: "'JetBrains Mono', monospace", color: f.flagged ? '#DC2626' : '#8A8A8A', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', fontSize: 11 }}>{f.from}</span>
          <span style={{ color: '#EDEDED', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{f.subject}</span>
          {f.hasCode && <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: '#10B981', padding: '2px 6px', background: '#0a1f1a', border: '1px solid #1a3f33', borderRadius: 3 }}>⚡ {f.code}</span>}
          {!f.hasCode && <span />}
        </div>
      ))}
    </div>
  );
};

// Shared loading + empty placeholders
const AdminLoading = () => (
  <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#565656', fontFamily: "'JetBrains Mono', monospace", fontSize: 11, letterSpacing: '0.2em' }}>
    LOADING…
  </div>
);
const AdminEmpty = ({ title, detail }) => (
  <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', color: '#8A8A8A', gap: 6 }}>
    <div style={{ fontSize: 13 }}>{title}</div>
    {detail && <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: '#565656' }}>{detail}</div>}
  </div>
);

// ================= DOMAINS =================
const AdminDomains = ({ toast }) => {
  const [domains, setDomains] = React.useState(null);
  const [adding, setAdding] = React.useState(false);
  const [newDomain, setNewDomain] = React.useState('');
  const [dnsModalDomain, setDnsModalDomain] = React.useState(null);

  const reload = () => tmApi.admin.domains.list().then(setDomains).catch((e) => toast('Load failed: ' + e.message));
  React.useEffect(() => { reload(); }, []);
  if (!domains) return <AdminLoading />;

  const toggle = async (id, enabled) => {
    try {
      await tmApi.admin.domains.patch(id, { enabled: !enabled });
      reload();
      toast('Domain toggled');
    } catch (e) { toast('Toggle failed: ' + e.message); }
  };
  const remove = async (id) => {
    try {
      await tmApi.admin.domains.remove(id);
      reload();
      toast('Domain removed');
    } catch (e) { toast('Remove failed: ' + e.message); }
  };
  const add = async () => {
    if (!/^[a-z0-9][a-z0-9-]*(\.[a-z0-9][a-z0-9-]*)+$/i.test(newDomain)) return;
    const target = newDomain;
    try {
      await tmApi.admin.domains.create({ domain: target });
      toast(`@${target} added`);
      setNewDomain(''); setAdding(false);
      reload();
      setDnsModalDomain(target);   // show DNS instructions
    } catch (e) { toast('Add failed: ' + e.message); }
  };

  return (
    <>
      <AdminPageHeader title="Shared Domains" count={`${domains.length} · ${domains.filter(d=>d.enabled).length} enabled`}>
        <AdminBtn variant="primary" onClick={() => setAdding(true)}><IconPlus size={12} stroke="#0A0A0A" /> Add domain</AdminBtn>
      </AdminPageHeader>
      <div style={{ flex: 1, overflow: 'auto' }}>
        {adding && (
          <div style={{ padding: 16, background: '#0f0f0f', borderBottom: '1px solid #1f1f1f', display: 'flex', gap: 8, alignItems: 'center' }}>
            <input autoFocus value={newDomain} onChange={(e) => setNewDomain(e.target.value.toLowerCase().trim())} onKeyDown={(e) => e.key === 'Enter' && add()} placeholder="example.com" style={{ flex: 1, background: '#0a0a0a', border: '1px solid #262626', color: '#EDEDED', fontFamily: "'JetBrains Mono', monospace", fontSize: 13, padding: '8px 12px', borderRadius: 5, outline: 'none' }} />
            <AdminBtn variant="primary" onClick={add}>Add</AdminBtn>
            <AdminBtn onClick={() => { setAdding(false); setNewDomain(''); }}>Cancel</AdminBtn>
          </div>
        )}
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead>
            <tr style={{ borderBottom: '1px solid #1f1f1f', background: '#0d0d0d', position: 'sticky', top: 0 }}>
              <Th>DOMAIN</Th><Th>STATUS</Th><Th>INBOXES</Th><Th>EMAILS 24H</Th><Th>SPAM SCORE</Th><Th>STORAGE</Th><Th>BADGES</Th><Th style={{textAlign:'right'}}>ACTIONS</Th>
            </tr>
          </thead>
          <tbody>
            {domains.map((d) => (
              <tr key={d.id} style={{ borderBottom: '1px solid #141414' }}>
                <td style={td}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                    {d.premium && <IconCrown size={11} stroke="#F59E0B" />}
                    <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 12, color: '#EDEDED' }}>@{d.domain}</span>
                  </div>
                </td>
                <td style={td}>
                  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: '0.1em', color: d.enabled ? '#10B981' : '#565656' }}>
                    <StatusDot status={d.enabled ? 'ok' : 'off'} /> {d.enabled ? 'ENABLED' : 'DISABLED'}
                  </span>
                </td>
                <td style={tdMono}>{d.inboxes.toLocaleString()}</td>
                <td style={tdMono}>{d.emails24h.toLocaleString()}</td>
                <td style={tdMono}>
                  <span style={{ color: d.spamScore > 0.1 ? '#DC2626' : d.spamScore > 0.05 ? '#F59E0B' : '#10B981' }}>{d.spamScore.toFixed(2)}</span>
                </td>
                <td style={tdMono}>{d.storage}</td>
                <td style={td}>
                  <div style={{ display: 'flex', gap: 4 }}>{d.badges.map((b) => <Badge key={b} kind={b} />)}</div>
                </td>
                <td style={{ ...td, textAlign: 'right' }}>
                  <div style={{ display: 'inline-flex', gap: 6 }}>
                    <AdminBtn size="sm" onClick={() => setDnsModalDomain(d.domain)}>DNS</AdminBtn>
                    <AdminBtn size="sm" onClick={() => toggle(d.id, d.enabled)}>{d.enabled ? 'Disable' : 'Enable'}</AdminBtn>
                    <AdminBtn size="sm" danger onClick={() => remove(d.id)}>Remove</AdminBtn>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      <SharedDomainDnsModal domain={dnsModalDomain} onClose={() => setDnsModalDomain(null)} toast={toast} />
    </>
  );
};

// Shows the DNS records the operator must add at the domain's registrar so
// inbound mail reaches the relay. Each field rendered separately because most
// registrar UIs (Namecheap, Cloudflare, Route 53) have distinct inputs for
// Type / Host / Mail Server / Priority — pasting `10 mx.example.com.` into
// a single "Mail Server" field doesn't work.
const SharedDomainDnsModal = ({ domain, onClose, toast }) => {
  if (!domain) return null;
  const relayHost = (typeof window !== 'undefined' && window.location.hostname) || 'zeromailer.cloud';
  const mxTarget = 'mx.' + relayHost;
  const copy = (txt) => { navigator.clipboard?.writeText(txt); toast && toast('Copied'); };

  // Color-coded label chips so each DNS field maps unambiguously to the
  // matching column in registrar UIs.
  const LABEL_COLORS = {
    TYPE:        { bg: '#3a0e0e', border: '#5a1a1a', color: '#F87171' },  // red
    HOST:        { bg: '#3a2a08', border: '#5c3e08', color: '#F59E0B' },  // orange
    VALUE:       { bg: '#2a3a08', border: '#3e5c08', color: '#FACC15' },  // yellow
    'MAIL SERVER': { bg: '#2a3a08', border: '#3e5c08', color: '#FACC15' },  // yellow (same family as value)
    PRIORITY:    { bg: '#0c2a4a', border: '#1e3f6b', color: '#60A5FA' },  // blue
  };
  const Chip = ({ label }) => {
    const c = LABEL_COLORS[label] || { bg: '#1a1a1a', border: '#262626', color: '#8A8A8A' };
    return (
      <span style={{
        display: 'inline-block', minWidth: 96, textAlign: 'center',
        fontFamily: "'JetBrains Mono', monospace", fontSize: 10, fontWeight: 600,
        letterSpacing: '0.15em', padding: '4px 8px', borderRadius: 3,
        background: c.bg, border: `1px solid ${c.border}`, color: c.color,
      }}>{label}</span>
    );
  };
  const Field = ({ label, value }) => {
    const [copied, setCopied] = React.useState(false);
    const doCopy = () => { copy(value); setCopied(true); setTimeout(() => setCopied(false), 1200); };
    return (
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
        <Chip label={label} />
        <code style={{ flex: 1, fontFamily: "'JetBrains Mono', monospace", fontSize: 12, color: '#EDEDED', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', padding: '6px 10px', background: '#0a0a0a', border: '1px solid #1f1f1f', borderRadius: 4 }}>{value}</code>
        <button onClick={doCopy} style={{ background: '#141414', border: '1px solid #262626', color: copied ? '#10B981' : '#8A8A8A', padding: '6px 10px', borderRadius: 4, fontSize: 10, fontFamily: "'JetBrains Mono', monospace", cursor: 'pointer', letterSpacing: '0.1em', flexShrink: 0 }}>
          {copied ? '✓ COPIED' : 'COPY'}
        </button>
      </div>
    );
  };

  const Card = ({ type, children, note }) => (
    <div style={{ background: '#0a0a0a', border: '1px solid #1f1f1f', borderRadius: 6, padding: 14, marginBottom: 10 }}>
      <Field label="TYPE" value={type} />
      {children}
      {note && <div style={{ fontSize: 11, color: '#565656', lineHeight: 1.4, marginTop: 6 }}>{note}</div>}
    </div>
  );

  return (
    <>
      <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.65)', zIndex: 700, animation: 'fadeIn 150ms' }} />
      <div style={{
        position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',
        width: '92%', maxWidth: 640, maxHeight: '85vh', overflowY: 'auto',
        background: '#0d0d0d', border: '1px solid #1f1f1f', borderRadius: 10,
        zIndex: 701, padding: 0, animation: 'zoomIn 200ms ease',
      }}>
        <div style={{ padding: '16px 24px', borderBottom: '1px solid #1f1f1f', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
          <div>
            <h3 style={{ margin: 0, fontSize: 15, fontWeight: 500, color: '#EDEDED' }}>DNS records for @{domain}</h3>
            <p style={{ margin: '4px 0 0', fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: '#565656', letterSpacing: '0.1em' }}>SET THESE AT THE REGISTRAR — MAIL WON'T FLOW UNTIL THEN</p>
          </div>
          <button onClick={onClose} style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#8A8A8A', padding: 6, fontSize: 16 }}>×</button>
        </div>
        <div style={{ padding: 20 }}>
          <p style={{ margin: '0 0 16px', fontSize: 13, color: '#8A8A8A', lineHeight: 1.5 }}>
            Open the DNS panel for <code style={{ fontFamily: "'JetBrains Mono', monospace", color: '#EDEDED' }}>{domain}</code> at whichever registrar holds it (Namecheap, Cloudflare, Route 53, etc.) and add the records below. The relay will accept mail to <code style={{ fontFamily: "'JetBrains Mono', monospace", color: '#EDEDED' }}>anything@{domain}</code> as soon as MX propagates (~5-30 min).
          </p>

          <Card type="MX" note="Routes inbound mail to the relay.">
            <Field label="HOST"        value={domain} />
            <Field label="MAIL SERVER" value={mxTarget} />
            <Field label="PRIORITY"    value="10" />
          </Card>

          <Card type="TXT" note="SPF — authorizes the MX host as a sender.">
            <Field label="HOST"  value={domain} />
            <Field label="VALUE" value="v=spf1 mx ~all" />
          </Card>

          <Card type="TXT" note="DMARC — optional but recommended.">
            <Field label="HOST"  value={'_dmarc.' + domain} />
            <Field label="VALUE" value="v=DMARC1; p=none" />
          </Card>

          <div style={{ marginTop: 16, padding: 12, background: '#0c1f2e', border: '1px solid #1e3f6b', borderRadius: 6 }}>
            <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: '0.18em', color: '#60A5FA', marginBottom: 6 }}>VERIFY WITH</div>
            <code style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, color: '#EDEDED', display: 'block', marginBottom: 4 }}>dig {domain} MX +short</code>
            <code style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, color: '#EDEDED', display: 'block' }}>dig {domain} TXT +short</code>
          </div>
        </div>
      </div>
    </>
  );
};

const Th = ({ children, style }) => <th style={{ textAlign: 'left', fontFamily: "'JetBrains Mono', monospace", fontSize: 9, fontWeight: 500, letterSpacing: '0.2em', color: '#565656', padding: '11px 16px', ...style }}>{children}</th>;
const Label = ({ children }) => <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 9, letterSpacing: '0.22em', color: '#565656' }}>{children}</span>;
const td = { padding: '11px 16px', fontSize: 12, color: '#EDEDED' };
const tdMono = { ...td, fontFamily: "'JetBrains Mono', monospace", color: '#8A8A8A' };

// ================= KEYS =================
const AdminKeys = ({ toast, onInspect }) => {
  const [keys, setKeys] = React.useState(null);
  const [showGen, setShowGen] = React.useState(false);
  const [newLabel, setNewLabel] = React.useState('');
  const [newExp, setNewExp] = React.useState('30d');
  const [justCreatedCode, setJustCreatedCode] = React.useState(null);

  const reload = () => tmApi.admin.keys.list().then(setKeys).catch((e) => toast('Load failed: ' + e.message));
  React.useEffect(() => { reload(); }, []);
  if (!keys) return <AdminLoading />;

  const addKey = async () => {
    try {
      const result = await tmApi.admin.keys.create(newLabel, newExp);
      setJustCreatedCode(result.codeFull);   // show full code ONCE
      reload();
      setShowGen(false); setNewLabel(''); setNewExp('30d');
    } catch (e) { toast('Generate failed: ' + e.message); }
  };

  const revoke = async (id) => {
    try {
      await tmApi.admin.keys.revoke(id);
      reload();
      toast('Key revoked');
    } catch (e) { toast('Revoke failed: ' + e.message); }
  };
  const copy = (code) => { navigator.clipboard?.writeText(code); toast('Code copied'); };

  return (
    <>
      <AdminPageHeader title="Access Keys" count={`${keys.length} · ${keys.filter(k=>k.status==='active').length} active`}>
        <AdminBtn><IconDownload size={12} /> Export CSV</AdminBtn>
        <AdminBtn variant="primary" onClick={() => setShowGen(true)}><IconPlus size={12} stroke="#0A0A0A" /> Generate key</AdminBtn>
      </AdminPageHeader>

      {showGen && (
        <div style={{ padding: 16, background: '#0f0f0f', borderBottom: '1px solid #1f1f1f', display: 'grid', gridTemplateColumns: '1fr 200px auto auto', gap: 8, alignItems: 'center' }}>
          <input autoFocus value={newLabel} onChange={(e) => setNewLabel(e.target.value)} placeholder="Label (optional) — e.g. Alex beta" style={{ background: '#0a0a0a', border: '1px solid #262626', color: '#EDEDED', fontSize: 13, padding: '8px 12px', borderRadius: 5, outline: 'none' }} />
          <select value={newExp} onChange={(e) => setNewExp(e.target.value)} style={{ background: '#0a0a0a', border: '1px solid #262626', color: '#EDEDED', fontFamily: "'JetBrains Mono', monospace", fontSize: 12, padding: '8px 12px', borderRadius: 5, outline: 'none' }}>
            <option value="24h">Expires in 24h</option>
            <option value="7d">Expires in 7d</option>
            <option value="30d">Expires in 30d</option>
            <option value="never">Never expires</option>
          </select>
          <AdminBtn variant="primary" onClick={addKey}>Generate</AdminBtn>
          <AdminBtn onClick={() => setShowGen(false)}>Cancel</AdminBtn>
        </div>
      )}
      <NewKeyModal code={justCreatedCode} onClose={() => setJustCreatedCode(null)} toast={toast} />

      <div style={{ flex: 1, overflow: 'auto' }}>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead>
            <tr style={{ borderBottom: '1px solid #1f1f1f', background: '#0d0d0d', position: 'sticky', top: 0 }}>
              <Th>CODE</Th><Th>LABEL</Th><Th>STATUS</Th><Th>CREATED</Th><Th>EXPIRES</Th><Th>INBOXES</Th><Th>EMAILS</Th><Th>LAST SEEN</Th><Th style={{textAlign:'right'}}>ACTIONS</Th>
            </tr>
          </thead>
          <tbody>
            {keys.map((k) => (
              <tr key={k.id} style={{ borderBottom: '1px solid #141414', cursor: 'pointer' }}
                onMouseEnter={(e) => e.currentTarget.style.background = '#101010'}
                onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
              >
                <td style={tdMono}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                    <span style={{ color: k.hasFullCode ? '#EDEDED' : '#8A8A8A' }} title={k.hasFullCode ? 'Full code — click copy to share' : 'Redacted preview — this key was created before full-code storage'}>{k.code}</span>
                    {k.hasFullCode && (
                      <button
                        onClick={() => copy(k.code)}
                        title="Copy full code"
                        style={{ background: 'none', border: 'none', color: '#565656', cursor: 'pointer', display: 'flex', padding: 2 }}
                      >
                        <IconCopy size={11} />
                      </button>
                    )}
                  </div>
                </td>
                <td style={td}>{k.label || <span style={{ color: '#404040' }}>—</span>}</td>
                <td style={td}>
                  <StatusPill status={k.status} />
                </td>
                <td style={tdMono}>{k.created}</td>
                <td style={tdMono}>{k.expires}</td>
                <td style={tdMono}>{k.inboxes}</td>
                <td style={tdMono}>{k.emails}</td>
                <td style={tdMono}>{k.lastSeen}</td>
                <td style={{ ...td, textAlign: 'right' }}>
                  <div style={{ display: 'inline-flex', gap: 6 }}>
                    <AdminBtn size="sm" onClick={() => onInspect(k)}><IconEye size={11} /> Activity</AdminBtn>
                    {k.status === 'active' && <AdminBtn size="sm" danger onClick={() => revoke(k.id)}>Revoke</AdminBtn>}
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </>
  );
};

// Modal shown ONCE when a fresh access key is generated. The full code is
// argon2-hashed in the DB so this is the only chance to copy it.
const NewKeyModal = ({ code, onClose, toast }) => {
  const [acknowledged, setAcknowledged] = React.useState(false);
  const [copied, setCopied] = React.useState(false);

  React.useEffect(() => {
    if (code) { setAcknowledged(false); setCopied(false); }
  }, [code]);

  if (!code) return null;

  const doCopy = () => {
    navigator.clipboard?.writeText(code);
    setCopied(true);
    toast && toast('Code copied to clipboard');
  };

  return (
    <>
      <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.85)', zIndex: 800, animation: 'fadeIn 200ms' }} />
      <div style={{
        position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',
        width: '92%', maxWidth: 580,
        background: '#0d0d0d', border: '2px solid #F59E0B', borderRadius: 10,
        zIndex: 801, padding: 28, boxShadow: '0 0 0 1px rgba(245,158,11,0.15), 0 20px 60px rgba(0,0,0,0.7)',
        animation: 'zoomIn 200ms ease',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 18 }}>
          <span style={{ width: 8, height: 8, borderRadius: '50%', background: '#F59E0B', boxShadow: '0 0 8px #F59E0B', animation: 'pulse 1.6s ease-in-out infinite' }} />
          <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, letterSpacing: '0.22em', color: '#F59E0B', fontWeight: 600 }}>
            FULL CODE — SHOWN ONCE
          </span>
        </div>

        <p style={{ margin: '0 0 14px', fontSize: 14, color: '#EDEDED', lineHeight: 1.5 }}>
          Copy this access code <strong>now</strong>. It's argon2-hashed in the database — once you close this dialog there is <strong>no way</strong> to retrieve it. If you lose it, you'll need to revoke this key and generate a new one.
        </p>

        <div style={{ background: '#0a0a0a', border: '1px solid #1f1f1f', borderRadius: 6, padding: '20px 18px', display: 'flex', alignItems: 'center', gap: 12, marginBottom: 14 }}>
          <code style={{ flex: 1, fontFamily: "'JetBrains Mono', monospace", fontSize: 22, color: '#F59E0B', letterSpacing: '0.08em', userSelect: 'all' }}>
            {code}
          </code>
          <button
            onClick={doCopy}
            style={{
              background: copied ? '#10B981' : '#F59E0B', color: '#0A0A0A', border: 'none',
              padding: '10px 16px', borderRadius: 5,
              fontFamily: "'JetBrains Mono', monospace", fontSize: 11, letterSpacing: '0.15em', fontWeight: 700,
              cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 6,
            }}
          >
            {copied ? '✓ COPIED' : 'COPY'}
          </button>
        </div>

        <p style={{ margin: '0 0 18px', fontSize: 12, color: '#8A8A8A', lineHeight: 1.5 }}>
          The keys list will only show the redacted preview <code style={{ fontFamily: "'JetBrains Mono', monospace", color: '#565656' }}>{code.slice(0,4)}-XXXX-XXXX-{code.slice(-4)}</code> from now on.
        </p>

        <label style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px', background: '#141414', border: '1px solid #262626', borderRadius: 6, cursor: 'pointer', marginBottom: 16 }}>
          <input
            type="checkbox"
            checked={acknowledged}
            onChange={(e) => setAcknowledged(e.target.checked)}
            style={{ accentColor: '#F59E0B', width: 16, height: 16 }}
          />
          <span style={{ fontSize: 13, color: '#EDEDED' }}>I have copied this code somewhere safe.</span>
        </label>

        <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
          <button
            onClick={onClose}
            disabled={!acknowledged}
            style={{
              background: acknowledged ? '#F59E0B' : '#262626',
              color: acknowledged ? '#0A0A0A' : '#565656',
              border: 'none', padding: '10px 18px', borderRadius: 5,
              fontFamily: "'Geist', system-ui, sans-serif", fontSize: 13, fontWeight: 600,
              cursor: acknowledged ? 'pointer' : 'not-allowed',
              transition: 'background 120ms',
            }}
          >
            Close
          </button>
        </div>
      </div>
    </>
  );
};

const StatusPill = ({ status }) => {
  const map = {
    active: { bg: '#0a1f1a', border: '#1a3f33', color: '#10B981' },
    revoked: { bg: '#2a0e0e', border: '#5a1a1a', color: '#DC2626' },
    expired: { bg: '#1a1a1a', border: '#262626', color: '#8A8A8A' },
    unused: { bg: '#0c2a4a', border: '#1e3f6b', color: '#60A5FA' },
  };
  const s = map[status] || map.expired;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontFamily: "'JetBrains Mono', monospace", fontSize: 9, letterSpacing: '0.15em', fontWeight: 600, padding: '3px 7px', borderRadius: 3, background: s.bg, border: `1px solid ${s.border}`, color: s.color }}>
      <span style={{ width: 5, height: 5, borderRadius: '50%', background: s.color }} /> {status.toUpperCase()}
    </span>
  );
};

// ================= FIREHOSE =================
const AdminFirehose = ({ toast }) => {
  const [stream, setStream] = React.useState([]);
  const [paused, setPaused] = React.useState(false);
  const [filter, setFilter] = React.useState('');
  const [selected, setSelected] = React.useState(null);
  const [loaded, setLoaded] = React.useState(false);

  // Initial load
  React.useEffect(() => {
    let cancel = false;
    tmApi.admin.firehose.list({ limit: 50 }).then((r) => {
      if (cancel) return;
      setStream(r);
      setSelected(r[0] || null);
      setLoaded(true);
    }).catch((e) => { setLoaded(true); toast('Firehose load failed: ' + e.message); });
    return () => { cancel = true; };
  }, []);

  // Live WS stream
  React.useEffect(() => {
    if (paused) return;
    const conn = tmApi.openFirehose({
      onEntry: (entry) => setStream((p) => [{ ...entry, isNew: true }, ...p].slice(0, 200)),
      onError: () => { /* will be retried on next mount */ },
    });
    return () => conn.close();
  }, [paused]);

  const filtered = filter ? stream.filter(f => (f.from + f.subject + f.to + f.domain).toLowerCase().includes(filter.toLowerCase())) : stream;
  if (!loaded) return <AdminLoading />;

  return (
    <>
      <AdminPageHeader title="Firehose" count={`${filtered.length} · LIVE`}>
        <div style={{ position: 'relative' }}>
          <IconSearch size={12} stroke="#565656" style={{ position: 'absolute', left: 8, top: '50%', transform: 'translateY(-50%)' }} />
          <input value={filter} onChange={(e) => setFilter(e.target.value)} placeholder="Filter sender / subject / domain" style={{ background: '#141414', border: '1px solid #262626', color: '#EDEDED', fontFamily: "'JetBrains Mono', monospace", fontSize: 11, padding: '7px 10px 7px 26px', borderRadius: 5, outline: 'none', width: 260 }} />
        </div>
        <AdminBtn onClick={() => setPaused(!paused)}>
          {paused ? <><IconPlay size={11} /> Resume</> : <><IconPause size={11} /> Pause</>}
        </AdminBtn>
      </AdminPageHeader>

      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1fr 420px', overflow: 'hidden' }}>
        {/* Stream */}
        <div style={{ overflowY: 'auto', borderRight: '1px solid #1f1f1f' }}>
          {filtered.map((f) => (
            <div key={f.id} onClick={() => setSelected(f)} style={{
              display: 'grid', gridTemplateColumns: '70px 1fr auto 70px', gap: 10, padding: '9px 16px',
              borderBottom: '1px solid #141414', cursor: 'pointer', alignItems: 'center',
              background: selected?.id === f.id ? '#141414' : 'transparent',
              borderLeft: `2px solid ${selected?.id === f.id ? '#F59E0B' : f.flagged ? '#DC2626' : 'transparent'}`,
              animation: f.isNew ? 'newMail 1.8s ease' : 'none',
            }}
              onMouseEnter={(e) => selected?.id !== f.id && (e.currentTarget.style.background = '#101010')}
              onMouseLeave={(e) => selected?.id !== f.id && (e.currentTarget.style.background = 'transparent')}
            >
              <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, color: '#565656' }}>{f.ts}</span>
              <div style={{ minWidth: 0 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontFamily: "'JetBrains Mono', monospace", fontSize: 11, color: f.flagged ? '#DC2626' : '#8A8A8A', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                  {f.flagged && <IconAlert size={10} stroke="#DC2626" />}
                  {f.from} <span style={{ color: '#404040' }}>→</span> {f.to}
                </div>
                <div style={{ fontSize: 12, color: '#EDEDED', marginTop: 2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{f.subject}</div>
              </div>
              {f.hasCode ? (
                <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: '#10B981', padding: '2px 6px', background: '#0a1f1a', border: '1px solid #1a3f33', borderRadius: 3 }}>⚡ {f.code}</span>
              ) : <span />}
              <span style={{ textAlign: 'right', fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: '#565656' }}>{f.size}</span>
            </div>
          ))}
        </div>

        {/* Inspector */}
        <div style={{ overflowY: 'auto', padding: 20, background: '#0a0a0a' }}>
          {selected ? (
            <>
              <div style={adminStyles.monoLabel}>INSPECTION · {selected.id}</div>
              <div style={{ marginTop: 14, display: 'grid', gridTemplateColumns: '80px 1fr', rowGap: 10, fontSize: 12 }}>
                <Label>TS</Label><span style={{ fontFamily: "'JetBrains Mono', monospace", color: '#EDEDED' }}>{selected.ts}</span>
                <Label>FROM</Label><span style={{ fontFamily: "'JetBrains Mono', monospace", color: '#EDEDED' }}>{selected.from}</span>
                <Label>TO</Label><span style={{ fontFamily: "'JetBrains Mono', monospace", color: '#EDEDED' }}>{selected.to}</span>
                <Label>DOMAIN</Label><span style={{ fontFamily: "'JetBrains Mono', monospace", color: '#EDEDED' }}>{selected.domain}</span>
                <Label>KEY</Label><span style={{ fontFamily: "'JetBrains Mono', monospace", color: '#60A5FA' }}>{selected.keyId}</span>
                <Label>SIZE</Label><span style={{ fontFamily: "'JetBrains Mono', monospace", color: '#8A8A8A' }}>{selected.size}</span>
                <Label>FLAGGED</Label><span style={{ fontFamily: "'JetBrains Mono', monospace", color: selected.flagged ? '#DC2626' : '#10B981' }}>{selected.flagged ? 'YES' : 'NO'}</span>
                {selected.hasCode && (<><Label>CODE</Label><span style={{ fontFamily: "'JetBrains Mono', monospace", color: '#10B981' }}>{selected.code}</span></>)}
              </div>
              <div style={{ ...adminStyles.monoLabel, marginTop: 24, marginBottom: 10 }}>SUBJECT</div>
              <div style={{ fontSize: 14, color: '#EDEDED', padding: 12, background: '#111', border: '1px solid #1f1f1f', borderRadius: 6 }}>{selected.subject}</div>
              <div style={{ ...adminStyles.monoLabel, marginTop: 20, marginBottom: 10 }}>BODY PREVIEW</div>
              <div style={{ background: '#EDEDED', borderRadius: 6, padding: 16, color: '#1a1a1a', fontSize: 13, lineHeight: 1.6 }}>
                <p style={{ margin: '0 0 10px' }}>Hello,</p>
                <p style={{ margin: '0 0 10px' }}>{selected.hasCode ? `Your verification code is ${selected.code}.` : 'Thanks for using our service. This is a preview of the message body as it would appear to the recipient.'}</p>
                <p style={{ margin: 0, color: '#666', fontSize: 11 }}>— {selected.from}</p>
              </div>
              <div style={{ marginTop: 16, display: 'flex', gap: 6 }}>
                <AdminBtn size="sm"><IconDownload size={11} /> Full MIME</AdminBtn>
                <AdminBtn size="sm" danger>Flag</AdminBtn>
                <AdminBtn size="sm" danger>Block sender</AdminBtn>
              </div>
            </>
          ) : <div style={{ color: '#565656', fontSize: 12, padding: 40, textAlign: 'center' }}>Select a message</div>}
        </div>
      </div>
    </>
  );
};

// ================= ABUSE =================
const AdminAbuse = ({ toast }) => {
  const [blocks, setBlocks] = React.useState(null);
  const [adding, setAdding] = React.useState(false);
  const [pattern, setPattern] = React.useState('');
  const [reason, setReason] = React.useState('');

  const reload = () => tmApi.admin.blocks.list().then(setBlocks).catch((e) => toast('Load failed: ' + e.message));
  React.useEffect(() => { reload(); }, []);
  if (!blocks) return <AdminLoading />;

  const add = async () => {
    if (!pattern) return;
    try {
      await tmApi.admin.blocks.create({ pattern, reason });
      toast('Block rule added');
      setAdding(false); setPattern(''); setReason('');
      reload();
    } catch (e) { toast('Add failed: ' + e.message); }
  };
  const remove = async (id) => {
    try { await tmApi.admin.blocks.remove(id); reload(); toast('Block removed'); }
    catch (e) { toast('Remove failed: ' + e.message); }
  };

  return (
    <>
      <AdminPageHeader title="Abuse & Moderation" count={`${blocks.length} rules`}>
        <AdminBtn variant="primary" onClick={() => setAdding(true)}><IconPlus size={12} stroke="#0A0A0A" /> Add block</AdminBtn>
      </AdminPageHeader>
      {adding && (
        <div style={{ padding: 16, background: '#0f0f0f', borderBottom: '1px solid #1f1f1f', display: 'grid', gridTemplateColumns: '1fr 1fr auto auto', gap: 8 }}>
          <input autoFocus value={pattern} onChange={(e) => setPattern(e.target.value)} placeholder="spammer@example.com or @*.ml" style={{ background: '#0a0a0a', border: '1px solid #262626', color: '#EDEDED', fontFamily: "'JetBrains Mono', monospace", fontSize: 13, padding: '8px 12px', borderRadius: 5, outline: 'none' }} />
          <input value={reason} onChange={(e) => setReason(e.target.value)} placeholder="Reason" style={{ background: '#0a0a0a', border: '1px solid #262626', color: '#EDEDED', fontSize: 13, padding: '8px 12px', borderRadius: 5, outline: 'none' }} />
          <AdminBtn variant="primary" onClick={add}>Block</AdminBtn>
          <AdminBtn onClick={() => setAdding(false)}>Cancel</AdminBtn>
        </div>
      )}
      <div style={{ flex: 1, overflow: 'auto' }}>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr style={{ borderBottom: '1px solid #1f1f1f', background: '#0d0d0d' }}><Th>KIND</Th><Th>PATTERN</Th><Th>HITS</Th><Th>REASON</Th><Th>ADDED</Th><Th style={{textAlign:'right'}}>ACTIONS</Th></tr></thead>
          <tbody>
            {blocks.map((b) => (
              <tr key={b.id} style={{ borderBottom: '1px solid #141414' }}>
                <td style={td}><span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: '0.1em', padding: '2px 6px', background: '#1a1a1a', border: '1px solid #262626', borderRadius: 3, color: '#F59E0B' }}>{b.kind.toUpperCase()}</span></td>
                <td style={tdMono}><span style={{ color: '#EDEDED' }}>{b.pattern}</span></td>
                <td style={tdMono}>{b.hits}</td>
                <td style={td}>{b.reason || <span style={{ color: '#404040' }}>—</span>}</td>
                <td style={tdMono}>{b.added}</td>
                <td style={{...td, textAlign:'right'}}><AdminBtn size="sm" danger onClick={() => remove(b.id)}>Remove</AdminBtn></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </>
  );
};

// ================= HEALTH =================
const AdminHealth = () => {
  const [health, setHealth] = React.useState(null);
  React.useEffect(() => {
    tmApi.admin.health().then(setHealth).catch(() => setHealth([]));
    const t = setInterval(() => tmApi.admin.health().then(setHealth).catch(() => {}), 30000);
    return () => clearInterval(t);
  }, []);
  if (!health) return <AdminLoading />;
  return (
    <>
      <AdminPageHeader title="System Health" count={`${health.filter(h=>h.status==='ok').length}/${health.length} ok`} />
      <div style={{ flex: 1, overflow: 'auto', padding: 24 }}>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 10 }}>
          {health.map((h) => (
            <div key={h.label} style={{ background: '#111', border: '1px solid #1f1f1f', borderRadius: 8, padding: 14, display: 'flex', alignItems: 'center', gap: 12 }}>
              <StatusDot status={h.status} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, color: '#EDEDED', letterSpacing: '0.08em' }}>{h.label}</div>
                <div style={{ fontSize: 12, color: '#8A8A8A', marginTop: 2 }}>{h.detail}</div>
              </div>
              <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, color: '#565656', letterSpacing: '0.08em' }}>{h.uptime}</div>
            </div>
          ))}
        </div>
      </div>
    </>
  );
};

// ================= AUDIT =================
const AdminAudit = () => {
  const [events, setEvents] = React.useState(null);
  React.useEffect(() => {
    tmApi.admin.audit({ limit: 100 }).then(setEvents).catch(() => setEvents([]));
  }, []);
  if (!events) return <AdminLoading />;
  return (
    <>
      <AdminPageHeader title="Audit Log" count={`${events.length} events`} />
      <div style={{ flex: 1, overflow: 'auto' }}>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr style={{ borderBottom: '1px solid #1f1f1f', background: '#0d0d0d' }}><Th>TIMESTAMP</Th><Th>ACTOR</Th><Th>ACTION</Th><Th>TARGET</Th><Th>META</Th></tr></thead>
          <tbody>
            {events.map((a) => (
              <tr key={a.id} style={{ borderBottom: '1px solid #141414' }}>
                <td style={tdMono}>{a.ts}</td>
                <td style={tdMono}>{a.actor}</td>
                <td style={td}><span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, color: a.action.includes('revoke') || a.action.includes('disable') || a.action.includes('block') ? '#DC2626' : a.action.includes('create') || a.action.includes('add') ? '#10B981' : '#F59E0B' }}>{a.action}</span></td>
                <td style={tdMono}><span style={{ color: '#EDEDED' }}>{a.target}</span></td>
                <td style={td}><span style={{ color: '#8A8A8A', fontSize: 12 }}>{a.meta}</span></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </>
  );
};

// ================= SETTINGS =================
const AdminSettings = ({ toast }) => {
  const [s, setS] = React.useState(null);
  React.useEffect(() => {
    tmApi.admin.settings.get().then(setS).catch((e) => toast('Load failed: ' + e.message));
  }, []);
  if (!s) return <AdminLoading />;
  const save = async () => {
    try { const updated = await tmApi.admin.settings.update(s); setS(updated); toast('Settings saved'); }
    catch (e) { toast('Save failed: ' + e.message); }
  };
  return (
    <>
      <AdminPageHeader title="Global Settings">
        <AdminBtn variant="primaryGreen" onClick={save}>Save changes</AdminBtn>
      </AdminPageHeader>
      <div style={{ flex: 1, overflow: 'auto', padding: 24 }}>
        <SettingsGroup label="RETENTION">
          <SRow label="Shared domain emails (hours)"><NumInput value={s.sharedRetention} onChange={(v) => setS({...s, sharedRetention: v})} /></SRow>
          <SRow label="Custom domain emails (hours)"><NumInput value={s.customRetention} onChange={(v) => setS({...s, customRetention: v})} /></SRow>
        </SettingsGroup>
        <SettingsGroup label="AUTHENTICATION">
          <SRow label="Max code attempts before rate limit"><NumInput value={s.maxAttempts} onChange={(v) => setS({...s, maxAttempts: v})} /></SRow>
          <SRow label="Rate-limit window (minutes)"><NumInput value={s.rateLimitWin} onChange={(v) => setS({...s, rateLimitWin: v})} /></SRow>
          <SRow label="Session TTL (hours)"><NumInput value={s.sessionTTL} onChange={(v) => setS({...s, sessionTTL: v})} /></SRow>
        </SettingsGroup>
        <SettingsGroup label="SMTP">
          <SRow label="Relay hostname"><TxtInput value={s.smtpHost} onChange={(v) => setS({...s, smtpHost: v})} /></SRow>
          <SRow label="Max attachment size (MB)"><NumInput value={s.maxAttachMB} onChange={(v) => setS({...s, maxAttachMB: v})} /></SRow>
          <SRow label="Auto-flag likely spam"><Toggle value={s.autoFlagSpam} onChange={(v) => setS({...s, autoFlagSpam: v})} /></SRow>
        </SettingsGroup>
        <SettingsGroup label="INTEGRATIONS">
          <SRow label="Webhook URL (new email)"><TxtInput value={s.webhookUrl} onChange={(v) => setS({...s, webhookUrl: v})} placeholder="https://…" /></SRow>
        </SettingsGroup>
      </div>
    </>
  );
};

const SettingsGroup = ({ label, children }) => (
  <div style={{ marginBottom: 24 }}>
    <div style={{ ...adminStyles.monoLabel, marginBottom: 10 }}>{label}</div>
    <div style={{ background: '#111', border: '1px solid #1f1f1f', borderRadius: 8 }}>{children}</div>
  </div>
);
const SRow = ({ label, children }) => (
  <div style={{ padding: '12px 16px', borderBottom: '1px solid #1a1a1a', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 }}>
    <span style={{ fontSize: 13, color: '#EDEDED' }}>{label}</span>{children}
  </div>
);
const NumInput = ({ value, onChange }) => <input type="number" value={value} onChange={(e) => onChange(Number(e.target.value))} style={{ background: '#0a0a0a', border: '1px solid #262626', color: '#EDEDED', fontFamily: "'JetBrains Mono', monospace", fontSize: 12, padding: '6px 10px', borderRadius: 4, outline: 'none', width: 100, textAlign: 'right' }} />;
const TxtInput = ({ value, onChange, placeholder }) => <input value={value} onChange={(e) => onChange(e.target.value)} placeholder={placeholder} style={{ background: '#0a0a0a', border: '1px solid #262626', color: '#EDEDED', fontFamily: "'JetBrains Mono', monospace", fontSize: 12, padding: '6px 10px', borderRadius: 4, outline: 'none', width: 280 }} />;

// ================= KEY ACTIVITY DRAWER =================
const KeyActivityDrawer = ({ keyObj, onClose, toast }) => {
  if (!keyObj) return null;
  const [selected, setSelected] = React.useState(null);
  const [keyFirehose, setKeyFirehose] = React.useState([]);
  React.useEffect(() => {
    let cancel = false;
    tmApi.admin.keys.activity(keyObj.id).then((r) => !cancel && setKeyFirehose(r.messages || []))
      .catch(() => !cancel && setKeyFirehose([]));
    return () => { cancel = true; };
  }, [keyObj.id]);
  return (
    <>
      <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', zIndex: 500, animation: 'fadeIn 150ms' }} />
      <div style={{ position: 'fixed', top: 0, right: 0, bottom: 0, width: '60%', maxWidth: 900, background: '#0A0A0A', borderLeft: '1px solid #1f1f1f', zIndex: 501, display: 'flex', flexDirection: 'column', animation: 'slideInRight 200ms ease' }}>
        <div style={{ padding: '16px 24px', borderBottom: '1px solid #1f1f1f', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <div>
            <div style={adminStyles.monoLabel}>KEY ACTIVITY</div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 4 }}>
              <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 15, color: '#EDEDED' }}>{keyObj.code}</span>
              <StatusPill status={keyObj.status} />
            </div>
            {keyObj.label && <div style={{ fontSize: 12, color: '#8A8A8A', marginTop: 3 }}>{keyObj.label}</div>}
          </div>
          <button onClick={onClose} style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#8A8A8A', padding: 6 }}><IconX size={16} /></button>
        </div>

        {/* Stat strip */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', borderBottom: '1px solid #1f1f1f' }}>
          {[['INBOXES', keyObj.inboxes], ['EMAILS', keyObj.emails], ['LAST IP', keyObj.ip], ['LAST SEEN', keyObj.lastSeen]].map(([l, v]) => (
            <div key={l} style={{ padding: '12px 16px', borderRight: '1px solid #1f1f1f' }}>
              <div style={adminStyles.monoLabel}>{l}</div>
              <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 14, color: '#EDEDED', marginTop: 3 }}>{v}</div>
            </div>
          ))}
        </div>

        <div style={{ flex: 1, display: 'grid', gridTemplateColumns: selected ? '1fr 1fr' : '1fr', overflow: 'hidden' }}>
          <div style={{ overflowY: 'auto', borderRight: selected ? '1px solid #1f1f1f' : 'none' }}>
            <div style={{ padding: '12px 24px', ...adminStyles.monoLabel, borderBottom: '1px solid #1a1a1a' }}>ALL MESSAGES · {keyFirehose.length}</div>
            {keyFirehose.length === 0 ? (
              <div style={{ padding: 40, textAlign: 'center', color: '#565656', fontSize: 12 }}>No activity yet</div>
            ) : keyFirehose.map((f) => (
              <div key={f.id} onClick={() => setSelected(f)} style={{ padding: '10px 24px', borderBottom: '1px solid #151515', cursor: 'pointer', background: selected?.id === f.id ? '#141414' : 'transparent' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: "'JetBrains Mono', monospace", fontSize: 11, color: '#8A8A8A', marginBottom: 3 }}>
                  <span>{f.from}</span><span>{f.ts}</span>
                </div>
                <div style={{ fontSize: 13, color: '#EDEDED' }}>{f.subject}</div>
              </div>
            ))}
          </div>
          {selected && (
            <div style={{ overflowY: 'auto', padding: 20, background: '#0a0a0a' }}>
              <div style={adminStyles.monoLabel}>MESSAGE INSPECT</div>
              <div style={{ marginTop: 14, fontSize: 12, fontFamily: "'JetBrains Mono', monospace", color: '#8A8A8A', lineHeight: 1.9 }}>
                <div>FROM: <span style={{ color: '#EDEDED' }}>{selected.from}</span></div>
                <div>TO: <span style={{ color: '#EDEDED' }}>{selected.to}</span></div>
                <div>TS: <span style={{ color: '#EDEDED' }}>{selected.ts}</span></div>
              </div>
              <div style={{ marginTop: 20, background: '#EDEDED', padding: 16, borderRadius: 6, color: '#1a1a1a', fontSize: 13 }}>
                <p style={{ margin: '0 0 8px', fontWeight: 600 }}>{selected.subject}</p>
                <p style={{ margin: 0 }}>{selected.hasCode ? `Your verification code is ${selected.code}.` : 'Full email body would render here, sanitized and sandboxed.'}</p>
              </div>
            </div>
          )}
        </div>
      </div>
    </>
  );
};

Object.assign(window, { AdminDashboard, AdminDomains, AdminKeys, AdminFirehose, AdminAbuse, AdminHealth, AdminAudit, AdminSettings, KeyActivityDrawer });
