// local-game.jsx — single-phone pass-and-play mode (no server / room needed)
// Exports: LocalGame

function LocalGame({ metaphor, onExit }) {
  const { useState, useEffect, useRef } = React;

  const SLOT_TIMES = window.SLOT_TIMES || [8, 12, 18, 25];

  const blank = {
    phase: 'setup',          // setup | handoff | pick | order | play | result | end
    teams: [],
    activeTeamIndex: 0,
    round: 1,
    rounds: 2,
    currentSlots: null,
    chosenCards: null,
    orderedCards: null,
    cardStates: null,
    activeCardIndex: 0,
    timeLeft: 0,
    bufferTimeLeft: 0,
    bufferWord: null,
  };

  const [g, setG] = useState(blank);
  const [showExit, setShowExit] = useState(false);
  const [teamInputs, setTeamInputs] = useState(['', '']);
  const [roundsPick, setRoundsPick] = useState(2);
  const timerRef = useRef(null);

  const stopTimer = () => { clearInterval(timerRef.current); timerRef.current = null; };

  // ── Score + transition to result ─────────────────────────────────────────
  function scoreAndResult(prev, finalStates) {
    const pts = (prev.orderedCards || []).reduce(
      (sum, c, i) => sum + (finalStates[i]?.status === 'guessed' ? c.pts : 0), 0
    );
    const newTeams = prev.teams.map((t, i) =>
      i === prev.activeTeamIndex ? { ...t, score: t.score + pts } : t
    );
    return { ...prev, cardStates: finalStates, teams: newTeams, phase: 'result' };
  }

  // ── Timer — runs only during 'play' phase ─────────────────────────────────
  useEffect(() => {
    if (g.phase !== 'play') { stopTimer(); return; }
    timerRef.current = setInterval(() => {
      setG(prev => {
        if (prev.phase !== 'play') { clearInterval(timerRef.current); return prev; }

        // Inter-card buffer countdown
        if (prev.bufferTimeLeft > 0) {
          const newBuf = prev.bufferTimeLeft - 1;
          if (newBuf === 0) {
            const next = prev.activeCardIndex + 1;
            if (next < prev.cardStates.length) {
              const newStates = prev.cardStates.map((s, i) =>
                i === next ? { ...s, status: 'active' } : s
              );
              return { ...prev, cardStates: newStates, activeCardIndex: next, timeLeft: newStates[next].timeLeft, bufferTimeLeft: 0, bufferWord: null };
            }
            clearInterval(timerRef.current);
            return scoreAndResult(prev, prev.cardStates);
          }
          return { ...prev, bufferTimeLeft: newBuf };
        }

        const ai = prev.activeCardIndex;
        const cs = prev.cardStates?.[ai];
        if (!cs || cs.status !== 'active') return prev;

        const newTime = cs.timeLeft - 1;
        const newStates = prev.cardStates.map((s, i) =>
          i === ai ? { ...s, timeLeft: Math.max(0, newTime) } : s
        );

        if (newTime <= 0) {
          window.sfx && window.sfx.blast();
          newStates[ai] = { ...newStates[ai], status: 'blasted', timeLeft: 0 };
          const next = ai + 1;
          if (next < newStates.length) {
            const word = prev.orderedCards[ai].word;
            return { ...prev, cardStates: newStates, bufferTimeLeft: 4, bufferWord: word };
          }
          clearInterval(timerRef.current);
          return scoreAndResult(prev, newStates);
        }

        return { ...prev, cardStates: newStates, timeLeft: newTime };
      });
    }, 1000);
    return stopTimer;
  }, [g.phase]); // eslint-disable-line react-hooks/exhaustive-deps

  // ── Actions ───────────────────────────────────────────────────────────────
  const startGame = () => {
    const valid = teamInputs.filter(n => n.trim()).map(n => ({ name: n.trim(), score: 0 }));
    if (valid.length < 2) return;
    window.sfx && window.sfx.start();
    setG({ ...blank, phase: 'handoff', teams: valid, rounds: roundsPick, round: 1, activeTeamIndex: 0, currentSlots: window.dealSlots() });
  };

  const handlePicked = (cards) => {
    window.sfx && window.sfx.lock();
    setG(prev => ({ ...prev, phase: 'order', chosenCards: cards }));
  };

  const handleOrdered = (sequenced) => {
    const cardStates = sequenced.map((c, i) => ({
      status: i === 0 ? 'active' : 'waiting',
      timeLeft: c.slotTime,
    }));
    setG(prev => ({
      ...prev, orderedCards: sequenced, cardStates, activeCardIndex: 0,
      timeLeft: sequenced[0].slotTime, phase: 'play',
    }));
  };

  const handleGuessed = () => {
    setG(prev => {
      if (prev.phase !== 'play' || prev.bufferTimeLeft > 0) return prev;
      const ai = prev.activeCardIndex;
      const card = prev.orderedCards[ai];
      const newStates = prev.cardStates.map((s, i) =>
        i === ai ? { ...s, status: 'guessed' } : s
      );
      const allDone = newStates.every(s => s.status === 'guessed' || s.status === 'blasted');
      if (allDone) { clearInterval(timerRef.current); return scoreAndResult(prev, newStates); }
      // Enter 4-second buffer before next card
      return { ...prev, cardStates: newStates, bufferTimeLeft: 4, bufferWord: card.word };
    });
  };

  const handleEndTurn = () => {
    setG(prev => {
      if (prev.phase !== 'play') return prev;
      clearInterval(timerRef.current);
      const newStates = prev.cardStates.map(s =>
        s.status === 'active' || s.status === 'waiting' ? { ...s, status: 'blasted' } : s
      );
      return scoreAndResult(prev, newStates);
    });
  };

  const handleNext = () => {
    window.sfx && window.sfx.woosh();
    setG(prev => {
      const ni = (prev.activeTeamIndex + 1) % prev.teams.length;
      const roundOver = ni === 0;
      const nextRound = roundOver ? prev.round + 1 : prev.round;
      if (nextRound > prev.rounds) return { ...prev, phase: 'end' };
      return {
        ...prev, phase: 'handoff', activeTeamIndex: ni, round: nextRound,
        currentSlots: window.dealSlots(), chosenCards: null, orderedCards: null,
        cardStates: null, activeCardIndex: 0,
      };
    });
  };

  const handleRestart = () => {
    window.sfx && window.sfx.start();
    setTeamInputs(['', '']);
    setRoundsPick(2);
    setG(blank);
  };

  const isLastTurn = () => {
    const ni = (g.activeTeamIndex + 1) % g.teams.length;
    const nextRound = ni === 0 ? g.round + 1 : g.round;
    return nextRound > g.rounds;
  };

  // ── Exit modal ────────────────────────────────────────────────────────────
  const exitModal = showExit && (
    <Modal
      icon="🚪"
      title="Exit game?"
      body="Scores will be lost. Return to the main menu."
      confirmLabel="Exit"
      cancelLabel="Keep Playing"
      onConfirm={() => { stopTimer(); onExit(); }}
      onCancel={() => setShowExit(false)}
      danger={true}
    />
  );

  // ── Setup ─────────────────────────────────────────────────────────────────
  if (g.phase === 'setup') {
    const cleanName = v => v.toUpperCase().replace(/[^A-Z0-9 ]/g, '').slice(0, 8).trimStart();
    const canStart = teamInputs.filter(n => n.trim()).length >= 2;
    return (
      <div className="screen fade-in" style={{ paddingTop: 10 }}>
        <Marquee title="Play Now" subtitle="Pass & Play · No Wi-Fi Needed" mini />

        <div style={panelStyle}>
          <div className="eyebrow" style={{ marginBottom: 12 }}>★ Teams</div>
          {teamInputs.map((n, i) => (
            <div key={i} style={{ display: 'flex', gap: 8, marginBottom: 8, alignItems: 'center' }}>
              <input
                className="tag-input"
                value={n}
                placeholder={`TEAM ${i + 1}`}
                maxLength={8}
                inputMode="text"
                autoCapitalize="words"
                spellCheck={false}
                style={{ flex: 1, letterSpacing: 2, fontSize: 14 }}
                onChange={e => {
                  const next = [...teamInputs];
                  next[i] = cleanName(e.target.value);
                  setTeamInputs(next);
                }}
                onKeyDown={e => e.key === 'Enter' && canStart && startGame()}
              />
              {teamInputs.length > 2 && (
                <button
                  onClick={() => setTeamInputs(teamInputs.filter((_, j) => j !== i))}
                  style={{ appearance: 'none', background: 'rgba(255,79,94,0.15)', border: '1px solid rgba(255,79,94,0.3)', color: 'var(--bad)', borderRadius: 8, padding: '10px 12px', cursor: 'pointer', fontSize: 13 }}
                >✕</button>
              )}
            </div>
          ))}
          {teamInputs.length < 4 && (
            <button
              onClick={() => setTeamInputs([...teamInputs, ''])}
              style={{ appearance: 'none', width: '100%', padding: '10px', background: 'transparent', border: '1px dashed rgba(255,255,255,0.18)', color: 'var(--fg-dim)', borderRadius: 8, cursor: 'pointer', fontFamily: 'var(--font-ui)', fontSize: 13, marginTop: 2 }}
            >+ Add Team</button>
          )}
        </div>

        <div style={panelStyle}>
          <div className="eyebrow" style={{ marginBottom: 10 }}>▣ Rounds</div>
          <div style={{ display: 'flex', gap: 8 }}>
            {[1, 2, 3].map(r => (
              <button
                key={r}
                onClick={() => setRoundsPick(r)}
                style={{
                  appearance: 'none', flex: 1, padding: '16px 0', borderRadius: 12, cursor: 'pointer',
                  border: r === roundsPick ? '1px solid rgba(255,94,58,0.55)' : '1px solid rgba(255,255,255,0.1)',
                  background: r === roundsPick ? 'rgba(255,94,58,0.18)' : 'rgba(255,255,255,0.04)',
                  color: r === roundsPick ? 'var(--accent)' : 'var(--fg-dim)',
                  fontFamily: 'var(--font-arcade)', fontSize: 18,
                }}
              >{r}</button>
            ))}
          </div>
        </div>

        <div className="spacer" />
        <button className="btn go" disabled={!canStart} onClick={startGame}>▶ Start Game</button>
        <button className="btn ghost" onClick={onExit}>← Back</button>
      </div>
    );
  }

  // ── Handoff screen ────────────────────────────────────────────────────────
  if (g.phase === 'handoff') {
    const team = g.teams[g.activeTeamIndex];
    return (
      <div className="screen fade-in" style={{ alignItems: 'center', justifyContent: 'center', textAlign: 'center', gap: 16 }}>
        <div style={{ fontSize: 64 }}>🎮</div>
        <div className="eyebrow">— Pass the Phone —</div>
        <div style={{ fontFamily: 'var(--font-arcade)', fontSize: 22, color: 'var(--accent)', letterSpacing: 2, marginTop: 4 }}>
          {team.name}
        </div>
        <div style={{ color: 'var(--fg-dim)', fontSize: 13 }}>
          Round {g.round} of {g.rounds} · Don't show your team
        </div>
        <div className="spacer" />
        <button className="btn" style={{ width: '100%' }} onClick={() => { window.sfx && window.sfx.pick(); setG(prev => ({ ...prev, phase: 'pick' })); }}>
          Ready →
        </button>
        <button className="btn ghost" style={{ width: '100%' }} onClick={() => setShowExit(true)}>Exit</button>
        {exitModal}
      </div>
    );
  }

  // ── In-game screens ───────────────────────────────────────────────────────
  const activeTeam = g.teams[g.activeTeamIndex];

  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
      {g.phase !== 'end' && (
        <HUD
          teams={g.teams}
          activeIdx={g.activeTeamIndex}
          round={g.round}
          totalRounds={g.rounds}
          onExit={() => setShowExit(true)}
          onPlayerClick={null}
          lockActive={true}
        />
      )}

      <div style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
        {g.phase === 'pick' && (
          <PickScreen
            slots={g.currentSlots}
            teamName={activeTeam.name}
            metaphor={metaphor}
            onDone={handlePicked}
          />
        )}

        {g.phase === 'order' && (
          <OrderScreen
            cards={g.chosenCards}
            teamName={activeTeam.name}
            metaphor={metaphor}
            onReady={handleOrdered}
          />
        )}

        {g.phase === 'play' && (
          <PlayScreen
            cards={g.orderedCards}
            teamName={activeTeam.name}
            metaphor={metaphor}
            timeLeft={g.timeLeft}
            cardStates={g.cardStates}
            activeCardIndex={g.activeCardIndex}
            bufferTimeLeft={g.bufferTimeLeft}
            onGuessed={handleGuessed}
            onEndTurn={handleEndTurn}
          />
        )}

        {g.phase === 'result' && (
          <ResultScreen
            cards={g.orderedCards}
            guessed={g.cardStates.map(s => s.status === 'guessed')}
            teams={g.teams}
            teamIndex={g.activeTeamIndex}
            metaphor={metaphor}
            onNext={handleNext}
            isLast={isLastTurn()}
          />
        )}

        {g.phase === 'end' && (
          <EndScreen
            teams={g.teams}
            onRestart={handleRestart}
            onAddRound={g.teams.length >= 2 ? () => {
              setG(prev => ({
                ...prev,
                rounds: prev.rounds + 1,
                round: prev.rounds + 1,
                activeTeamIndex: 0,
                phase: 'handoff',
                currentSlots: window.dealSlots(),
                chosenCards: null, orderedCards: null, cardStates: null, activeCardIndex: 0,
              }));
            } : null}
          />
        )}
      </div>

      {exitModal}
    </div>
  );
}

const panelStyle = {
  background: 'rgba(255, 255, 255, 0.04)',
  border: '1px solid rgba(255, 255, 255, 0.07)',
  borderRadius: 'var(--r-lg)',
  padding: '16px 16px 18px',
};

window.LocalGame = LocalGame;
