/* ── Minesweeper ─────────────────────────────────────────────────────────── */
function Minesweeper({ balance, apiFetch, onBack, onBalanceChange }) {
  const { useState, useRef } = React;

  const GRID = 25; // 5 × 5

  const [phase,      setPhase]      = useState('idle');   // idle | playing | done
  const [gameId,     setGameId]     = useState(null);
  const [mineCount,  setMineCount]  = useState(3);
  const [bet,        setBet]        = useState(100);
  const [tiles,      setTiles]      = useState(Array(GRID).fill('hidden'));
  const [mult,       setMult]       = useState(1);
  const [safeCount,  setSafeCount]  = useState(0);
  const [result,     setResult]     = useState(null);
  const [busy,       setBusy]       = useState(false);
  const [history,    setHistory]    = useState([]);
  const [err,        setErr]        = useState('');

  const activeBet = useRef(100); // locked-in bet for current game

  // ── Helpers ────────────────────────────────────────────────────────────────
  // Mirrors server minesMult exactly: 0.88 * product of odds for each reveal
  function minesMult(mines, k) {
    if (k > GRID - mines) return null;
    let v = 0.88;
    for (let i = 0; i < k; i++) v *= (GRID - i) / (GRID - mines - i);
    return v;
  }

  function nextMult(safe, mines) {
    return minesMult(mines, safe + 1);
  }

  function resetBoard() {
    setPhase('idle');
    setGameId(null);
    setTiles(Array(GRID).fill('hidden'));
    setMult(1);
    setSafeCount(0);
    setResult(null);
    setErr('');
  }

  // ── Actions ────────────────────────────────────────────────────────────────
  async function startGame() {
    setErr('');
    const amt = parseInt(bet);
    if (!amt || amt <= 0)                         { setErr('Enter a valid bet'); return; }
    if (mineCount < 1 || mineCount > 24)          { setErr('Mines must be 1–24'); return; }
    if (25 - mineCount < 1)                       { setErr('Need at least 1 safe tile'); return; }

    setBusy(true);
    let data;
    try {
      data = await apiFetch('/api/game/minesweeper/start', { amount: amt, mines: mineCount });
    } catch (e) { setBusy(false); setErr(e.message); return; }

    activeBet.current = amt;
    onBalanceChange(data.balance);
    setGameId(data.gameId);
    setTiles(Array(GRID).fill('hidden'));
    setMult(1);
    setSafeCount(0);
    setResult(null);
    setPhase('playing');
    setBusy(false);
  }

  async function revealTile(idx) {
    if (phase !== 'playing' || tiles[idx] !== 'hidden' || busy) return;
    setBusy(true);

    let data;
    try {
      data = await apiFetch('/api/game/minesweeper/reveal', { gameId, tile: idx });
    } catch (e) { setBusy(false); setErr(e.message); return; }

    if (data.hit) {
      setTiles(prev => {
        const next = [...prev];
        next[idx] = 'mine-hit';
        data.mines.forEach(m => { if (m !== idx && next[m] === 'hidden') next[m] = 'mine'; });
        return next;
      });
      setResult({ won: false, net: -activeBet.current });
      setPhase('done');
      window.SoundFX?.bust();
      setHistory(h => [{ mines: mineCount, safe: safeCount, mult, net: -activeBet.current, won: false }, ...h.slice(0, 19)]);
    } else {
      setTiles(prev => { const next = [...prev]; next[idx] = 'safe'; return next; });
      setMult(data.mult);
      setSafeCount(data.safe);
      window.SoundFX?.chip();

      if (data.autoComplete) {
        setTiles(prev => {
          const next = [...prev];
          data.mines.forEach(m => { if (next[m] === 'hidden') next[m] = 'mine-cleared'; });
          return next;
        });
        setResult({ won: true, winAmount: data.winAmount, net: data.net, mult: data.mult });
        setPhase('done');
        onBalanceChange(data.balance);
        window.SoundFX?.win();
        setHistory(h => [{ mines: mineCount, safe: data.safe, mult: data.mult, net: data.net, won: true }, ...h.slice(0, 19)]);
      }
    }

    setBusy(false);
  }

  async function cashOut() {
    if (phase !== 'playing' || safeCount === 0 || busy) return;
    setBusy(true);

    let data;
    try {
      data = await apiFetch('/api/game/minesweeper/cashout', { gameId });
    } catch (e) { setBusy(false); setErr(e.message); return; }

    setTiles(prev => {
      const next = [...prev];
      data.mines.forEach(m => { if (next[m] === 'hidden') next[m] = 'mine-cleared'; });
      return next;
    });
    setMult(data.mult);
    setResult({ won: true, winAmount: data.winAmount, net: data.net, mult: data.mult });
    setPhase('done');
    onBalanceChange(data.balance);
    window.SoundFX?.win();
    setHistory(h => [{ mines: mineCount, safe: safeCount, mult: data.mult, net: data.net, won: true }, ...h.slice(0, 19)]);
    setBusy(false);
  }

  // ── Tile appearance ────────────────────────────────────────────────────────
  function tileProps(state, idx) {
    const clickable = phase === 'playing' && state === 'hidden' && !busy;
    const base = {
      width: 66, height: 66, borderRadius: 6,
      border: '1px solid', cursor: clickable ? 'pointer' : 'default',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      transition: 'background 0.14s, border-color 0.14s, box-shadow 0.14s',
      fontFamily: 'JetBrains Mono, monospace',
      fontSize: 22, fontWeight: 500,
    };
    switch (state) {
      case 'safe':
        return { style: { ...base, background: 'rgba(30,160,70,0.16)', borderColor: 'rgba(46,200,80,0.45)', color: 'var(--emerald)', boxShadow: '0 0 8px rgba(30,190,60,0.18)' }, label: '◆' };
      case 'mine':
        return { style: { ...base, background: 'rgba(160,30,30,0.12)', borderColor: 'rgba(190,50,50,0.3)', color: 'rgba(200,60,60,0.6)', fontSize: 18 }, label: '✦' };
      case 'mine-hit':
        return { style: { ...base, background: 'rgba(220,30,30,0.28)', borderColor: 'var(--garnet)', color: 'var(--garnet)', boxShadow: '0 0 14px rgba(220,30,30,0.45)', fontSize: 18 }, label: '✦' };
      case 'mine-cleared':
        return { style: { ...base, background: 'rgba(140,30,30,0.08)', borderColor: 'rgba(180,50,50,0.2)', color: 'rgba(180,50,50,0.4)', fontSize: 18 }, label: '✦' };
      default: // hidden
        return { style: { ...base, background: 'var(--bg-card)', borderColor: 'var(--line)', color: 'transparent' }, label: '·', clickable };
    }
  }

  // ── Derived display values ─────────────────────────────────────────────────
  const previewNext = phase === 'playing' ? nextMult(safeCount, mineCount) : null;
  const potentialPayout = Math.floor(activeBet.current * mult);

  // ── Render ────────────────────────────────────────────────────────────────
  return (
    <div className="game-panel" data-game-view="minesweeper">
      <div className="game-panel-header">
        <button className="btn-back" onClick={phase === 'playing' ? null : onBack}
          style={{ opacity: phase === 'playing' ? 0.35 : 1, cursor: phase === 'playing' ? 'default' : 'pointer' }}>
          Lobby
        </button>
        <div>
          <h1 className="game-panel-title">Minesweeper</h1>
          <div className="game-panel-subtitle">·❦· The Minefield ·❦·</div>
        </div>
        <div className="game-panel-meta">
          <span>{mineCount} Mine{mineCount !== 1 ? 's' : ''}</span>
        </div>
      </div>

      <div className="game-table">
        <FiligreeCorners />

        {/* Stat row */}
        <div style={{ display: 'flex', justifyContent: 'center', gap: 36, marginBottom: 20, flexWrap: 'wrap' }}>
          <div style={{ textAlign: 'center' }}>
            <div style={{ fontSize: 9, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'var(--muted)', marginBottom: 4 }}>Multiplier</div>
            <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 26, color: 'var(--gold)', fontWeight: 500 }}>
              {mult.toFixed(2)}×
            </div>
          </div>
          {previewNext && (
            <div style={{ textAlign: 'center' }}>
              <div style={{ fontSize: 9, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'var(--muted)', marginBottom: 4 }}>Next Safe</div>
              <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 26, color: 'var(--emerald)', fontWeight: 500 }}>
                {previewNext.toFixed(2)}×
              </div>
            </div>
          )}
          {phase === 'playing' && safeCount > 0 && (
            <div style={{ textAlign: 'center' }}>
              <div style={{ fontSize: 9, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'var(--muted)', marginBottom: 4 }}>Payout</div>
              <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 26, color: 'var(--gold-soft)', fontWeight: 500 }}>
                {potentialPayout.toLocaleString()} G
              </div>
            </div>
          )}
        </div>

        {/* 5 × 5 grid */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 66px)', gap: 8, justifyContent: 'center' }}>
          {Array.from({ length: GRID }, (_, i) => {
            const { style, label, clickable } = tileProps(tiles[i], i);
            return (
              <button
                key={i}
                style={style}
                onClick={() => revealTile(i)}
                disabled={!clickable}
                onMouseEnter={e => {
                  if (clickable) {
                    e.currentTarget.style.borderColor = 'var(--gold-soft)';
                    e.currentTarget.style.boxShadow = '0 0 10px rgba(212,169,96,0.22)';
                    e.currentTarget.style.background = 'rgba(212,169,96,0.07)';
                  }
                }}
                onMouseLeave={e => {
                  if (tiles[i] === 'hidden') {
                    e.currentTarget.style.borderColor = 'var(--line)';
                    e.currentTarget.style.boxShadow = 'none';
                    e.currentTarget.style.background = 'var(--bg-card)';
                  }
                }}
              >
                {label}
              </button>
            );
          })}
        </div>

        {/* Result banner */}
        {result && (
          <div className={`game-status ${result.won ? 'win' : 'loss'}`} style={{ marginTop: 18, textAlign: 'center' }}>
            {result.won
              ? `Cashed out ${result.mult.toFixed(2)}× — +${result.winAmount.toLocaleString()} G`
              : 'Mine detonated. Bet lost.'}
          </div>
        )}
      </div>

      {/* Mine count selector — idle only */}
      {phase === 'idle' && (
        <div style={{ marginTop: 16, marginBottom: 4 }}>
          <div className="section-header" style={{ marginBottom: 10 }}>
            <span className="section-title">Mines</span>
            <div className="section-line" />
            <span style={{ fontSize: 10, color: 'var(--muted)', letterSpacing: '0.12em', whiteSpace: 'nowrap' }}>
              {(25 - mineCount)} safe tiles
            </span>
          </div>
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
            {[1, 3, 5, 10, 15, 20, 24].map(n => (
              <button
                key={n}
                className={`btn${mineCount === n ? ' btn-primary' : ''}`}
                onClick={() => { window.SoundFX?.chip(); setMineCount(n); }}
                style={{ fontSize: 11, padding: '6px 12px' }}
              >
                {n}
              </button>
            ))}
            <input
              className="form-input"
              type="number" min={1} max={24}
              value={mineCount}
              onChange={e => setMineCount(Math.max(1, Math.min(24, parseInt(e.target.value) || 1)))}
              style={{ width: 64 }}
            />
          </div>
        </div>
      )}

      {/* Bet controls — idle only */}
      {phase === 'idle' && (
        <div className="bet-controls">
          <span className="bet-label">Bet</span>
          <input className="bet-input" type="number" min={1} max={1000}
            value={bet} onChange={e => setBet(e.target.value)} />
          <div className="bet-presets">
            {[100, 250, 500, 1000].map(n => (
              <button key={n} className="btn-preset" onClick={() => { window.SoundFX?.chip(); setBet(n); }}>
                {n >= 1000 ? `${n / 1000}k` : n}
              </button>
            ))}
          </div>
          <div className="bet-increments">
            {[10, 25, 100].map(n => (
              <button key={n} className="btn-increment"
                onClick={() => { window.SoundFX?.chip(); setBet(Math.min(1000, (parseInt(bet)||0) + n)); }}>
                +{n}
              </button>
            ))}
          </div>
          <div className="action-buttons">
            <button className="btn btn-primary btn-lg" onClick={startGame} disabled={busy}>
              {busy ? 'Starting…' : 'Place Bet'}
            </button>
          </div>
        </div>
      )}

      {/* Cash out — playing */}
      {phase === 'playing' && (
        <div className="bet-controls">
          <div className="action-buttons" style={{ width: '100%', justifyContent: 'center', gap: 12 }}>
            <button
              className="btn btn-primary btn-lg"
              onClick={cashOut}
              disabled={safeCount === 0 || busy}
              style={{ minWidth: 220, opacity: safeCount === 0 ? 0.45 : 1 }}
            >
              {safeCount === 0
                ? 'Reveal a tile to start'
                : `Cash Out — ${potentialPayout.toLocaleString()} G`}
            </button>
          </div>
        </div>
      )}

      {/* New game — done */}
      {phase === 'done' && (
        <div className="bet-controls">
          <div className="action-buttons" style={{ width: '100%', justifyContent: 'center', gap: 10 }}>
            <button className="btn btn-primary btn-lg" onClick={startGame} disabled={busy}>
              Play Again
            </button>
            <button className="btn btn-lg" onClick={resetBoard}>
              Change Settings
            </button>
          </div>
        </div>
      )}

      {err && <p style={{ color: 'var(--garnet)', fontSize: 12, marginTop: 10 }}>{err}</p>}

      {history.length > 0 && (
        <div style={{ marginTop: 20 }}>
          <div className="section-header">
            <span className="section-title">Recent Games</span>
            <div className="section-line" />
          </div>
          <div className="history-feed">
            {history.map((h, i) => (
              <div key={i} className="history-item">
                <span className="history-game">Mines</span>
                <span className="history-bet">{h.mines}✦ · {h.safe} safe · {h.mult.toFixed(2)}×</span>
                <span className={`history-result ${h.net > 0 ? 'pos' : h.net < 0 ? 'neg' : 'zero'}`}>
                  {h.net > 0 ? '+' : ''}{h.net.toLocaleString()} G
                </span>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}
