/* ── Roulette ────────────────────────────────────────────────────────────── */
const RED_NUMBERS = new Set([1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36]);

function numColor(n) {
  if (n === 0 || n === '00') return 'green-n';
  return RED_NUMBERS.has(n) ? 'red-n' : 'black-n';
}

const ROULETTE_GRID = Array.from({ length: 12 }, (_, col) => [
  col * 3 + 3,
  col * 3 + 2,
  col * 3 + 1,
]);

const OUTSIDE_BETS = [
  { id: 'red',   label: 'Red',   mult: 1, check: n => n !== 0 && n !== '00' && RED_NUMBERS.has(n) },
  { id: 'black', label: 'Black', mult: 1, check: n => n !== 0 && n !== '00' && !RED_NUMBERS.has(n) },
  { id: 'odd',   label: 'Odd',   mult: 1, check: n => typeof n === 'number' && n > 0 && n % 2 !== 0 },
  { id: 'even',  label: 'Even',  mult: 1, check: n => typeof n === 'number' && n > 0 && n % 2 === 0 },
  { id: 'low',   label: '1–18',  mult: 1, check: n => typeof n === 'number' && n >= 1  && n <= 18 },
  { id: 'high',  label: '19–36', mult: 1, check: n => typeof n === 'number' && n >= 19 && n <= 36 },
  { id: 'd1',    label: '1–12',  mult: 2, check: n => typeof n === 'number' && n >= 1  && n <= 12 },
  { id: 'd2',    label: '13–24', mult: 2, check: n => typeof n === 'number' && n >= 13 && n <= 24 },
  { id: 'd3',    label: '25–36', mult: 2, check: n => typeof n === 'number' && n >= 25 && n <= 36 },
];

const WHEEL = [0, '00', ...Array.from({ length: 36 }, (_, i) => i + 1)];

// American roulette wheel order — clockwise starting from 0 at top
const WHEEL_ORDER = [0,28,9,26,30,11,7,20,32,17,5,22,34,15,3,24,36,13,1,'00',27,10,25,29,12,8,19,31,18,6,21,33,16,4,23,35,14,2];
const SLICE = (2 * Math.PI) / WHEEL_ORDER.length;

