/* ── Group Blackjack ─────────────────────────────────────────────────────── */

function _bjHandVal(hand) {
  let v = 0, aces = 0;
  for (const c of hand) {
    if (c.hidden) continue;
    if (c.rank === 'A') { v += 11; aces++; }
    else if (['J','Q','K'].includes(c.rank)) v += 10;
    else v += parseInt(c.rank);
  }
  while (v > 21 && aces > 0) { v -= 10; aces--; }
  return v;
}

function GroupBJ({ balance, token, onBack, onBalanceChange }) {
  const { useState, useEffect, useRef, useCallback } = React;
  const username = jwtUsername(token);

  const [phase,        setPhase]        = useState('lobby');
  const [tables,       setTables]       = useState([]);
  const [table,        setTable]        = useState(null);
  const [err,          setErr]          = useState('');
  const [tname,        setTname]        = useState('');
  const [tpassword,    setTpassword]    = useState('');
  const [minBet,       setMinBet]       = useState(100);
  const [maxBet,       setMaxBet]       = useState(1000);
  const [joiningTable, setJoiningTable] = useState(null);
  const [joinPassword, setJoinPassword] = useState('');
  const [chatMessages,      setChatMessages]      = useState([]);  // lobby chat
  const [tableChatMessages, setTableChatMessages] = useState([]);  // table chat

  const [hostNotif, setHostNotif] = useState('');

  const socketRef      = useRef(null);
  const isSpectatingRef = useRef(false);
  const prevHostRef     = useRef(null);
  const hostNotifTimer  = useRef(null);

  useEffect(() => {
    if (window.io) { connectSocket(); }
    else {
      const s = document.createElement('script');
      s.src = '/socket.io/socket.io.js'; s.onload = connectSocket;
      document.head.appendChild(s);
    }
    return () => { if (socketRef.current) socketRef.current.disconnect(); };
  }, []);

  function connectSocket() {
    const sock = window.io({ auth: { token } });
    socketRef.current = sock;
    sock.on('bj:list',       setTables);
    sock.on('bj:table', (t) => {
      if (prevHostRef.current !== null && prevHostRef.current !== username && t.createdBy === username) {
        setHostNotif('You are now the host — only you can deal cards.');
        clearTimeout(hostNotifTimer.current);
        hostNotifTimer.current = setTimeout(() => setHostNotif(''), 5000);
      }
      prevHostRef.current = t.createdBy;
      setTable(t);
      setPhase(isSpectatingRef.current ? 'spectate' : 'table');
    });
    sock.on('bj:joined',     ({ balance: bal }) => { onBalanceChange && onBalanceChange(bal); });
    sock.on('bj:balance',    ({ balance: bal }) => { onBalanceChange && onBalanceChange(bal); });
    sock.on('bj:left',       ({ balance: bal }) => {
      isSpectatingRef.current = false;
      if (bal != null) onBalanceChange && onBalanceChange(bal);
      setPhase('lobby'); setTable(null); setTableChatMessages([]);
    });
    sock.on('bj:closed', ({ balance: bal }) => {
      isSpectatingRef.current = false;
      if (bal != null) onBalanceChange && onBalanceChange(bal);
      setPhase('lobby'); setTable(null); setTableChatMessages([]);
      setErr('This table was closed by an admin. Your bet has been refunded.');
    });
    sock.on('bj:error',      (msg) => setErr(msg));
    sock.on('poker:lobby-chat', (msg) => setChatMessages(ms => [...ms.slice(-99), msg]));
    sock.on('bj:table-chat', (msg) => setTableChatMessages(ms => [...ms.slice(-99), msg]));
  }

  const emit = useCallback((ev, data) => {
    setErr(''); socketRef.current?.emit(ev, data);
  }, []);

  const sendLobbyChat  = useCallback((msg) => socketRef.current?.emit('poker:chat',    { message: msg }), []);
  const sendTableChat  = useCallback((msg) => socketRef.current?.emit('bj:table-chat', { message: msg }), []);

  function spectate(t) {
    isSpectatingRef.current = true;
    emit('bj:spectate', { tableId: t.id });
  }

  function stopSpectating() {
    isSpectatingRef.current = false;
    emit('bj:unspectate');
  }

  /* ── Lobby ──────────────────────────────────────────────────────────────── */
  if (phase === 'lobby') return (
    <div className="game-panel game-panel--wide" data-game-view="group_bj">
      <div className="game-panel-header">
        <button className="btn-back" onClick={onBack}>Lobby</button>
        <div>
          <h1 className="game-panel-title">Group Blackjack</h1>
          <div className="game-panel-subtitle">·❦· The Round Table ·❦·</div>
        </div>
        <div className="game-panel-meta"><span>2–8 Seats</span></div>
      </div>

      <div className="poker-lobby">
        <div className="poker-lobby-create">
          <h3 className="poker-section-title">Create Table</h3>
          <div className="poker-form-row">
            <label>Table Name</label>
            <input className="poker-input" value={tname} onChange={e=>setTname(e.target.value)} placeholder="My Table" maxLength={24} />
          </div>
          <div className="poker-form-row">
            <label>Bet Limits</label>
            <div style={{ display:'flex', gap:6 }}>
              <input className="poker-input" type="number" value={minBet} onChange={e=>setMinBet(parseInt(e.target.value)||0)} placeholder="Min" style={{flex:1}} />
              <span style={{alignSelf:'center',color:'var(--muted)'}}>–</span>
              <input className="poker-input" type="number" value={maxBet} onChange={e=>setMaxBet(parseInt(e.target.value)||0)} placeholder="Max" style={{flex:1}} />
            </div>
          </div>
          <div className="poker-form-row">
            <label>Password (optional)</label>
            <input className="poker-input" type="password" value={tpassword} onChange={e=>setTpassword(e.target.value)} placeholder="Leave blank for public" maxLength={32} />
          </div>
          <button className="btn btn-primary" onClick={() => emit('bj:create', { name: tname||undefined, stakes: { min: minBet, max: maxBet }, password: tpassword||undefined })}>
            Create &amp; Join
          </button>
        </div>

        <div className="poker-lobby-tables">
          <h3 className="poker-section-title">Open Tables</h3>
          {tables.length === 0 && <p className="poker-empty">No tables yet — create one above</p>}
          {tables.map(t => (
            <div key={t.id} className="poker-table-row">
              <div className="poker-table-info">
                <span className="poker-table-name">
                  {t.hasPassword && <span className="poker-lock">🔒</span>}
                  {t.name}
                </span>
                <span className="poker-table-meta">
                  {t.stakes.min.toLocaleString()}–{t.stakes.max.toLocaleString()} G · {t.seats}/8 seated · {t.phase}
                </span>
              </div>
              <div style={{ display: 'flex', gap: 6 }}>
                <button className="btn btn-primary btn-sm" onClick={() => { setJoiningTable(t); setJoinPassword(''); setPhase('seat'); }}>
                  Join
                </button>
                <button className="btn btn-sm" onClick={() => spectate(t)}>
                  Spectate
                </button>
              </div>
            </div>
          ))}
        </div>

        <ChatPanel messages={chatMessages} onSend={sendLobbyChat} title="Lobby Chat" />
      </div>
      {err && <p className="poker-err">{err}</p>}
    </div>
  );

  /* ── Buy-in screen ──────────────────────────────────────────────────────── */
  if (phase === 'seat') return (
    <div className="game-panel" data-game-view="group_bj">
      <div className="game-panel-header">
        <button className="btn-back" onClick={() => setPhase('lobby')}>Back</button>
        <div>
          <h1 className="game-panel-title">Join — {joiningTable?.name}</h1>
          <div className="game-panel-subtitle">·❦· Take a Seat ·❦·</div>
        </div>
        <div className="game-panel-meta"><span>Blackjack</span></div>
      </div>
      <div style={{ padding:'32px 0', maxWidth:320, margin:'0 auto' }}>
        {joiningTable?.hasPassword && (
          <div className="poker-form-row">
            <label>🔒 Password</label>
            <input className="poker-input" type="password" value={joinPassword} onChange={e=>setJoinPassword(e.target.value)} placeholder="Enter table password" maxLength={32} />
          </div>
        )}
        <p style={{ color:'var(--muted)', fontSize:13, marginBottom:16 }}>Bets are charged directly from your account balance each hand.</p>
        <button className="btn btn-primary btn-lg" onClick={() => emit('bj:join', { tableId: joiningTable.id, password: joinPassword||undefined })}>
          Sit Down
        </button>
      </div>
      {err && <p className="poker-err">{err}</p>}
    </div>
  );

  /* ── Spectate ────────────────────────────────────────────────────────────── */
  if (phase === 'spectate' && table) return (
    <GroupBJTable
      table={table} username={username}
      onBet={() => {}} onDeal={() => {}} onAction={() => {}}
      onLeave={stopSpectating}
      chatMessages={tableChatMessages} onChat={sendTableChat}
      err={err}
      spectating={true}
    />
  );

  /* ── Table ──────────────────────────────────────────────────────────────── */
  if (phase === 'table' && table) return (
    <GroupBJTable
      table={table} username={username}
      onBet={amt => emit('bj:bet', { amount: amt })}
      onDeal={() => emit('bj:deal')}
      onAction={a => emit('bj:action', { action: a })}
      onLeave={() => emit('bj:leave')}
      onSitOut={() => emit('bj:sitout')}
      chatMessages={tableChatMessages} onChat={sendTableChat}
      err={err} hostNotif={hostNotif}
    />
  );

  return <div className="game-panel"><p style={{padding:40,color:'var(--muted)'}}>Connecting…</p></div>;
}

