// Live terminal typing demo

const { useState: uT, useEffect: eT, useRef: rT } = React;

const DEMO_SCRIPT = [
  { type: 'prompt', text: 'evalyn one-click --project gemini-deep-research-agent' },
  { type: 'delay', ms: 350 },
  { type: 'out', text: '→ detecting framework... langchain', cls: 'dim' },
  { type: 'out', text: '→ loading 137 traces from sqlite://.evalyn/traces.db', cls: 'dim' },
  { type: 'delay', ms: 220 },
  { type: 'out', text: 'STAGE 1/5  collect       ✓  137 calls · 4 projects', cls: 'ok' },
  { type: 'out', text: 'STAGE 2/5  build dataset ✓  stratified · deduplicated', cls: 'ok' },
  { type: 'out', text: 'STAGE 3/5  suggest       ✓  10 metrics (3 obj · 7 llm)', cls: 'ok' },
  { type: 'delay', ms: 300 },
  { type: 'out', text: 'STAGE 4/5  evaluating ...', cls: 'accent' },
  { type: 'progress' },
  { type: 'out', text: '' },
  { type: 'out', text: 'metric                         type   count   pass     avg', cls: 'dim' },
  { type: 'out', text: 'output_nonempty                obj    137    100.0%   1.000', cls: 'row-ok' },
  { type: 'out', text: 'url_count                      obj    137    100.0%   55.18', cls: 'row-ok' },
  { type: 'out', text: 'helpfulness_accuracy           llm    137     95.6%   0.985', cls: 'row-ok' },
  { type: 'out', text: 'clarity_and_readability        llm    137     97.1%   1.000', cls: 'row-ok' },
  { type: 'out', text: 'factual_accuracy               llm    137     79.6%   0.801', cls: 'row-warn' },
  { type: 'out', text: 'conciseness_and_efficiency     llm    137     90.5%   0.910', cls: 'row-warn' },
  { type: 'out', text: '' },
  { type: 'out', text: 'tokens: 10,048,041 in + 70,929 out = 10,118,970  ·  $1.03', cls: 'dim' },
  { type: 'out', text: 'STAGE 5/5  report        ✓  eval_runs/20260127-055659/report.html', cls: 'ok' },
  { type: 'delay', ms: 200 },
  { type: 'out', text: '' },
  { type: 'out', text: '→ hint: factual_accuracy pass rate is low. run:', cls: 'dim' },
  { type: 'out', text: '  evalyn annotate --latest  &&  evalyn calibrate --metric-id factual_accuracy', cls: 'accent' },
];

