/* global React */
const { useState: stS, useEffect: stE, useMemo: stM, useRef: stR } = React;

// 8 Frage/Antwort-Paare — kurz, on-brand, monochrom rendert
const STREAM_PAIRS = [
  { kind: 'typewriter', label: 'Typewriter',  q: 'Wann startet ein Projekt?',     a: 'Audit in 2 Wochen, Build ab Woche 3.' },
  { kind: 'words',      label: 'Word fade',   q: 'Was kostet ein Retainer?',      a: 'Ab €18.000 pro Monat für ein 3er-Team.' },
  { kind: 'tokens',     label: 'Token chunks',q: 'Welches Modell läuft?',         a: 'Claude Code fürs Reasoning, GPT-5 für Sprache.' },
  { kind: 'blur',       label: 'Blur reveal', q: 'Bekomme ich Logs?',             a: 'Ja, jeder Agent-Call ist einsehbar.' },
  { kind: 'cascade',    label: 'Cascade',     q: 'Wer arbeitet am Projekt?',      a: 'Senior-Team. Kein Outsourcing, kein Praktikant.' },
  { kind: 'lines',      label: 'Line slide',  q: 'Wie reportet ihr?',             a: 'Wöchentlich KPIs.\nMonatlich Strategie.\nQuartalsweise Audit.' },
  { kind: 'decode',     label: 'Decode',      q: 'Was bekomme ich am Ende?',      a: 'Code, Doku, Training — alles übergebbar.' },
  { kind: 'drop',       label: 'Drop in',     q: 'Was, wenn AI nicht passt?',     a: 'Sagen wir dir im Audit.' },
];

// ---------- Renderer ----------
function STypewriter({ text }) {
  const [n, setN] = stS(0);
  stE(() => {
    if (n >= text.length) return;
    const t = setTimeout(() => setN(x => x + 1), 30 + (text[n] === ' ' ? 40 : 0));
    return () => clearTimeout(t);
  }, [n, text]);
  const done = n >= text.length;
  return <span>{text.slice(0, n)}{!done && <span className="sc-caret">▌</span>}</span>;
}

function SWords({ text }) {
  const words = text.split(' ');
  return <span className="sc-words">{words.map((w, i) =>
    <span key={i} style={{ animationDelay: `${i * 95}ms` }}>{w}{i < words.length - 1 ? '\u00A0' : ''}</span>
  )}</span>;
}

function STokens({ text }) {
  const chunks = stM(() => {
    const out = []; let i = 0;
    while (i < text.length) {
      const len = 2 + Math.floor(Math.random() * 4); // 2–5
      out.push(text.slice(i, i + len));
      i += len;
    }
    return out;
  }, [text]);
  const [n, setN] = stS(0);
  stE(() => {
    if (n >= chunks.length) return;
    const t = setTimeout(() => setN(x => x + 1), 70 + Math.random() * 70);
    return () => clearTimeout(t);
  }, [n, chunks]);
  const done = n >= chunks.length;
  return <span>{chunks.slice(0, n).join('')}{!done && <span className="sc-caret">▌</span>}</span>;
}

function SCascade({ text }) {
  return <span className="sc-cascade">{[...text].map((c, i) =>
    <span key={i} style={{ animationDelay: `${i * 16}ms` }}>{c === ' ' ? '\u00A0' : c}</span>
  )}</span>;
}

function SBlur({ text }) {
  const words = text.split(' ');
  return <span className="sc-blur">{words.map((w, i) =>
    <span key={i} style={{ animationDelay: `${i * 130}ms` }}>{w}{i < words.length - 1 ? '\u00A0' : ''}</span>
  )}</span>;
}

const SCRAMBLE_GLYPHS = '/\\<>{}[]+=-#$%&*?';
function SScramble({ text }) {
  const [tick, setTick] = stS(0);
  stE(() => {
    const id = setInterval(() => setTick(t => t + 1), 30);
    return () => clearInterval(id);
  }, []);
  const out = [...text].map((c, i) => {
    if (c === ' ' || c === '\n' || c === ',' || c === '.') return c;
    const start = i * 2;
    const end = start + 7;
    if (tick < start) return '\u00A0';
    if (tick >= end) return c;
    return SCRAMBLE_GLYPHS[Math.floor(Math.random() * SCRAMBLE_GLYPHS.length)];
  });
  return <span>{out.join('')}</span>;
}