/* ── Card component ─────────────────────────────────────────────────────── */
function BjCard({ card, big, dealDelay }) {
  if (!card) return null;
  const red = !card.hidden && (card.suit === '♥' || card.suit === '♦');
  const anim = dealDelay !== undefined
    ? { animation: `pcardDeal 0.42s cubic-bezier(0.2,0.8,0.3,1) ${dealDelay}ms both` }
    : {};
  return (
    <div className={`pcard${big?' pcard--big':''}${card.hidden?' pcard--hidden':''}`}
      style={{ color: red ? 'var(--garnet)' : '#1a1a1a', ...anim }}>
      {!card.hidden && <>
        <div className="pcard-rank">{card.rank}</div>
        <div className="pcard-suit">{card.suit}</div>
      </>}
    </div>
  );
}

/* ── Table view ──────────────────────────────────────────────────────────── */
function GroupBJTable({ table, username, onBet, onDeal, onAction, onLeave, onSitOut, chatMessages, onChat, err, hostNotif = '', spectating = false }) {
  const { useState, useEffect, useRef } = React;
  const [betInput, setBetInput] = useState(table.stakes?.min || 100);

  const [dealKey,          setDealKey]          = useState(0);
  const [visibleDealerLen, setVisibleDealerLen] = useState(0);
  const prevPhaseRef = useRef(table.phase);
  const timersRef    = useRef([]);

  const [countdown, setCountdown] = useState(0);
  const countdownRef = useRef(null);

  const prevVisibleRef   = useRef(0);
  const myCardCountRef   = useRef(0);
  const prevResultKeyRef = useRef(null);

  useEffect(() => {
    const prev = prevPhaseRef.current;
    prevPhaseRef.current = table.phase;
    if (table.phase === 'playing' && prev !== 'playing') {
      timersRef.current.forEach(clearTimeout); timersRef.current = [];
      setDealKey(k => k + 1);
      setVisibleDealerLen(0);
      prevVisibleRef.current = 0;
      const t1 = setTimeout(() => setVisibleDealerLen(1), 300);
      const t2 = setTimeout(() => setVisibleDealerLen(2), 750);
      timersRef.current = [t1, t2];
      const betCount = table.seats.filter(s => s.betPlaced).length;
      for (let i = 0; i < betCount * 2; i++) {
        timersRef.current.push(setTimeout(() => window.SoundFX?.card(), i * 400));
      }
    }
    if (table.phase === 'idle') { setVisibleDealerLen(0); prevVisibleRef.current = 0; }
  }, [table.phase]);

  useEffect(() => {
    const curr = table.dealer.length;
    if (table.phase !== 'dealer' && table.phase !== 'done') return;
    if (curr <= visibleDealerLen) return;
    timersRef.current.forEach(clearTimeout); timersRef.current = [];
    for (let i = visibleDealerLen; i < curr; i++) {
      const t = setTimeout(() => setVisibleDealerLen(i + 1), (i - visibleDealerLen) * 650 + 300);
      timersRef.current.push(t);
    }
  }, [table.dealer.length, table.phase]);

  useEffect(() => () => timersRef.current.forEach(clearTimeout), []);

  useEffect(() => {
    if (table.phase === 'done') {
      setCountdown(10);
      countdownRef.current = setInterval(() => {
        setCountdown(c => {
          if (c <= 1) { clearInterval(countdownRef.current); return 0; }
          return c - 1;
        });
      }, 1000);
    } else {
      clearInterval(countdownRef.current);
      setCountdown(0);
    }
    return () => clearInterval(countdownRef.current);
  }, [table.phase]);

  useEffect(() => {
    if (visibleDealerLen > 0 && visibleDealerLen > prevVisibleRef.current) window.SoundFX?.card();
    prevVisibleRef.current = visibleDealerLen;
  }, [visibleDealerLen]);

  const _myCardCount = table.seats.find(s => s.username === username)?.cards?.length;
  useEffect(() => {
    const count = _myCardCount || 0;
    if (count > myCardCountRef.current && myCardCountRef.current >= 2) window.SoundFX?.card();
    myCardCountRef.current = count;
  }, [_myCardCount]);

  const _myResultMsg = table.seats.find(s => s.username === username)?.result?.msg;
  const _myResultCls = table.seats.find(s => s.username === username)?.result?.cls;
  const _myResultNet = table.seats.find(s => s.username === username)?.result?.net;
  useEffect(() => {
    if (!_myResultMsg || _myResultMsg === prevResultKeyRef.current) return;
    prevResultKeyRef.current = _myResultMsg;
    if (_myResultCls === 'bj')        window.SoundFX?.blackjack();
    else if ((_myResultNet || 0) > 0) window.SoundFX?.win();
    else                              window.SoundFX?.bust();
  }, [_myResultMsg]);

  const myIdx   = table.seats.findIndex(s => s.username === username);
  const mySeat  = myIdx >= 0 ? table.seats[myIdx] : null;
  const myActing = table.phase === 'playing' && table.actingIdx === myIdx && myIdx >= 0;

  const dealerVisible = table.dealer.slice(0, visibleDealerLen);
  const dealerVal = table.phase !== 'playing' ? _bjHandVal(table.dealer) : _bjHandVal([table.dealer[0]].filter(Boolean));

  return (
    <div className="game-panel game-panel--wide" data-game-view="group_bj">
      <div className="game-panel-header">
        <button className="btn-back" onClick={onLeave}>{spectating ? 'Stop Watching' : 'Leave'}</button>
        <div>
          <h1 className="game-panel-title">{table.name}</h1>
          <div className="game-panel-subtitle">·❦· The Round Table ·❦·</div>
        </div>
        <div className="game-panel-meta">
          {spectating
            ? <span className="poker-phase-badge" style={{ background: 'rgba(212,169,96,0.15)', color: 'var(--gold)' }}>Spectating</span>
            : <span className="poker-phase-badge">{table.phase}</span>}
        </div>
      </div>

      <div className="poker-table-layout">
        <div className="poker-chat-col">
          <ChatPanel messages={chatMessages} onSend={onChat} title="Table Chat" />
        </div>
        <div className="poker-game-col">
          {/* Dealer */}
          <div className="bj-dealer-section">
            <div className="bj-dealer-label">Dealer</div>
            <div className="bj-dealer-cards">
              {dealerVisible.length === 0
                ? <span className="poker-community-empty">Waiting for next hand…</span>
                : dealerVisible.map((c, i) => <BjCard key={i} card={c} big dealDelay={i * 420} />)
              }
            </div>
            {dealerVisible.length > 0 && (
              <div className={`bj-hand-value${dealerVal > 21 ? ' bust' : dealerVal === 21 ? ' bj-21' : ''}`}>
                {table.phase === 'playing' ? `${dealerVal} …` : dealerVal > 21 ? 'Bust' : dealerVal}
              </div>
            )}
          </div>

          {/* Seats */}
          <div className="bj-seats">
            {table.seats.map((seat, i) => {
              const isMe = seat.username === username;
              const val  = seat.cards.length > 0 ? _bjHandVal(seat.cards) : 0;
              return (
                <div key={i} className={`bj-seat${isMe?' bj-seat--me':''}${seat.sitout?' bj-seat--sitout':''}${seat.bust?' bj-seat--bust':''}${(seat.stood||seat.doubled)&&!seat.bust?' bj-seat--done':''}${i===table.actingIdx&&table.phase==='playing'?' bj-seat--active':''}`}>
                  <div className="bj-seat-header">
                    <span className="bj-seat-name">{seat.username}</span>
                    <span className="bj-seat-chips">{seat.chips.toLocaleString()} G</span>
                  </div>
                  {seat.sitout && <div className="bj-seat-sitout-badge">Sitting Out</div>}
                  <div className="bj-seat-cards">
                    {seat.cards.length > 0
                      ? seat.cards.map((c, ci) => (
                          <BjCard key={`${dealKey}-${ci}`} card={c} dealDelay={(i * 2 + ci) * 400} />
                        ))
                      : <div className="bj-seat-nocard" />}
                  </div>
                  {seat.cards.length > 0 && (
                    <div className={`bj-hand-value${val > 21?' bust':val===21?' bj-21':''}`}>
                      {val > 21 ? 'Bust' : val}
                    </div>
                  )}
                  {seat.betPlaced
                    ? <div className="bj-seat-bet">Bet: {seat.bet.toLocaleString()} G{seat.doubled?' (2×)':''}</div>
                    : seat.bet > 0
                      ? <div className="bj-seat-bet bj-seat-bet--pending">Bet: {seat.bet.toLocaleString()} G ✓</div>
                      : null}
                  {seat.result && (
                    <div className={`bj-seat-result ${seat.result.net>0?'pos':seat.result.net<0?'neg':'zero'}`}>
                      {seat.result.net > 0 ? '+' : ''}{seat.result.net.toLocaleString()} G
                      <span className="bj-seat-result-msg"> — {seat.result.msg}</span>
                    </div>
                  )}
                  {table.phase === 'playing' && i === table.actingIdx && seat.betPlaced && !seat.stood && !seat.bust && !seat.doubled && (
                    <div className="bj-seat-acting">{isMe ? 'Your Turn!' : 'Acting…'}</div>
                  )}
                  {table.phase === 'playing' && seat.betPlaced && (seat.stood || seat.doubled) && !seat.bust && (
                    <div className="bj-seat-stood">{seat.doubled ? 'Doubled' : 'Standing'}</div>
                  )}
                </div>
              );
            })}
          </div>

          {countdown > 0 && <div className="bj-timer">Next round in {countdown}s</div>}

          {/* Controls */}
          {!spectating && table.phase !== 'done' && <div className="bet-controls" style={{ gap:8, flexWrap:'wrap' }}>
            {mySeat && (
              <button
                className={`btn${mySeat.sitout ? ' btn-primary' : ''}`}
                onClick={() => { window.SoundFX?.chip(); onSitOut(); }}
                style={{ minWidth: 110 }}
              >
                {mySeat.sitout ? 'Return' : 'Sit Out'}
              </button>
            )}
            {table.phase === 'idle' && mySeat && !mySeat.sitout && (
              <>
                <input
                  className="poker-input" type="number"
                  value={betInput} min={table.stakes?.min||1} max={Math.min(table.stakes?.max||1000, mySeat.chips)}
                  onChange={e => setBetInput(parseInt(e.target.value)||0)}
                  style={{ width:120 }}
                />
                <button className="btn btn-primary" onClick={() => { window.SoundFX?.chip(); onBet(betInput); }}>Set Bet</button>
                {table.createdBy === username && table.seats.length > 0 && table.seats.every(s => s.sitout || s.bet > 0) && (
                  <button className="btn btn-primary btn-lg" onClick={() => { window.SoundFX?.chip(); onDeal(); }} style={{ marginLeft:8 }}>
                    Deal Cards
                  </button>
                )}
              </>
            )}
            {table.phase === 'idle' && mySeat && mySeat.sitout && (
              <p style={{ color:'var(--muted)', fontSize:13 }}>You are sitting out — click Return to rejoin</p>
            )}
            {table.phase === 'idle' && table.createdBy === username && !table.seats.every(s => s.sitout || s.bet > 0) && (
              <p style={{ color:'var(--muted)', fontSize:13 }}>Waiting for all players to place bets…</p>
            )}
            {myActing && (
              <>
                <button className="btn btn-primary" onClick={() => { window.SoundFX?.chip(); onAction('hit'); }}>Hit</button>
                <button className="btn"             onClick={() => { window.SoundFX?.chip(); onAction('stand'); }}>Stand</button>
                {mySeat.cards.length === 2 && mySeat.chips >= mySeat.bet && (
                  <button className="btn" onClick={() => { window.SoundFX?.chip(); onAction('double'); }}>Double Down</button>
                )}
              </>
            )}
            {table.phase === 'playing' && !myActing && mySeat?.betPlaced && (
              <p style={{ color:'var(--muted)', fontSize:13 }}>
                {mySeat.bust ? 'You busted' : mySeat.stood ? 'Standing — waiting for others…' : mySeat.doubled ? 'Doubled — waiting for others…' : 'Waiting for your turn…'}
              </p>
            )}
            {table.phase === 'idle' && !mySeat && (
              <p style={{ color:'var(--muted)', fontSize:13 }}>Spectating — wait for next hand to join</p>
            )}
          </div>}
          {spectating && (
            <div className="bet-controls" style={{ justifyContent: 'center' }}>
              <p style={{ color: 'var(--muted)', fontSize: 13, fontStyle: 'italic', fontFamily: 'Cormorant Garamond, serif' }}>
                Watching — bets and actions are disabled
              </p>
            </div>
          )}
          {hostNotif && (
            <div style={{
              marginTop: 10, padding: '8px 14px', borderRadius: 6,
              background: 'rgba(212,169,96,0.12)', border: '1px solid rgba(212,169,96,0.35)',
              color: 'var(--gold)', fontSize: 12, letterSpacing: '0.04em',
            }}>
              {hostNotif}
            </div>
          )}
          {err && <p className="poker-err">{err}</p>}
        </div>
      </div>
    </div>
  );
}