function drawRouletteWheel(canvas, ballAngle, highlightIdx, ballDone) {
  const ctx = canvas.getContext('2d');
  const W = canvas.width, H = canvas.height;
  const cx = W / 2, cy = H / 2;
  const outerR = Math.min(W, H) / 2 - 4;
  const rimR   = outerR * 0.93;
  const trackR = outerR * 0.86;
  const numOR  = outerR * 0.84;
  const numIR  = outerR * 0.64;
  const innerR = outerR * 0.38;

  ctx.clearRect(0, 0, W, H);

  // Outer rim
  ctx.beginPath();
  ctx.arc(cx, cy, outerR, 0, 2 * Math.PI);
  ctx.fillStyle = '#0c0904';
  ctx.fill();
  ctx.strokeStyle = 'rgba(212,169,96,0.55)';
  ctx.lineWidth = 2;
  ctx.stroke();

  // Segments
  const N = WHEEL_ORDER.length;
  for (let i = 0; i < N; i++) {
    const startA = -Math.PI / 2 + i * SLICE;
    const endA   = startA + SLICE;
    const num    = WHEEL_ORDER[i];
    const lit    = ballDone && i === highlightIdx;

    let fill;
    if (lit) {
      fill = 'rgba(212,169,96,0.94)';
    } else if (num === 0 || num === '00') {
      fill = 'rgba(27,120,60,0.88)';
    } else if (RED_NUMBERS.has(num)) {
      fill = 'rgba(192,57,43,0.85)';
    } else {
      fill = 'rgba(16,22,40,0.96)';
    }

    ctx.beginPath();
    ctx.moveTo(cx, cy);
    ctx.arc(cx, cy, rimR, startA, endA);
    ctx.closePath();
    ctx.fillStyle = fill;
    ctx.fill();
    ctx.strokeStyle = 'rgba(212,169,96,0.18)';
    ctx.lineWidth = 0.8;
    ctx.stroke();

    // Number label
    const midA   = startA + SLICE / 2;
    const labelR = (numOR + numIR) / 2;
    const lx = cx + Math.cos(midA) * labelR;
    const ly = cy + Math.sin(midA) * labelR;
    ctx.save();
    ctx.translate(lx, ly);
    ctx.rotate(midA + Math.PI / 2);
    ctx.font = `bold ${Math.max(7, Math.floor(outerR * 0.052))}px Inter, sans-serif`;
    ctx.fillStyle = lit ? '#0d1322' : 'rgba(241,228,200,0.88)';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(String(num), 0, 0);
    ctx.restore();
  }

  // Inner separator ring
  ctx.beginPath();
  ctx.arc(cx, cy, numIR, 0, 2 * Math.PI);
  ctx.fillStyle = '#0d1322';
  ctx.strokeStyle = 'rgba(212,169,96,0.38)';
  ctx.lineWidth = 1.5;
  ctx.fill();
  ctx.stroke();

  // Center cap
  ctx.beginPath();
  ctx.arc(cx, cy, innerR, 0, 2 * Math.PI);
  ctx.fillStyle = '#141c30';
  ctx.strokeStyle = 'rgba(212,169,96,0.22)';
  ctx.lineWidth = 1;
  ctx.fill();
  ctx.stroke();

  // Center text
  ctx.font = `italic ${Math.floor(innerR * 0.30)}px 'Cormorant Garamond', serif`;
  ctx.fillStyle = 'rgba(212,169,96,0.42)';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.fillText('ArcheBet', cx, cy);

  // Pointer — gold diamond at 12 o'clock
  const ptY = cy - outerR + 2;
  ctx.beginPath();
  ctx.moveTo(cx,     ptY + 2);
  ctx.lineTo(cx - 7, ptY + 12);
  ctx.lineTo(cx,     ptY + 22);
  ctx.lineTo(cx + 7, ptY + 12);
  ctx.closePath();
  ctx.fillStyle = 'rgba(212,169,96,0.95)';
  ctx.shadowColor = 'rgba(212,169,96,0.7)';
  ctx.shadowBlur  = 8;
  ctx.fill();
  ctx.shadowBlur  = 0;

  // Ball
  if (ballAngle !== null) {
    const ballR  = ballDone ? (numOR + numIR) / 2 : trackR;
    const bx     = cx + Math.cos(ballAngle) * ballR;
    const by     = cy + Math.sin(ballAngle) * ballR;
    const br     = Math.max(5, outerR * 0.047);

    const grad = ctx.createRadialGradient(bx - br * 0.3, by - br * 0.3, br * 0.05, bx, by, br);
    grad.addColorStop(0, '#ffffff');
    grad.addColorStop(0.5, '#f0e8d8');
    grad.addColorStop(1, '#c8b898');

    ctx.beginPath();
    ctx.arc(bx, by, br, 0, 2 * Math.PI);
    ctx.fillStyle = grad;
    ctx.shadowColor = 'rgba(255,255,255,0.55)';
    ctx.shadowBlur  = 10;
    ctx.fill();
    ctx.shadowBlur  = 0;
  }
}