function LiveTerminal({ theme, compact = false }) {
  const printMode = typeof window !== 'undefined' && window.__printMode;
  const initialLines = printMode
    ? DEMO_SCRIPT
        .filter(s => s.type !== 'delay')
        .map(s => s.type === 'prompt' ? { type: 'prompt', text: s.text } : s)
    : [];
  const [lines, setLines] = useState(initialLines);
  const [cursor, setCursor] = useState(true);
  const [running, setRunning] = useState(printMode);
  const [finished, setFinished] = useState(printMode);
  const [progress, setProgress] = useState(printMode ? 100 : 0);
  const containerRef = useRef(null);

  // Start on scroll into view
  useEffect(() => {
    if (printMode) return;
    if (!containerRef.current) return;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting && !running) { setRunning(true); io.disconnect(); }
    }, { threshold: 0.35 });
    io.observe(containerRef.current);
    return () => io.disconnect();
  }, [running, printMode]);

  useEffect(() => {
    if (!running || printMode) return;
    let cancelled = false;
    (async () => {
      for (let i = 0; i < DEMO_SCRIPT.length; i++) {
        if (cancelled) return;
        const step = DEMO_SCRIPT[i];
        if (step.type === 'delay') {
          await new Promise(r => setTimeout(r, step.ms));
        } else if (step.type === 'prompt') {
          // Type character by character
          for (let c = 0; c <= step.text.length; c++) {
            if (cancelled) return;
            setLines(prev => {
              const copy = [...prev];
              copy[copy.length - 1] = { type: 'prompt', text: step.text.slice(0, c) };
              return copy;
            });
            if (c === 0) setLines(prev => [...prev, { type: 'prompt', text: '' }]);
            await new Promise(r => setTimeout(r, 28 + Math.random() * 40));
          }
          await new Promise(r => setTimeout(r, 240));
        } else if (step.type === 'out') {
          setLines(prev => [...prev, step]);
          await new Promise(r => setTimeout(r, 110));
        } else if (step.type === 'progress') {
          setLines(prev => [...prev, { type: 'progress' }]);
          for (let p = 0; p <= 100; p += 4) {
            if (cancelled) return;
            setProgress(p);
            await new Promise(r => setTimeout(r, 30));
          }
        }
      }
      setFinished(true);
    })();
    return () => { cancelled = true; };
  }, [running]);

  useEffect(() => {
    const t = setInterval(() => setCursor(c => !c), 500);
    return () => clearInterval(t);
  }, []);

  // Auto-scroll
  useEffect(() => {
    if (containerRef.current) {
      const bodyEl = containerRef.current.querySelector('[data-body]');
      if (bodyEl) bodyEl.scrollTop = bodyEl.scrollHeight;
    }
  }, [lines, progress]);

  const colorFor = (cls) => {
    if (cls === 'ok') return theme.accent;
    if (cls === 'accent') return theme.accent;
    if (cls === 'dim') return theme.textMute;
    if (cls === 'row-ok') return theme.text;
    if (cls === 'row-warn') return theme.text;
    return theme.text;
  };

  return (
    <div ref={containerRef} style={{
      background: theme.scheme === 'dark' ? '#0a0805' : '#1a1510',
      border: `1px solid ${theme.borderStrong}`,
      fontFamily: 'var(--mono)',
      fontSize: compact ? 11 : 12.5,
      color: theme.text,
      boxShadow: `0 30px 60px -30px rgba(0,0,0,0.6), 0 0 0 1px ${theme.border}`,
      position: 'relative',
      overflow: 'hidden',
    }}>
      {/* chrome */}
      <div style={{
        padding: '10px 14px',
        borderBottom: `1px solid ${theme.border}`,
        display: 'flex', alignItems: 'center', gap: 10,
        background: 'rgba(0,0,0,0.35)',
      }}>
        <span style={{ width: 10, height: 10, borderRadius: 10, background: '#ff5f57' }} />
        <span style={{ width: 10, height: 10, borderRadius: 10, background: '#ffbd2e' }} />
        <span style={{ width: 10, height: 10, borderRadius: 10, background: '#28ca41' }} />
        <span style={{ flex: 1, textAlign: 'center', color: theme.textMute, fontSize: 11, letterSpacing: '0.08em' }}>
          zsh — evalyn one-click — 120×32
        </span>
        <span style={{
          color: theme.accent, fontSize: 10, letterSpacing: '0.15em',
          border: `1px solid ${theme.accentHair}`, padding: '1px 6px',
        }}>● LIVE</span>
      </div>
      <div data-body style={{
        padding: '18px 18px 14px',
        minHeight: compact ? 340 : 440,
        maxHeight: compact ? 340 : 440,
        overflow: 'auto',
        lineHeight: 1.65,
      }}>
        {lines.map((l, i) => {
          if (l.type === 'progress') {
            const p = i === lines.findIndex(x => x.type === 'progress') ? progress : 100;
            const w = 40;
            const filled = Math.round((p / 100) * w);
            return (
              <div key={i} style={{ color: theme.accent, margin: '4px 0' }}>
                <span style={{ color: theme.textMute }}>evaluating </span>
                [<span style={{ color: theme.accent }}>{'█'.repeat(filled)}</span><span style={{ color: theme.textMute }}>{'░'.repeat(w - filled)}</span>] {String(p).padStart(3,' ')}%
              </div>
            );
          }
          const isLast = i === lines.length - 1;
          return (
            <div key={i} style={{
              color: colorFor(l.cls),
              whiteSpace: 'pre',
              ...(l.cls === 'row-warn' ? { background: `${theme.accentSoft}`, margin: '0 -18px', padding: '0 18px' } : {}),
            }}>
              {l.type === 'prompt' ? (
                <>
                  <span style={{ color: theme.accent }}>$ </span>
                  <span>{l.text}</span>
                  {isLast && !finished && <span style={{
                    display: 'inline-block', width: 7, height: 14,
                    background: cursor ? theme.accent : 'transparent',
                    marginLeft: 2, verticalAlign: 'middle',
                  }} />}
                </>
              ) : l.text || '\u00a0'}
              {isLast && l.type === 'out' && !finished && l.cls !== undefined && null}
            </div>
          );
        })}
        {finished && (
          <div style={{ marginTop: 10, color: theme.textMute }}>
            <span style={{ color: theme.accent }}>$ </span>
            <span style={{
              display: 'inline-block', width: 7, height: 14,
              background: cursor ? theme.accent : 'transparent',
              verticalAlign: 'middle',
            }} />
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { LiveTerminal, DEMO_SCRIPT });
