// Bot Central — admin-only live sync/reanalysis feed.
const { useState: useStateBC, useEffect: useEffectBC, useCallback: useCallbackBC, useRef: useRefBC } = React;

function SyncCountdown({ lastSynced, intervalH, autoSync, label = 'sync' }) {
  const [now, setNow] = useStateBC(Date.now());
  useEffectBC(() => {
    const t = setInterval(() => setNow(Date.now()), 1000);
    return () => clearInterval(t);
  }, []);

  if (!autoSync || !lastSynced) return null;

  const lastMs = new Date(lastSynced).getTime();
  const nextMs = lastMs + intervalH * 3600000;
  const diffMs = nextMs - now;

  if (diffMs <= 0) {
    return (
      <div className="bc-countdown">
        <span className="bc-countdown-label mono">Next {label}</span>
        <span className="bc-countdown-val mono" style={{ color: 'var(--accent-warm)' }}>overdue</span>
      </div>
    );
  }

  const h = Math.floor(diffMs / 3600000);
  const m = Math.floor((diffMs % 3600000) / 60000);
  const s = Math.floor((diffMs % 60000) / 1000);
  const parts = [];
  if (h > 0) parts.push(`${h}h`);
  if (m > 0 || h > 0) parts.push(`${m}m`);
  parts.push(`${s}s`);

  return (
    <div className="bc-countdown">
      <span className="bc-countdown-label mono">Next {label} in</span>
      <span className="bc-countdown-val mono">{parts.join(' ')}</span>
    </div>
  );
}