function Roulette({ balance, apiFetch, onBack, onBalanceChange }) {
  const { useState, useRef, useEffect } = React;

  const [selectedBet, setSelectedBet] = useState(null);
  const [betAmount, setBetAmount] = useState(100);
  const [phase, setPhase] = useState('idle');
  const [result, setResult] = useState(null);
  const [history, setHistory] = useState([]);
  const [err, setErr] = useState('');

  const canvasRef = useRef(null);
  const animRef   = useRef(null);

  useEffect(() => {
    if (canvasRef.current) drawRouletteWheel(canvasRef.current, null, -1, false);
    return () => { if (animRef.current) cancelAnimationFrame(animRef.current); };
  }, []);

  function selectNumber(n) { window.SoundFX?.chip(); setSelectedBet({ type: 'number', value: n, mult: 35 }); }
  function selectOutside(bet) { window.SoundFX?.chip(); setSelectedBet({ type: 'outside', ...bet }); }

  async function spin() {
    setErr('');
    if (!selectedBet) { setErr('Select a bet first'); return; }
    const amt = parseInt(betAmount);
    if (!amt || amt <= 0) { setErr('Enter a valid bet'); return; }
    if (amt > balance)   { setErr('Insufficient balance'); return; }

    setPhase('spinning');
    setResult(null);

    // Fetch result from server before starting animation
    const betType  = selectedBet.type === 'number' ? 'number' : selectedBet.id;
    const betValue = selectedBet.type === 'number' ? selectedBet.value : undefined;

    let data;
    try {
      data = await apiFetch('/api/game/roulette/play', { amount: amt, betType, betValue });
    } catch (e) { setPhase('idle'); setErr(e.message); return; }

    const { landed } = data;
    const landIdx = WHEEL_ORDER.indexOf(landed);
    const targetA = -Math.PI / 2 + (landIdx + 0.5) * SLICE;

    const startA  = Math.random() * 2 * Math.PI;
    const delta   = ((targetA - startA) % (2 * Math.PI) + 2 * Math.PI) % (2 * Math.PI);
    const totalA  = 7 * 2 * Math.PI + delta;
    const duration = 4800;

    if (canvasRef.current) drawRouletteWheel(canvasRef.current, startA, -1, false);

    const tileOf = a => Math.floor(((a + Math.PI / 2) % (2 * Math.PI) + 2 * Math.PI) % (2 * Math.PI) / SLICE) % WHEEL_ORDER.length;
    let prevTile = tileOf(startA);

    await new Promise(resolve => {
      const t0 = performance.now();
      function frame(now) {
        const raw   = Math.min((now - t0) / duration, 1);
        const eased = 1 - Math.pow(1 - raw, 5);
        const angle = startA + totalA * eased;
        const done  = raw >= 1;
        if (canvasRef.current) drawRouletteWheel(canvasRef.current, angle, done ? landIdx : -1, done);
        const tile = tileOf(angle);
        if (tile !== prevTile) { window.SoundFX?.tick(); prevTile = tile; }
        if (!done) { animRef.current = requestAnimationFrame(frame); } else { resolve(); }
      }
      animRef.current = requestAnimationFrame(frame);
    });

    setResult({ landed, color: numColor(landed), won: data.won, winAmount: data.winAmount, net: data.net });
    setPhase('done');
    onBalanceChange(data.balance);
    if (data.won) window.SoundFX?.win(); else window.SoundFX?.bust();
    setHistory(h => [{ landed, won: data.won, bet: amt, net: data.net }, ...h.slice(0, 19)]);
  }

  const betLabel = selectedBet
    ? selectedBet.type === 'number'
      ? `Number ${selectedBet.value} (35:1)`
      : `${selectedBet.label} (${selectedBet.mult}:1)`
    : 'No bet selected';

  return (
    <div className="game-panel" data-game-view="roulette">
      <div className="game-panel-header">
        <button className="btn-back" onClick={onBack}>Lobby</button>
        <div>
          <h1 className="game-panel-title">Roulette</h1>
          <div className="game-panel-subtitle">·❦· The Wheel of Fates ·❦·</div>
        </div>
        <div className="game-panel-meta"><span>Up to 35 : 1</span></div>
      </div>

      <div className="game-table">
        <FiligreeCorners />
        {/* Wheel canvas */}
        <div className="roulette-wheel-wrap">
          <canvas ref={canvasRef} width={300} height={300} className="roulette-canvas" />
          {result && phase === 'done' && (
            <div className="roulette-wheel-result">
              <span className={`r-cell ${result.color}`} style={{ width: 44, height: 36, fontSize: 14, display: 'inline-flex' }}>
                {result.landed}
              </span>
              <div className={`game-status ${result.won ? 'win' : 'loss'}`} style={{ fontSize: 13, marginTop: 0 }}>
                {result.won ? `You Win! +${result.winAmount.toLocaleString()} G` : 'No Win'}
              </div>
            </div>
          )}
        </div>

        <div className="section-header" style={{ marginBottom: 10 }}>
          <span className="section-title">Betting Board</span>
          <div className="section-line" />
          <span style={{ fontSize: 10, color: 'var(--gold)', letterSpacing: '0.1em' }}>{betLabel}</span>
        </div>

        <div className="roulette-layout">
          <div className="roulette-zeros">
            {[0, '00'].map(n => (
              <div
                key={n}
                className={`r-cell green-n${selectedBet?.type === 'number' && selectedBet.value === n ? ' selected' : ''}`}
                style={{ width: 60, fontSize: 13, letterSpacing: '0.05em', flexDirection: 'column', gap: 1 }}
                onClick={() => selectNumber(n)}
              >
                <span>{n}</span>
                <span style={{ fontSize: 7, fontFamily: 'JetBrains Mono, monospace', opacity: 0.65, letterSpacing: '0.06em' }}>35:1</span>
              </div>
            ))}
          </div>

          {[0, 1, 2].map(row => (
            <div key={row} className="roulette-number-grid">
              {ROULETTE_GRID.map((col, ci) => {
                const n = col[row];
                const color = numColor(n);
                const isSel = selectedBet?.type === 'number' && selectedBet.value === n;
                return (
                  <div
                    key={ci}
                    className={`r-cell ${color}${isSel ? ' selected' : ''}`}
                    onClick={() => selectNumber(n)}
                  >{n}</div>
                );
              })}
            </div>
          ))}

          {/* Color bets — Red and Black with full suit treatment */}
          <div className="obet-colors">
            {[
              { id: 'red',   suits: '♥ ♦', label: 'Red'   },
              { id: 'black', suits: '♠ ♣', label: 'Black' },
            ].map(({ id, suits, label }) => {
              const b = OUTSIDE_BETS.find(x => x.id === id);
              return (
                <button
                  key={id}
                  className={`outside-btn obet-${id}${selectedBet?.id === id ? ' selected' : ''}`}
                  onClick={() => selectOutside(b)}
                >
                  <span className="obet-suits">{suits}</span>
                  <span className="obet-main">{label}</span>
                  <span className="obet-odds">1:1</span>
                </button>
              );
            })}
          </div>

          {/* Even-money bets */}
          <div className="obet-evens">
            {[
              { id: 'low',  main: 'Low',   sub: '1–18'   },
              { id: 'odd',  main: 'Odd',   sub: '1·3·5…' },
              { id: 'even', main: 'Even',  sub: '2·4·6…' },
              { id: 'high', main: 'High',  sub: '19–36'  },
            ].map(({ id, main, sub }) => {
              const b = OUTSIDE_BETS.find(x => x.id === id);
              return (
                <button
                  key={id}
                  className={`outside-btn${selectedBet?.id === id ? ' selected' : ''}`}
                  onClick={() => selectOutside(b)}
                >
                  <span className="obet-main">{main}</span>
                  <span className="obet-sub">{sub}</span>
                  <span className="obet-odds">1:1</span>
                </button>
              );
            })}
          </div>

          {/* Dozen bets — with mini red/black number strip */}
          <div className="obet-dozens">
            {[
              { id: 'd1', main: '1st 12',  nums: [1,2,3,4,5,6,7,8,9,10,11,12]    },
              { id: 'd2', main: '2nd 12',  nums: [13,14,15,16,17,18,19,20,21,22,23,24] },
              { id: 'd3', main: '3rd 12',  nums: [25,26,27,28,29,30,31,32,33,34,35,36] },
            ].map(({ id, main, nums }) => {
              const b = OUTSIDE_BETS.find(x => x.id === id);
              return (
                <button
                  key={id}
                  className={`outside-btn obet-dozen${selectedBet?.id === id ? ' selected' : ''}`}
                  onClick={() => selectOutside(b)}
                >
                  <span className="obet-main">{main}</span>
                  <div className="obet-strip">
                    {nums.map(n => (
                      <span key={n} className={`obet-dot ${RED_NUMBERS.has(n) ? 'red-n' : 'black-n'}`} />
                    ))}
                  </div>
                  <span className="obet-odds">2:1</span>
                </button>
              );
            })}
          </div>
        </div>
      </div>

      <div className="bet-controls">
        <span className="bet-label">Bet</span>
        <input
          className="bet-input"
          type="number"
          min={1}
          max={1000}
          value={betAmount}
          onChange={e => setBetAmount(e.target.value)}
          disabled={phase === 'spinning'}
        />
        <div className="bet-presets">
          {[100, 250, 500, 1000].map(n => (
            <button key={n} className="btn-preset" onClick={() => { window.SoundFX?.chip(); setBetAmount(n); }} disabled={phase === 'spinning'}>
              {n >= 1000 ? `${n/1000}k` : n}
            </button>
          ))}
        </div>
        <div className="bet-increments">
          {[10, 25, 100].map(n => (
            <button key={n} className="btn-increment" disabled={phase === 'spinning'}
              onClick={() => { window.SoundFX?.chip(); setBetAmount(Math.min(1000, (parseInt(betAmount)||0) + n)); }}>
              +{n}
            </button>
          ))}
        </div>
        <div className="action-buttons">
          <button className="btn btn-primary btn-lg" onClick={() => { window.SoundFX?.chip(); spin(); }} disabled={phase === 'spinning'}>
            {phase === 'spinning' ? 'Spinning…' : 'Spin'}
          </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 Spins</span>
            <div className="section-line" />
          </div>
          <div className="history-feed">
            {history.map((h, i) => (
              <div key={i} className="history-item">
                <span className="history-game">Roulette</span>
                <span className="history-bet">
                  <span className={`r-cell ${numColor(h.landed)}`} style={{ width: 28, height: 22, display: 'inline-flex', fontSize: 10, borderRadius: 3 }}>{h.landed}</span>
                </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>
  );
}