function SWipe({ text }) {
  return <span className="sc-wipe-wrap"><span className="sc-wipe-ghost">{text}</span><span className="sc-wipe">{text}</span></span>;
}

function SLines({ text }) {
  const lines = text.split('\n');
  return <>{lines.map((l, i) =>
    <div key={i} className="sc-line" style={{ animationDelay: `${i * 360}ms` }}>{l}</div>
  )}</>;
}

const DECODE_GLYPHS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#@$%&';
function SDecode({ text }) {
  const [tick, setTick] = stS(0);
  stE(() => {
    const id = setInterval(() => setTick(t => t + 1), 38);
    return () => clearInterval(id);
  }, []);
  const out = [...text].map((c, i) => {
    if (c === ' ' || c === '\n') return c;
    const settleAt = i * 2 + 4;
    if (tick >= settleAt) return c;
    return DECODE_GLYPHS[Math.floor(Math.random() * DECODE_GLYPHS.length)];
  });
  return <span className="sc-mono">{out.join('')}</span>;
}

function SDrop({ text }) {
  return <span className="sc-drop">{[...text].map((c, i) =>
    <span key={i} style={{ animationDelay: `${i * 26}ms` }}>{c === ' ' ? '\u00A0' : c}</span>
  )}</span>;
}

const RENDERERS = {
  typewriter: STypewriter,
  words:      SWords,
  tokens:     STokens,
  cascade:    SCascade,
  blur:       SBlur,
  scramble:   SScramble,
  wipe:       SWipe,
  lines:      SLines,
  decode:     SDecode,
  drop:       SDrop,
};

const DURATIONS = {
  typewriter: a => a.length * 32 + 250,
  words:      a => a.split(' ').length * 95 + 320,
  tokens:     a => Math.ceil(a.length / 3) * 110 + 250,
  cascade:    a => a.length * 16 + 420,
  blur:       a => a.split(' ').length * 130 + 600,
  scramble:   a => a.length * 30 * 2 + 350,
  wipe:       _ => 1900,
  lines:      a => a.split('\n').length * 360 + 600,
  decode:     a => a.length * 76 + 400,
  drop:       a => a.length * 26 + 520,
};

// ---------- Cell ----------
function StreamCell({ idx, kind, label, q, a }) {
  const [version, setVersion] = stS(0);

  stE(() => {
    const dur = (DURATIONS[kind] || (() => 2200))(a);
    const total = Math.max(2200, dur) + 1700;
    const t = setTimeout(() => setVersion(v => v + 1), total);
    return () => clearTimeout(t);
  }, [version, kind, a]);

  const Renderer = RENDERERS[kind];

  return (
    <div className="stream-cell">
      <div className="sc-top">
        <span className="sc-num">/ {String(idx + 1).padStart(2, '0')}</span>
        <span className="sc-name">{label}</span>
      </div>
      <div className="sc-body">
        <div className="sc-q-wrap"><div className="sc-q">{q}</div></div>
        <div className="sc-a" key={version}>
          <Renderer text={a} />
        </div>
      </div>
    </div>
  );
}

// ---------- Section ----------
function StreamSection() {
  return (
    <section className="section stream-section">
      <div className="container">
        <div className="stream-head">
          <span className="tag">Stream Studies</span>
          <h2 className="display h-3" style={{ margin: '20px 0 8px', maxWidth: '22ch' }}>
            Wie eine Antwort entsteht.
          </h2>
          <p className="stream-sub">Acht Mikro-Patterns. Eine Frage. Was passiert, während die Maschine denkt.</p>
        </div>
        <div className="stream-grid">
          {STREAM_PAIRS.map((p, i) => <StreamCell key={p.kind} idx={i} {...p} />)}
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { StreamSection });
