// screen-datastream.jsx
// PROTOCOL 01 — DATASTREAM DECODE
// Packets stream in. Player tags TRUE (ENTER) or FALSE (purge).
// Squad NPCs also vote; sync = combo.

const { useState: useSt1, useEffect: useEf1, useRef: useRef1, useMemo: useMemo1 } = React;

function DatastreamScreen({ run, difficulty, onComplete }) {
  const baseCfg = DIFF_CFG[difficulty];
  const tMul = window.__sylExtendedTime ? 1.5 : 1;
  const cfg = { ...baseCfg, dsTimePerPacket: baseCfg.dsTimePerPacket * tMul };
  const packets = useMemo1(() => shuffle(DATASTREAM_PACKETS).slice(0, cfg.dsPackets), []);

  const [idx, setIdx] = useSt1(0);
  const [score, setScore] = useSt1(0);
  const [combo, setCombo] = useSt1(0);
  const [syncFlash, setSyncFlash] = useSt1(false);
  const [feedback, setFeedback] = useSt1(null); // { ok, why }
  const [timeLeft, setTimeLeft] = useSt1(cfg.dsTimePerPacket);
  const [npcVotes, setNpcVotes] = useSt1([]);
  const [shake, setShake] = useSt1(false);
  const [packetKey, setPacketKey] = useSt1(0);
  const [floats, setFloats] = useSt1([]);

  const packet = packets[idx];
  const done = idx >= packets.length;

  // Reset clock + NPC votes when packet changes
  useEf1(() => {
    if (done) return;
    setTimeLeft(cfg.dsTimePerPacket);
    setFeedback(null);
    setNpcVotes([]);
    if (run.mode === 'solo') return; // No squadmate votes in solo
    // NPCs vote at staggered intervals; some are right, some confused.
    const timers = run.teammates.map((tm, i) => {
      const delay = 600 + Math.random() * 1800;
      const correctChance = 0.65 + (3 - i) * 0.05; // decreasing reliability
      const willBeCorrect = Math.random() < correctChance;
      return setTimeout(() => {
        setNpcVotes((v) => [...v, { id: tm.id, vote: willBeCorrect ? packet.truth : !packet.truth }]);
      }, delay);
    });
    return () => timers.forEach(clearTimeout);
  }, [idx, done]);

  // Countdown
  useEf1(() => {
    if (done || feedback) return;
    if (timeLeft <= 0) { resolve(null); return; }
    if (window.__sylPaused) return;
    const t = setTimeout(() => setTimeLeft(timeLeft - 0.1), 100);
    return () => clearTimeout(t);
  }, [timeLeft, feedback, done]);

  // Re-trigger timer effect when pause state changes
  useEf1(() => {
    function onPause() { setTimeLeft((v) => v); /* force effect re-run */ }
    window.addEventListener('syl-pause', onPause);
    return () => window.removeEventListener('syl-pause', onPause);
  }, []);

  // Keyboard
  useEf1(() => {
    const onKey = (e) => {
      if (done || feedback) return;
      if (e.key === 'ArrowRight' || e.key === 'Enter') resolve(true);
      else if (e.key === 'ArrowLeft' || e.key === 'Backspace') resolve(false);
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  });

  function resolve(playerVote) {
    if (feedback) return;
    const ok = playerVote === packet.truth;
    const correctNpcs = npcVotes.filter((v) => v.vote === packet.truth).length;
    const isSolo = run.mode === 'solo';
    const synced = !isSolo && ok && correctNpcs >= 2;
    if (synced) setSyncFlash(true);
    setTimeout(() => setSyncFlash(false), 600);

    let gain = 0;
    if (ok) {
      const base = 100;
      const speedBonus = Math.round(timeLeft * 8);
      const comboBonus = combo * 25;
      const syncBonus = synced ? Math.round((base + speedBonus + comboBonus) * 0.5) : 0;
      gain = base + speedBonus + comboBonus + syncBonus;
      setCombo(combo + 1);
    } else {
      setCombo(0);
      setShake(true);
      setTimeout(() => setShake(false), 400);
    }
    setScore(score + gain);
    setFeedback({ ok, why: packet.why || `Correct. ${packet.source}.`, gain, synced });
    window.sylAnnounce && window.sylAnnounce(
      ok ? `Authentic. Plus ${gain} XP.` : 'False positive. Zero XP.',
      true
    );
    if (gain > 0) {
      const fId = Math.random();
      setFloats((f) => [...f, { id: fId, gain, synced }]);
      setTimeout(() => setFloats((f) => f.filter(x => x.id !== fId)), 1100);
    }

    setTimeout(() => {
      if (idx + 1 >= packets.length) {
        onComplete({ protocol: 'datastream', score: score + gain });
      } else {
        setIdx(idx + 1);
        setPacketKey(packetKey + 1);
      }
    }, 1800);
  }

  if (done) return null;

  const totalCorrectNpcs = npcVotes.filter((v) => v.vote === packet.truth).length;

  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
      <ProtocolHeader
        num="01" name="DATASTREAM DECODE"
        progress={`${idx + 1}/${packets.length}`}
        score={score} combo={combo} accent="var(--neon-cyan)"
      />

      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1fr 280px', gap: 24, padding: '24px 48px 32px', minHeight: 0 }}>
        {/* Packet stage */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 20, minWidth: 0, position: 'relative' }}>
          {/* Timer bar */}
          <div style={{ position: 'relative', height: 4, background: 'rgba(0,234,255,.1)' }}>
            <div style={{
              position: 'absolute', left: 0, top: 0, bottom: 0,
              width: `${(timeLeft / cfg.dsTimePerPacket) * 100}%`,
              background: timeLeft < 2 ? 'var(--neon-red)' : 'var(--neon-cyan)',
              boxShadow: `0 0 12px ${timeLeft < 2 ? 'var(--neon-red)' : 'var(--neon-cyan)'}`,
              transition: 'width .1s linear, background .3s',
            }} />
          </div>

          {/* The packet itself */}
          <div
            key={packetKey}
            className={`panel ${shake ? 'shake' : ''}`}
            style={{
              flex: 1, padding: '40px 48px', display: 'flex', flexDirection: 'column',
              justifyContent: 'center', position: 'relative', minHeight: 0,
              animation: 'packet-in .4s',
              borderColor: feedback ? (feedback.ok ? 'var(--neon-lime)' : 'var(--neon-red)') : 'rgba(0,234,255,.18)',
              boxShadow: feedback ? `0 0 48px ${feedback.ok ? 'rgba(170,255,0,.25)' : 'rgba(255,51,85,.25)'}` : 'none',
              transition: 'border-color .3s, box-shadow .3s',
            }}
          >
            <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 20 }}>
              <div className="chip">◇ INTERCEPTED PACKET</div>
              <div style={{ fontSize: 10, color: 'var(--ink-60)', letterSpacing: '0.14em' }}>
                ID/0x{packet.id.toUpperCase().padStart(4, '0')} · CHAN/Δ7
              </div>
            </div>

            <div className="t-mono" style={{
              fontSize: 22, lineHeight: 1.5, color: 'var(--ink-100)',
              letterSpacing: '0.01em', textWrap: 'pretty',
            }}>
              <span style={{ color: 'var(--neon-cyan)' }}>"</span>
              {packet.text}
              <span style={{ color: 'var(--neon-cyan)' }}>"</span>
            </div>

            <div style={{ marginTop: 20, fontSize: 10, color: 'var(--ink-60)', letterSpacing: '0.14em', textTransform: 'uppercase' }}>
              ◇ SOURCE NODE: {packet.source}
            </div>

            {/* Floating score */}
            {floats.map(f => (
              <div key={f.id} style={{
                position: 'absolute', top: 24, right: 32,
                fontFamily: 'Orbitron', fontWeight: 800, fontSize: 36,
                color: f.synced ? 'var(--neon-yellow)' : 'var(--neon-lime)',
                textShadow: `0 0 16px ${f.synced ? 'rgba(251,191,36,.7)' : 'rgba(170,255,0,.5)'}`,
                animation: 'float-up 1.1s ease-out forwards', pointerEvents: 'none',
              }}>
                +{f.gain}
                {f.synced && <div style={{ fontSize: 11, letterSpacing: '0.2em', textAlign: 'right', marginTop: 4 }}>SYNC</div>}
              </div>
            ))}

            {/* Feedback overlay */}
            {feedback && (
              <div style={{
                position: 'absolute', left: 24, right: 24, bottom: 24,
                background: 'rgba(0,0,0,.7)',
                borderLeft: `3px solid ${feedback.ok ? 'var(--neon-lime)' : 'var(--neon-red)'}`,
                padding: '12px 16px', fontSize: 12, color: 'var(--ink-80)', lineHeight: 1.5,
              }}>
                <span className="t-display" style={{ color: feedback.ok ? 'var(--neon-lime)' : 'var(--neon-red)', letterSpacing: '0.12em', marginRight: 8 }}>
                  {feedback.ok ? '◉ AUTHENTIC' : '◉ FALSE POSITIVE'}
                </span>
                {feedback.why}
              </div>
            )}
          </div>

          {/* Action buttons */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
            <ActionBtn
              label="◀ PURGE / FALSE"
              aria="Purge as false. Keyboard: left arrow or delete."
              hint="← / DEL"
              color="var(--neon-magenta)"
              onClick={() => resolve(false)}
              disabled={!!feedback}
            />
            <ActionBtn
              label="LET THROUGH / TRUE ▶"
              aria="Let through as true. Keyboard: right arrow or enter."
              hint="→ / ENTER"
              color="var(--neon-lime)"
              onClick={() => resolve(true)}
              disabled={!!feedback}
            />
          </div>
        </div>

        {/* Squad sync panel */}
        <div className="panel" style={{ padding: 20, display: 'flex', flexDirection: 'column', gap: 12,
          borderColor: syncFlash ? 'var(--neon-yellow)' : 'rgba(0,234,255,.18)',
          boxShadow: syncFlash ? '0 0 32px rgba(251,191,36,.5)' : 'none',
          transition: 'all .3s',
        }}>
          {run.mode === 'solo' ? (
            <>
              <div className="chip chip-magenta">◇ SOLO RUN</div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px',
                background: `${run.role.accent}10`, border: `1px solid ${run.role.accent}33` }}>
                <div style={{
                  width: 32, height: 32, background: `${run.role.accent}22`,
                  border: `1px solid ${run.role.accent}88`, color: run.role.accent,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontFamily: 'Orbitron', fontWeight: 800, fontSize: 16,
                }}>{run.role.glyph}</div>
                <div>
                  <div className="t-mono" style={{ fontSize: 12, color: run.role.accent, letterSpacing: '0.06em' }}>
                    YOU ◆
                  </div>
                  <div style={{ fontSize: 9, color: 'var(--ink-60)', letterSpacing: '0.12em', marginTop: 2 }}>
                    {run.role.name}
                  </div>
                </div>
              </div>
              <div style={{ fontSize: 10, color: 'var(--ink-60)', lineHeight: 1.6, padding: 8 }}>
                ◇ No squadmates. No sync bonus. Pure score, every packet counts double.
              </div>
            </>
          ) : (
            <>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <div className={`chip ${syncFlash ? 'chip-yellow' : ''}`}>◇ SQUAD VOTES</div>
            <div style={{ fontSize: 10, color: 'var(--ink-60)' }}>{npcVotes.length}/3</div>
          </div>

          {[
            { ...run.role, callsign: 'YOU', you: true },
            ...run.teammates,
          ].map((tm, i) => {
            const v = i === 0 ? null : npcVotes.find((x) => x.id === tm.id);
            return (
              <div key={i} style={{
                display: 'flex', alignItems: 'center', gap: 10,
                padding: '8px 10px',
                background: `${tm.accent}10`,
                border: `1px solid ${tm.accent}33`,
              }}>
                <div style={{
                  width: 28, height: 28, background: `${tm.accent}22`,
                  border: `1px solid ${tm.accent}88`, color: tm.accent,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontFamily: 'Orbitron', fontWeight: 800, fontSize: 14,
                }}>{tm.glyph}</div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div className="t-mono" style={{ fontSize: 11, color: tm.accent, letterSpacing: '0.06em' }}>
                    {tm.callsign}{tm.you && ' ◆'}
                  </div>
                </div>
                <div style={{ fontSize: 11, fontFamily: 'Orbitron', fontWeight: 700, letterSpacing: '0.1em',
                  color: v ? (v.vote ? 'var(--neon-lime)' : 'var(--neon-magenta)') : 'var(--ink-40)',
                }}>
                  {tm.you ? '...' : (v ? (v.vote ? 'TRUE' : 'FALSE') : '...')}
                </div>
              </div>
            );
          })}
            </>
          )}

          <div style={{ marginTop: 'auto', paddingTop: 12, borderTop: '1px solid rgba(0,234,255,.1)' }}>
            <div style={{ fontSize: 10, color: 'var(--ink-60)', letterSpacing: '0.14em', marginBottom: 4 }}>
              ◇ COMBO STREAK
            </div>
            <div className="t-display" style={{ fontSize: 32, color: combo > 0 ? 'var(--neon-yellow)' : 'var(--ink-40)', letterSpacing: '0.04em', textShadow: combo > 2 ? '0 0 12px rgba(251,191,36,.6)' : 'none' }}>
              ×{combo}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function ActionBtn({ label, hint, color, onClick, disabled, aria }) {
  return (
    <button
      onClick={onClick} disabled={disabled}
      aria-label={aria || label}
      className="t-display"
      style={{
        appearance: 'none', cursor: 'pointer',
        background: `linear-gradient(180deg, ${color}28, ${color}08)`,
        border: `1px solid ${color}88`,
        color, padding: '20px 24px', fontSize: 16, letterSpacing: '0.12em',
        clipPath: 'polygon(12px 0, 100% 0, calc(100% - 12px) 100%, 0 100%)',
        position: 'relative', overflow: 'hidden',
        boxShadow: `0 0 24px ${color}22, inset 0 0 24px ${color}10`,
        opacity: disabled ? 0.4 : 1, transition: 'all .15s',
      }}
      onMouseEnter={(e) => { if (!disabled) e.currentTarget.style.filter = 'brightness(1.3)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.filter = 'none'; }}
    >
      <div>{label}</div>
      <div style={{ fontSize: 10, opacity: .6, marginTop: 6, letterSpacing: '0.16em' }}>[ {hint} ]</div>
    </button>
  );
}

function ProtocolHeader({ num, name, progress, score, combo, accent }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      padding: '20px 48px', borderBottom: `1px solid ${accent}33`,
      background: `linear-gradient(180deg, ${accent}08, transparent)`,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 24 }}>
        <div className="t-display" style={{ fontSize: 36, color: accent, letterSpacing: '0.04em', textShadow: `0 0 16px ${accent}88` }}>
          {num}
        </div>
        <div>
          <div className="t-display" style={{ fontSize: 18, letterSpacing: '0.08em', color: 'var(--ink-100)' }}>{name}</div>
          <div style={{ fontSize: 10, color: 'var(--ink-60)', letterSpacing: '0.14em', marginTop: 2 }}>
            ◇ PROTOCOL ACTIVE · {progress}
          </div>
        </div>
      </div>
      <div style={{ display: 'flex', gap: 32, alignItems: 'center' }}>
        <Stat label="SCORE" value={score.toLocaleString()} accent={accent} />
        {combo != null && <Stat label="COMBO" value={`×${combo}`} accent={combo > 0 ? 'var(--neon-yellow)' : 'var(--ink-60)'} />}
      </div>
    </div>
  );
}

function Stat({ label, value, accent }) {
  return (
    <div style={{ textAlign: 'right' }}>
      <div style={{ fontSize: 9, color: 'var(--ink-60)', letterSpacing: '0.18em' }}>{label}</div>
      <div className="t-display" style={{ fontSize: 22, color: accent, letterSpacing: '0.06em', fontVariantNumeric: 'tabular-nums' }}>
        {value}
      </div>
    </div>
  );
}

function shuffle(arr) {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

const DIFF_CFG = {
  recruit:  { dsPackets: 5, dsTimePerPacket: 12, dlNodes: 4, dlTime: 50, pfTime: 18 },
  operative: { dsPackets: 7, dsTimePerPacket: 9, dlNodes: 6, dlTime: 45, pfTime: 14 },
  ghost:    { dsPackets: 9, dsTimePerPacket: 6, dlNodes: 8, dlTime: 40, pfTime: 10 },
};

Object.assign(window, { DatastreamScreen, ProtocolHeader, Stat, shuffle, DIFF_CFG });