function BotCentralView({ autoCycleEnabled, setAutoCycleEnabled, autoCycleIntervalH, setAutoCycleIntervalH, onSaveAutoCycleInterval, lastAutoCycle, onSyncNow, syncing, onReanalyzeNow, reanalyzing, batchSyncEnabled, setBatchSyncEnabled, batchReanalysisEnabled, setBatchReanalysisEnabled, reanalysisFullContext, setReanalysisFullContext, reanalysisRagContext, setReanalysisRagContext, reanalysisAllowConfirmed, setReanalysisAllowConfirmed, onFullReprocess, reprocessing, syncModel, setSyncModel, reanalysisModel, setReanalysisModel, correctionModel, setCorrectionModel }) {
  const [log, setLog] = useStateBC({ state: 'idle', events: [] });
  const [expanded, setExpanded] = useStateBC({});
  const [models, setModels] = useStateBC([]);

  useEffectBC(() => {
    fetch('/api/models').then(r => r.json()).then(setModels).catch(() => {});
  }, []);

  const fetchLog = useCallbackBC(async () => {
    try {
      const res = await fetch('/api/sync-log', { cache: 'no-store' });
      if (res.ok) setLog(await res.json());
    } catch {}
  }, []);

  useEffectBC(() => {
    fetchLog();
    const es = new EventSource('/api/events');
    es.addEventListener('sync-log', () => fetchLog());
    return () => es.close();
  }, [fetchLog]);

  const toggle = (id) => setExpanded(prev => ({ ...prev, [id]: !prev[id] }));

  const cycles = groupIntoCycles(log.events || []);
  const isWaiting = (log.state || '').startsWith('waiting_for_batch');
  const stateColor = log.state === 'syncing' ? 'var(--conf-medium)' : log.state === 'reanalyzing' ? 'var(--conf-high)' : isWaiting ? 'var(--conf-uncertain)' : 'var(--conf-confirmed)';
  const stateLabel = log.state === 'syncing' ? 'SYNCING' : log.state === 'reanalyzing' ? 'RE-ANALYZING' : isWaiting ? 'WAITING FOR BATCH' : 'IDLE';
  const lastEvent = (log.events || []).length > 0 ? log.events[log.events.length - 1] : null;

  return (
    <div className="bc-shell">
      <div className="bc-status">
        <span className="bc-dot" style={{ background: stateColor }} />
        <span className="bc-state mono">{stateLabel}</span>
        {lastEvent && <span className="bc-ts">{relTime(lastEvent.ts)}</span>}
      </div>

      {/* Automation — unified auto-cycle */}
      <div className="bc-controls" style={{ gridTemplateColumns: '1fr' }}>
        <div className="bc-controls-row">
          <div className="eyebrow" style={{ marginBottom: 10 }}><span className="rule"></span>Automation</div>
          <SyncCountdown lastSynced={lastAutoCycle} intervalH={autoCycleIntervalH} autoSync={autoCycleEnabled} label="auto cycle" />
          <div className="bc-ctrl-grid">
            <label className="bc-ctrl-item">
              <span>
                <span className="bc-ctrl-label">Auto cycle</span>
                <span className="bc-ctrl-help">Syncs new messages then re-analyzes the dictionary on a timer.</span>
              </span>
              <button className={`switch ${autoCycleEnabled ? 'on' : ''}`} role="switch" aria-checked={autoCycleEnabled} onClick={() => setAutoCycleEnabled(!autoCycleEnabled)}>
                <span className="switch-knob" />
              </button>
            </label>
            <div className="bc-ctrl-item">
              <span className="bc-ctrl-label">Interval</span>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <input type="number" min="1" max="168" className="field field-mono" value={autoCycleIntervalH} onChange={e => setAutoCycleIntervalH(Math.max(1, Math.min(168, parseInt(e.target.value) || 1)))} style={{ width: 60, textAlign: 'center', fontSize: 12 }} />
                <span className="mono" style={{ fontSize: 11, color: 'var(--fg-mute)' }}>h</span>
                <button className="btn" style={{ fontSize: 11, padding: '3px 8px' }} onClick={onSaveAutoCycleInterval}>save</button>
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* Manual controls — Sync and Re-analysis */}
      <div className="bc-controls">
        <div className="bc-controls-row">
          <div className="eyebrow" style={{ marginBottom: 10 }}><span className="rule"></span>Sync</div>
          <div className="bc-ctrl-grid">
            <label className="bc-ctrl-item">
              <span>
                <span className="bc-ctrl-label">Batch API</span>
                <span className="bc-ctrl-help">50% cheaper but async (results in minutes, not seconds).</span>
              </span>
              <button className={`switch ${batchSyncEnabled ? 'on' : ''}`} role="switch" aria-checked={batchSyncEnabled} onClick={() => setBatchSyncEnabled(!batchSyncEnabled)}>
                <span className="switch-knob" />
              </button>
            </label>
            <div className="bc-ctrl-item">
              <span className="bc-ctrl-label">Model</span>
              <select className="field field-mono" style={{ fontSize: 11, padding: '3px 6px', maxWidth: 200 }} value={syncModel} onChange={e => setSyncModel(e.target.value)}>
                {models.length ? models.map(m => <option key={m} value={m}>{m}</option>) : <option value={syncModel}>{syncModel}</option>}
              </select>
            </div>
            <div className="bc-ctrl-item">
              <div>
                <button className="btn btn-primary" style={{ fontSize: 11, padding: '4px 10px' }} onClick={onSyncNow} disabled={syncing}>{syncing ? '…' : 'Sync now'}</button>
                <span className="bc-ctrl-help" style={{ marginLeft: 6 }}>Fetch new messages since last sync.</span>
              </div>
            </div>
            <div className="bc-ctrl-item">
              <div>
                <button className="btn" style={{ fontSize: 11, padding: '4px 10px', color: 'var(--accent-warm)', borderColor: 'var(--accent-warm)' }} onClick={onFullReprocess} disabled={reprocessing}>{reprocessing ? '…' : 'Full reprocess'}</button>
                <span className="bc-ctrl-help" style={{ marginLeft: 6 }}>Re-fetch ALL messages and rebuild. Expensive!</span>
              </div>
            </div>
          </div>
        </div>
        <div className="bc-controls-row">
          <div className="eyebrow" style={{ marginBottom: 10 }}><span className="rule"></span>Re-analysis</div>
          <div className="bc-ctrl-grid">
            <label className="bc-ctrl-item">
              <span className="bc-ctrl-label">Batch API (50% cheaper)</span>
              <button className={`switch ${batchReanalysisEnabled ? 'on' : ''}`} role="switch" aria-checked={batchReanalysisEnabled} onClick={() => setBatchReanalysisEnabled(!batchReanalysisEnabled)}>
                <span className="switch-knob" />
              </button>
            </label>
            <div className="bc-ctrl-item">
              <span className="bc-ctrl-label">Model</span>
              <select className="field field-mono" style={{ fontSize: 11, padding: '3px 6px', maxWidth: 200 }} value={reanalysisModel} onChange={e => setReanalysisModel(e.target.value)}>
                {models.length ? models.map(m => <option key={m} value={m}>{m}</option>) : <option value={reanalysisModel}>{reanalysisModel}</option>}
              </select>
            </div>
            <label className="bc-ctrl-item">
              <span>
                <span className="bc-ctrl-label">Full context</span>
                <span className="bc-ctrl-help">Include source quotes for every entry. Most accurate, most tokens.</span>
              </span>
              <button className={`switch ${reanalysisFullContext ? 'on' : ''}`} role="switch" aria-checked={reanalysisFullContext} onClick={() => setReanalysisFullContext(!reanalysisFullContext)}>
                <span className="switch-knob" />
              </button>
            </label>
            <label className="bc-ctrl-item">
              <span>
                <span className="bc-ctrl-label">RAG context</span>
                <span className="bc-ctrl-help">Only include source quotes for entries related to newly confirmed words. Cheaper than full.</span>
              </span>
              <button className={`switch ${reanalysisRagContext ? 'on' : ''}`} role="switch" aria-checked={reanalysisRagContext} onClick={() => setReanalysisRagContext(!reanalysisRagContext)}>
                <span className="switch-knob" />
              </button>
            </label>
            <label className="bc-ctrl-item">
              <span>
                <span className="bc-ctrl-label">Allow confirmed revisions</span>
                <span className="bc-ctrl-help">Let re-analysis change confirmed entries. Off = confirmed are protected.</span>
              </span>
              <button className={`switch ${reanalysisAllowConfirmed ? 'on' : ''}`} role="switch" aria-checked={reanalysisAllowConfirmed} onClick={() => setReanalysisAllowConfirmed(!reanalysisAllowConfirmed)}>
                <span className="switch-knob" />
              </button>
            </label>
            <div className="bc-ctrl-item">
              <button className="btn btn-primary" style={{ fontSize: 11, padding: '4px 10px' }} onClick={onReanalyzeNow} disabled={reanalyzing}>{reanalyzing ? '…' : 'Re-analyze now'}</button>
            </div>
          </div>
        </div>
      </div>

      {/* AI Corrections & Teach Me */}
      <div className="bc-controls" style={{ gridTemplateColumns: '1fr', marginTop: 12 }}>
        <div className="bc-controls-row">
          <div className="eyebrow" style={{ marginBottom: 10 }}><span className="rule"></span>AI corrections &amp; Teach Me</div>
          <div className="bc-ctrl-grid">
            <div className="bc-ctrl-item">
              <span>
                <span className="bc-ctrl-label">Model</span>
                <span className="bc-ctrl-help">Used for Ask AI, Rewrite with AI, and Teach Me translations.</span>
              </span>
              <select className="field field-mono" style={{ fontSize: 11, padding: '3px 6px', maxWidth: 200 }} value={correctionModel} onChange={e => setCorrectionModel(e.target.value)}>
                {models.length ? models.map(m => <option key={m} value={m}>{m}</option>) : <option value={correctionModel}>{correctionModel}</option>}
              </select>
            </div>
          </div>
        </div>
      </div>

      <div className="eyebrow" style={{ marginTop: 24, marginBottom: 12 }}><span className="rule"></span>Activity feed</div>

      {cycles.length === 0 && (
        <div className="bc-empty">
          <p className="serif" style={{ fontStyle: 'italic', color: 'var(--fg-mute)', fontSize: 18 }}>No activity yet.</p>
          <p style={{ color: 'var(--fg-dim)', fontSize: 13 }}>The bot will log sync and re-analysis events here.</p>
        </div>
      )}

      <div className="bc-timeline">
        {cycles.map(cycle => {
          const isOpen = expanded[cycle.id] ?? false;
          return (
            <div key={cycle.id} className={`bc-card ${cycle.kind}`}>
              <button className="bc-card-head" onClick={() => toggle(cycle.id)}>
                <span className="bc-card-chevron">{isOpen ? '▼' : '▶'}</span>
                <span className="bc-card-title serif">{cycle.title}</span>
                <span className="bc-card-time mono">{cycle.time}</span>
                {cycle.badge && <span className="bc-badge">{cycle.badge}</span>}
              </button>
              {isOpen && (
                <div className="bc-card-body">
                  {cycle.sections.map((sec, si) => (
                    <div key={si} className={`bc-section bc-section-${sec.kind}`}>
                      {sec.kind === 'messages' && (
                        <div className="bc-messages">
                          <div className="bc-section-label mono">Messages ({sec.data.length})</div>
                          {sec.data.map((m, mi) => (
                            <div key={mi} className="bc-msg">
                              <span className={`bc-msg-tag mono ${m.tag === 'JORN' ? 'jorn' : ''}`}>{m.tag}</span>
                              <span className="bc-msg-text">{m.content || '(empty)'}{m.has_images ? ' 🖼' : ''}</span>
                            </div>
                          ))}
                        </div>
                      )}
                      {sec.kind === 'reasoning' && (
                        <div className="bc-reasoning">
                          <div className="bc-section-label mono">Analyzer reasoning</div>
                          <blockquote className="bc-quote serif">{sec.text}</blockquote>
                        </div>
                      )}
                      {sec.kind === 'stats' && (
                        <div className="bc-stats">
                          {sec.chips.map((c, ci) => (
                            <span key={ci} className="bc-chip mono">{c}</span>
                          ))}
                        </div>
                      )}
                      {sec.kind === 'entries' && (
                        <div className="bc-entries">
                          <div className="bc-section-label mono">{sec.label}</div>
                          {sec.items.map((item, ii) => (
                            <span key={ii} className="bc-chip mono">{item}</span>
                          ))}
                        </div>
                      )}
                    </div>
                  ))}
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

function groupIntoCycles(events) {
  const cycles = [];
  let current = null;

  for (const evt of events) {
    if (evt.type === 'sync_start') {
      current = {
        id: evt.id,
        kind: 'sync',
        title: `Sync · ${evt.data.message_count} messages`,
        time: fmtTime(evt.ts),
        badge: null,
        sections: [],
        _startTs: evt.ts,
      };
    } else if (evt.type === 'sync_chunk' && current?.kind === 'sync') {
      current.sections.push({
        kind: 'messages',
        data: evt.data.messages || [],
      });
    } else if (evt.type === 'sync_analysis' && current?.kind === 'sync') {
      if (evt.data.reasoning) {
        current.sections.push({ kind: 'reasoning', text: evt.data.reasoning });
      }
      const chips = [];
      if (evt.data.added) chips.push(`+${evt.data.added} new`);
      if (evt.data.updated) chips.push(`~${evt.data.updated} updated`);
      if (evt.data.corrected) chips.push(`-${evt.data.corrected} corrected`);
      if (evt.data.examples_added) chips.push(`+${evt.data.examples_added} examples`);
      if (evt.data.rules_added) chips.push(`+${evt.data.rules_added} rules`);
      if (chips.length) current.sections.push({ kind: 'stats', chips });
    } else if (evt.type === 'sync_complete' && current?.kind === 'sync') {
      current.badge = '✓';
      cycles.push(current);
      current = null;
    } else if (evt.type === 'reanalysis_start') {
      current = {
        id: evt.id,
        kind: 'reanalysis',
        title: `Re-analysis · ${(evt.data.newly_confirmed || []).length} newly confirmed`,
        time: fmtTime(evt.ts),
        badge: null,
        sections: [],
        _startTs: evt.ts,
      };
      if (evt.data.newly_confirmed?.length) {
        current.sections.push({
          kind: 'entries',
          label: 'Newly confirmed',
          items: evt.data.newly_confirmed,
        });
      }
    } else if (evt.type === 'reanalysis_result' && current?.kind === 'reanalysis') {
      if (evt.data.reasoning) {
        current.sections.push({ kind: 'reasoning', text: evt.data.reasoning });
      }
      if (evt.data.entries_changed?.length) {
        current.sections.push({
          kind: 'entries',
          label: `Updated (${evt.data.updated || 0})`,
          items: evt.data.entries_changed,
        });
      }
      const chips = [];
      if (evt.data.updated) chips.push(`~${evt.data.updated} revised`);
      if (chips.length) current.sections.push({ kind: 'stats', chips });
    } else if (evt.type === 'reanalysis_complete' && current?.kind === 'reanalysis') {
      current.badge = '✓';
      cycles.push(current);
      current = null;
    } else if (evt.type === 'sync_no_messages') {
      cycles.push({
        id: evt.id,
        kind: 'minor',
        title: 'Sync · no new messages',
        time: fmtTime(evt.ts),
        badge: '—',
        sections: [],
      });
    } else if (evt.type === 'web_request') {
      cycles.push({
        id: evt.id,
        kind: 'request',
        title: evt.data.label || 'Request sent',
        time: fmtTime(evt.ts),
        badge: '⏳',
        sections: [],
      });
    }
  }

  if (current) {
    current.badge = '…';
    cycles.push(current);
  }

  return cycles.reverse();
}

function fmtTime(ts) {
  if (!ts) return '';
  try {
    const d = new Date(ts);
    return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
  } catch {
    return '';
  }
}

Object.assign(window, { BotCentralView });
