/* eslint-disable */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ---------- Card metadata ----------

const CARD_FILES = {
  1: 'blue_crab_claw', 2: 'blue_fish', 3: 'blue_shrimp',
  4: 'brown_bacon', 5: 'brown_noodles', 6: 'brown_squid',
  7: 'green_bok_choy', 8: 'green_cabbage', 9: 'green_onion',
  10: 'orange_cauliflower', 11: 'orange_garlic', 12: 'orange_prawn',
  13: 'purple_bmushroom', 14: 'purple_mushroom_cluster', 15: 'purple_rmushroom',
  16: 'red_beef', 17: 'red_mutton', 18: 'red_sausage_roll',
  19: 'white_fish_cake', 20: 'white_oyster', 21: 'white_tofu',
  22: 'yellow_carrot', 23: 'yellow_corn', 24: 'yellow_potato',
};
const CARD_COLOR = {};
[
  ['blue',   [1,2,3]], ['brown', [4,5,6]], ['green', [7,8,9]],
  ['orange', [10,11,12]], ['purple', [13,14,15]], ['red', [16,17,18]],
  ['white',  [19,20,21]], ['yellow', [22,23,24]],
].forEach(([c, ids]) => ids.forEach(id => { CARD_COLOR[id] = c; }));

const COLOR_BORDER = {
  blue: '#3b82f6', brown: '#92400e', green: '#16a34a', orange: '#f97316',
  purple: '#a855f7', red: '#dc2626', white: '#e5e7eb', yellow: '#facc15',
};

const cardSrc = (id) => `cards/${CARD_FILES[id]}.png`;
const backSrc = 'cards/card_back.png';
const prettyName = (id) => (CARD_FILES[id] || '').replace(/_/g, ' ');

// ---------- Socket singleton ----------

const socket = io({ autoConnect: true });

// ---------- Viewport hook ----------

function useIsMobile() {
  const query = '(max-width: 768px)';
  const [isMobile, setIsMobile] = useState(
    () => typeof window !== 'undefined' && window.matchMedia(query).matches
  );
  useEffect(() => {
    const mq = window.matchMedia(query);
    const handler = (e) => setIsMobile(e.matches);
    if (mq.addEventListener) mq.addEventListener('change', handler);
    else mq.addListener(handler);
    return () => {
      if (mq.removeEventListener) mq.removeEventListener('change', handler);
      else mq.removeListener(handler);
    };
  }, []);
  return isMobile;
}

// ---------- Card visual ----------

function Card({ id, faceDown, size = 'md', highlight, onClick, style, className = '', rotate = 0, dim }) {
  const sizes = {
    xs: { w: 38,  h: 58 },
    sm: { w: 54,  h: 83 },
    md: { w: 78,  h: 120 },
    lg: { w: 110, h: 169 },
    xl: { w: 140, h: 215 },
  };
  const s = sizes[size] || sizes.md;
  const src = faceDown ? backSrc : cardSrc(id);
  const interactive = !!onClick;
  return (
    <div
      onClick={onClick}
      className={`relative inline-block ${interactive ? 'cursor-pointer' : ''} ${className}`}
      style={{
        width: s.w, height: s.h,
        transform: `rotate(${rotate}deg)`,
        transition: 'transform 180ms ease, filter 180ms ease',
        filter: dim ? 'brightness(0.55) saturate(0.7)' : 'none',
        ...style,
      }}
    >
      <img
        src={src}
        alt={faceDown ? 'card back' : prettyName(id)}
        className="card-img absolute inset-0 w-full h-full object-contain rounded-md select-none pointer-events-none"
        draggable={false}
        style={{
          boxShadow: highlight
            ? '0 0 0 3px rgba(251,146,60,0.85), 0 0 22px rgba(251,191,36,0.7)'
            : '0 4px 10px rgba(0,0,0,0.55)',
          borderRadius: 8,
        }}
      />
      {highlight && (
        <div className="absolute inset-0 rounded-md animate-glowpulse pointer-events-none" />
      )}
    </div>
  );
}

// ---------- Generic UI bits ----------

function Button({ children, onClick, disabled, variant = 'primary', className = '', size='md' }) {
  const sizes = { sm: 'px-3 py-1.5 text-sm', md: 'px-5 py-2.5 text-base', lg: 'px-7 py-3 text-lg' };
  const styles = {
    primary: 'bg-gradient-to-b from-ember-400 to-ember-600 text-white shadow-lg hover:from-ember-300 hover:to-ember-500 border border-ember-700',
    ghost: 'bg-hearth-800/60 text-ember-100 border border-hearth-600 hover:bg-hearth-700/70',
    danger: 'bg-gradient-to-b from-red-500 to-red-700 text-white border border-red-800',
  };
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      className={`rounded-full font-display font-bold tracking-wide transition ${sizes[size]} ${styles[variant]} ${disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer hover:-translate-y-0.5 active:translate-y-0'} ${className}`}
    >
      {children}
    </button>
  );
}

function Panel({ children, className = '' }) {
  return (
    <div
      className={`rounded-3xl border border-hearth-500/60 ${className}`}
      style={{
        background: 'linear-gradient(160deg, rgba(122,63,22,0.85) 0%, rgba(58,28,10,0.92) 100%)',
        boxShadow: '0 10px 50px rgba(0,0,0,0.55), inset 0 0 0 1px rgba(253,186,116,0.18)',
      }}
    >
      {children}
    </div>
  );
}

// ---------- Home screen ----------

function HomeScreen({ onHost, onJoin }) {
  return (
    <div className="min-h-screen w-full flex items-center justify-center px-6">
      <Panel className="p-10 max-w-xl w-full text-center">
        <h1 className="font-display text-5xl text-ember-300 mb-1 drop-shadow">Palia Hotpot</h1>
        <p className="text-ember-100/70 italic mb-8">Cozy up to the pot. Three sets to win.</p>
        <div className="flex flex-col gap-4 items-center">
          <Button size="lg" onClick={onHost} className="w-64">Host a Game</Button>
          <Button size="lg" variant="ghost" onClick={onJoin} className="w-64">Join a Game</Button>
        </div>
        <p className="mt-10 text-xs text-ember-100/40">High Ground Web · admin@ahcomputing.com</p>
      </Panel>
    </div>
  );
}

// ---------- Name prompt ----------

function NamePrompt({ title, onSubmit, onCancel, defaultName }) {
  const [name, setName] = useState(defaultName || '');
  const submit = () => {
    const trimmed = name.trim().slice(0, 24);
    if (trimmed) onSubmit(trimmed);
  };
  return (
    <div className="min-h-screen w-full flex items-center justify-center px-6">
      <Panel className="p-8 max-w-md w-full">
        <h2 className="font-display text-2xl text-ember-300 mb-4 text-center">{title}</h2>
        <input
          autoFocus
          value={name}
          onChange={e => setName(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter') submit(); }}
          placeholder="Your name"
          maxLength={24}
          className="w-full rounded-xl bg-hearth-900/70 border border-hearth-500/70 px-4 py-3 text-lg text-ember-50 placeholder:text-ember-100/30 focus:outline-none focus:border-ember-400"
        />
        <div className="flex gap-3 mt-5 justify-end">
          <Button variant="ghost" onClick={onCancel}>Cancel</Button>
          <Button onClick={submit} disabled={!name.trim()}>Continue</Button>
        </div>
      </Panel>
    </div>
  );
}

// ---------- Lobby list ----------

function LobbyListScreen({ lobbies, onPick, onBack }) {
  return (
    <div className="min-h-screen w-full flex items-center justify-center px-6">
      <Panel className="p-8 max-w-2xl w-full">
        <div className="flex items-center justify-between mb-5">
          <h2 className="font-display text-2xl text-ember-300">Open Lobbies</h2>
          <Button variant="ghost" size="sm" onClick={onBack}>Back</Button>
        </div>
        {lobbies.length === 0 && (
          <div className="text-center text-ember-100/60 italic py-10">
            No open lobbies yet. Be the first to host!
          </div>
        )}
        <div className="flex flex-col gap-2 max-h-[60vh] scrollable">
          {lobbies.map(l => (
            <div
              key={l.lobbyId}
              className="flex items-center justify-between bg-hearth-900/60 border border-hearth-600/60 rounded-xl px-4 py-3"
            >
              <div className="flex-1">
                <div className="font-display text-lg text-ember-100">{l.hostName}'s Game</div>
                <div className="text-xs text-ember-100/60">{l.playerCount} / 4 players</div>
              </div>
              <Button size="sm" onClick={() => onPick(l.lobbyId)}>Join</Button>
            </div>
          ))}
        </div>
      </Panel>
    </div>
  );
}

// ---------- Lobby ----------

function LobbyScreen({ lobbyState, isHost, onStart, onLeave }) {
  const count = lobbyState.players.length;
  return (
    <div className="min-h-screen w-full flex items-center justify-center px-6">
      <Panel className="p-8 max-w-xl w-full">
        <div className="flex items-center justify-between mb-2">
          <h2 className="font-display text-2xl text-ember-300">Lobby</h2>
          <Button variant="ghost" size="sm" onClick={onLeave}>Leave</Button>
        </div>
        <div className="text-ember-100/70 mb-4">{count} / 4 players · empty seats will be filled with bots</div>
        <div className="flex flex-col gap-2 mb-6">
          {Array.from({ length: 4 }).map((_, i) => {
            const p = lobbyState.players[i];
            return (
              <div key={i} className="flex items-center gap-3 bg-hearth-900/60 border border-hearth-600/50 rounded-xl px-4 py-3">
                <div className="w-8 h-8 rounded-full bg-ember-500/30 border border-ember-400/40 flex items-center justify-center text-ember-100 font-bold">
                  {i + 1}
                </div>
                <div className="flex-1 font-display text-lg">
                  {p ? p.name : <span className="italic text-ember-100/40">empty (bot)</span>}
                </div>
                {p && i === 0 && (
                  <span className="text-xs uppercase tracking-wider text-ember-300/90">host</span>
                )}
              </div>
            );
          })}
        </div>
        {isHost ? (
          <Button size="lg" onClick={onStart} className="w-full" disabled={count < 1}>
            Start Game
          </Button>
        ) : (
          <div className="text-center text-ember-100/70 italic">Waiting for host to start...</div>
        )}
      </Panel>
    </div>
  );
}

// ---------- Action Log ----------

function ActionLog({ entries }) {
  // Show last 4 entries, fading the older ones
  const recent = entries.slice(-4);
  return (
    <div className="absolute top-4 right-4 flex flex-col items-end gap-1.5 z-30 pointer-events-none max-w-xs">
      {recent.map((e, i) => {
        const age = recent.length - 1 - i;
        const opacity = age === 0 ? 1 : age === 1 ? 0.8 : age === 2 ? 0.55 : 0.35;
        return (
          <div
            key={`${entries.length - recent.length + i}-${e}`}
            className="bg-hearth-900/85 border border-hearth-500/60 text-ember-100 text-sm rounded-full px-3 py-1.5 shadow animate-fadeup"
            style={{ opacity }}
          >
            {e}
          </div>
        );
      })}
    </div>
  );
}

// ---------- Game screen ----------

// Seat positions around the table relative to client:
// bottom: myIndex; clockwise: left=(my+1), top=(my+2), right=(my+3)
function seatForIndex(myIndex, playerIndex, total) {
  if (playerIndex === myIndex) return 'bottom';
  const diff = ((playerIndex - myIndex) + total) % total;
  if (total === 4) {
    if (diff === 1) return 'left';
    if (diff === 2) return 'top';
    if (diff === 3) return 'right';
  }
  // Fallback (3-player edge case): spread top/left/right
  if (diff === 1) return 'left';
  if (diff === 2) return 'right';
  return 'top';
}

function OpponentSeat({ player, seat, isActive, isCurrentTurn, drawPhaseHighlight, onClickDiscard }) {
  const handCount = player.handSize || 0;
  const cards = Array.from({ length: handCount });
  // Rotation for opponent hand cards
  const rotates = { top: 180, left: 90, right: -90, bottom: 0 };
  const rotate = rotates[seat] || 0;

  // Position styles per seat for the seat container
  const seatStyle = {
    top:    { top: 8, left: '50%', transform: 'translateX(-50%)' },
    left:   { left: 8, top: '50%', transform: 'translateY(-50%)' },
    right:  { right: 8, top: '50%', transform: 'translateY(-50%)' },
  }[seat] || {};

  const nameSide = {
    top:   'order-first mb-2',
    left:  'mb-2',
    right: 'mb-2',
  }[seat] || '';

  // Layout: hand of mini cards arranged in a row (top) or column (left/right)
  const layoutClass = seat === 'left' || seat === 'right' ? 'flex-col' : 'flex-row';

  return (
    <div
      className="absolute z-20 flex items-center"
      style={{
        ...seatStyle,
        flexDirection: seat === 'left' ? 'row' : seat === 'right' ? 'row-reverse' : 'column',
        gap: 8,
      }}
    >
      <div className={`flex items-center gap-2 ${seat === 'left' || seat === 'right' ? 'flex-col' : ''}`}>
        <div
          className={`font-display rounded-full px-3 py-1 border ${isCurrentTurn ? 'border-ember-300 text-ember-50 bg-ember-700/60 animate-glowpulse' : 'border-hearth-500/70 text-ember-100/90 bg-hearth-900/70'}`}
          style={{ writingMode: 'horizontal-tb' }}
        >
          {player.name} {!player.isHuman && <span className="text-xs italic opacity-70">(bot)</span>}
        </div>
      </div>

      <div className={`flex ${layoutClass} items-center justify-center`}>
        {cards.map((_, i) => {
          const overlap = seat === 'left' || seat === 'right' ? -50 : -32;
          const wrapStyle = (seat === 'left' || seat === 'right')
            ? { marginTop: i === 0 ? 0 : overlap }
            : { marginLeft: i === 0 ? 0 : overlap };
          return (
            <div key={i} style={wrapStyle}>
              <Card faceDown size="sm" rotate={rotate} />
            </div>
          );
        })}
      </div>
    </div>
  );
}

function MySeat({ me, isMyTurn, phase, drawnCard, onDiscardCard, dim }) {
  const handToShow = [...me.hand].sort((a, b) => a - b);
  return (
    <div className="absolute bottom-0 left-0 right-0 flex flex-col items-center z-30 pb-2"
         style={{ filter: dim ? 'brightness(0.7)' : 'none', transition: 'filter 250ms' }}>
      {/* Drawn card display */}
      {drawnCard != null && (
        <div className="mb-2 flex items-center gap-3 animate-fadeup">
          <div className="text-ember-200 italic">You drew:</div>
          <Card
            id={drawnCard}
            size="lg"
            onClick={phase === 'discard' ? () => onDiscardCard(drawnCard) : undefined}
            highlight
            className="animate-softfloat"
          />
          {phase === 'discard' && <div className="text-ember-200 italic">Click a card to discard</div>}
        </div>
      )}

      <div className="flex items-end justify-center">
        {handToShow.map((id, i) => {
          const total = handToShow.length;
          const offset = (i - (total - 1) / 2);
          const rotate = offset * 3.2;
          const lift = -Math.abs(offset) * 1.5;
          return (
            <div
              key={`${id}-${i}`}
              style={{ transform: `translateY(${lift}px)`, marginLeft: i === 0 ? 0 : -28 }}
              className="hover:z-10 relative transition"
            >
              <Card
                id={id}
                size="md"
                rotate={rotate}
                onClick={phase === 'discard' && isMyTurn ? () => onDiscardCard(id) : undefined}
                highlight={false}
              />
            </div>
          );
        })}
      </div>

      <div className={`mt-1 font-display rounded-full px-4 py-1 border ${isMyTurn ? 'border-ember-300 text-ember-50 bg-ember-700/60 animate-glowpulse' : 'border-hearth-500/70 text-ember-100/90 bg-hearth-900/70'}`}>
        {me.name} <span className="text-xs italic opacity-70">(you)</span>
      </div>
    </div>
  );
}

function CenterArea({ players, myIndex, drawPhase, onDrawDeck, onDrawDiscard, drawnCard, currentPlayerIndex }) {
  // Position the 4 player discard piles around the deck.
  // The pile for the "bottom" player sits just below the deck,
  // the "top" player just above, etc.
  const seats = {};
  players.forEach(p => {
    seats[seatForIndex(myIndex, p.index, players.length)] = p;
  });
  const seatPositions = {
    bottom: { left: '50%', top: '50%', dx: 0,     dy: 110, rot: 0 },
    top:    { left: '50%', top: '50%', dx: 0,     dy: -110, rot: 180 },
    left:   { left: '50%', top: '50%', dx: -150,  dy: 0,   rot: 90 },
    right:  { left: '50%', top: '50%', dx: 150,   dy: 0,   rot: -90 },
  };

  return (
    <div className="absolute left-1/2 top-1/2" style={{ transform: 'translate(-50%, -50%)' }}>
      <div className="relative" style={{ width: 360, height: 360 }}>
        {/* glowing pot underlay */}
        <div
          className="absolute inset-0 rounded-full"
          style={{
            background: 'radial-gradient(circle at 50% 50%, rgba(255,170,80,0.85) 0%, rgba(234,88,12,0.55) 40%, rgba(124,45,18,0.0) 75%)',
            filter: 'blur(2px)',
          }}
        />
        {/* deck */}
        <div className="absolute left-1/2 top-1/2" style={{ transform: 'translate(-50%, -50%)' }}>
          <Card
            faceDown
            size="lg"
            onClick={drawPhase && drawnCard == null ? onDrawDeck : undefined}
            highlight={drawPhase && drawnCard == null}
          />
          <div className="text-center mt-1 text-xs uppercase tracking-widest text-ember-200/80 font-display">deck</div>
        </div>

        {/* discard piles */}
        {Object.entries(seatPositions).map(([seat, pos]) => {
          const p = seats[seat];
          if (!p) return null;
          const pile = p.discardPile || [];
          const topCard = pile.length ? pile[pile.length - 1] : null;
          const canTake = drawPhase && drawnCard == null && topCard != null;
          return (
            <div
              key={seat}
              className="absolute"
              style={{
                left: pos.left, top: pos.top,
                transform: `translate(-50%, -50%) translate(${pos.dx}px, ${pos.dy}px)`,
              }}
            >
              {topCard != null ? (
                <Card
                  id={topCard}
                  size="sm"
                  rotate={pos.rot}
                  onClick={canTake ? () => onDrawDiscard(p.index) : undefined}
                  highlight={canTake}
                />
              ) : (
                <div
                  className="rounded-md border-2 border-dashed border-hearth-500/50"
                  style={{ width: 54, height: 83, transform: `rotate(${pos.rot}deg)` }}
                />
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

function TableBackdrop() {
  return (
    <div className="absolute inset-0 pointer-events-none">
      {/* outer dark wood ring */}
      <div
        className="absolute left-1/2 top-1/2 rounded-full"
        style={{
          width: 'min(94vh, 94vw)',
          height: 'min(94vh, 94vw)',
          transform: 'translate(-50%, -50%)',
          background: 'radial-gradient(circle at 50% 50%, #5a2d10 60%, #2b1106 100%)',
          boxShadow: 'inset 0 0 80px rgba(0,0,0,0.7), 0 0 60px rgba(0,0,0,0.6)',
          border: '6px solid #3d1e0a',
        }}
      />
      {/* warm pot center */}
      <div
        className="absolute left-1/2 top-1/2 rounded-full"
        style={{
          width: 'min(60vh, 60vw)',
          height: 'min(60vh, 60vw)',
          transform: 'translate(-50%, -50%)',
          background: 'radial-gradient(circle at 50% 50%, rgba(255,196,128,0.85) 0%, rgba(234,88,12,0.55) 45%, rgba(124,45,18,0.15) 80%, rgba(0,0,0,0) 100%)',
          boxShadow: 'inset 0 0 80px rgba(0,0,0,0.5)',
        }}
      />
    </div>
  );
}

function WinOverlay({ finalState, myIndex, onPlayAgain, isHost }) {
  const winnerIdx = finalState.winner;
  const winner = finalState.players[winnerIdx];
  const winningSets = finalState.winningSets || [];
  const winningIds = new Set(winningSets.flatMap(s => s.cards));

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm p-2 overflow-y-auto scrollable">
      <Panel className="p-4 sm:p-8 max-w-4xl w-full sm:w-[90%] animate-winpop my-auto">
        <h2 className="font-display text-2xl sm:text-4xl text-ember-300 text-center mb-2">
          {winner.name} wins! 🎉
        </h2>
        {winnerIdx === myIndex && (
          <div className="text-center text-ember-200 italic mb-3">A delicious victory.</div>
        )}

        {/* Winner's sets */}
        <div className="mb-6">
          <div className="text-center text-ember-200/80 uppercase tracking-wider text-xs mb-2">Winning hand</div>
          <div className="flex flex-wrap justify-center gap-6">
            {winningSets.map((s, si) => (
              <div key={si} className="flex flex-col items-center">
                <div className="flex gap-1">
                  {s.cards.map((cid, ci) => (
                    <div
                      key={ci}
                      style={{
                        border: `3px solid ${s.type === 'color' ? COLOR_BORDER[s.color] : '#fbbf24'}`,
                        borderRadius: 10,
                        padding: 2,
                      }}
                    >
                      <Card id={cid} size="sm" />
                    </div>
                  ))}
                </div>
                <div className="text-xs mt-1 text-ember-100/80 capitalize">
                  {s.type === 'color' ? `${s.color} set` : `Triple ${prettyName(s.cardId)}`}
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* All hands revealed */}
        <div className="mb-6">
          <div className="text-center text-ember-200/80 uppercase tracking-wider text-xs mb-2">All hands</div>
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
            {finalState.players.map(p => (
              <div key={p.index} className={`p-3 rounded-xl border ${p.index === winnerIdx ? 'border-ember-400 bg-ember-700/20' : 'border-hearth-600/50 bg-hearth-900/40'}`}>
                <div className="font-display mb-1 text-ember-100">{p.name}{p.index === winnerIdx && ' 👑'}</div>
                <div className="flex flex-wrap gap-1">
                  {p.hand.map((cid, ci) => (
                    <div key={ci} style={{
                      outline: p.index === winnerIdx && winningIds.has(cid) ? '2px solid #fbbf24' : 'none',
                      borderRadius: 8,
                    }}>
                      <Card id={cid} size="xs" />
                    </div>
                  ))}
                </div>
              </div>
            ))}
          </div>
        </div>

        <div className="flex justify-center">
          {isHost ? (
            <Button size="lg" onClick={onPlayAgain}>Play Again</Button>
          ) : (
            <div className="text-ember-100/70 italic">Waiting for host to restart...</div>
          )}
        </div>
      </Panel>
    </div>
  );
}

// ---------- Mobile game screen ----------

function MobileActionLog({ entries }) {
  // Show only the latest 2 entries as compact pills near the top of the screen
  const recent = entries.slice(-2);
  return (
    <div className="absolute left-0 right-0 flex flex-col items-center gap-1 z-40 pointer-events-none px-2"
         style={{ top: 44 }}>
      {recent.map((e, i) => {
        const age = recent.length - 1 - i;
        const opacity = age === 0 ? 1 : 0.6;
        return (
          <div
            key={`${entries.length - recent.length + i}-${e}`}
            className="bg-hearth-900/85 border border-hearth-500/60 text-ember-100 text-xs rounded-full px-3 py-1 shadow animate-fadeup max-w-full truncate"
            style={{ opacity }}
          >
            {e}
          </div>
        );
      })}
    </div>
  );
}

function MobileOpponentRow({ p, isCurrent, hasNinthCard, canTakeDiscard, onDrawDiscard }) {
  const topDiscard = p.discardPile.length ? p.discardPile[p.discardPile.length - 1] : null;
  const handDots = Math.min(p.handSize, 8);
  return (
    <div className={`flex items-center gap-2 px-3 py-2 border-b border-hearth-500/30 ${isCurrent ? 'bg-ember-700/15' : ''}`}>
      <div className="flex-1 min-w-0">
        <div className="flex items-center gap-2">
          <div className={`font-display text-sm truncate ${isCurrent ? 'text-ember-200' : 'text-ember-100'}`}>
            {p.name}
          </div>
          {!p.isHuman && <span className="text-[10px] italic opacity-60 text-ember-100">bot</span>}
          {isCurrent && <span className="text-[10px] uppercase tracking-widest text-ember-300 animate-glowpulse rounded-full px-1.5 border border-ember-400/60">turn</span>}
        </div>
        <div className="text-[10px] text-ember-100/60 mb-1">
          {p.handSize} cards{hasNinthCard ? ' + 1 drawn' : ''}
        </div>
        <div className="flex">
          {Array.from({ length: handDots }).map((_, i) => (
            <div key={i} style={{ marginLeft: i === 0 ? 0 : -18 }}>
              <Card faceDown size="xs" />
            </div>
          ))}
        </div>
      </div>
      <div className="flex items-end gap-1.5">
        <div className="flex flex-col items-center">
          <div className="text-[9px] uppercase tracking-wider text-ember-100/40 mb-0.5">discard</div>
          {topDiscard != null ? (
            <Card
              id={topDiscard}
              size="sm"
              onClick={canTakeDiscard ? () => onDrawDiscard(p.index) : undefined}
              highlight={canTakeDiscard}
            />
          ) : (
            <div className="rounded-md border-2 border-dashed border-hearth-500/40" style={{ width: 54, height: 83 }} />
          )}
        </div>
        {hasNinthCard && (
          <div className="flex flex-col items-center animate-fadeup">
            <div className="text-[9px] uppercase tracking-wider text-ember-100/40 mb-0.5">drew</div>
            <Card faceDown size="sm" />
          </div>
        )}
      </div>
    </div>
  );
}

function MobileGameScreen({ gameState, finalState, isHost, onDrawDeck, onDrawDiscard, onDiscard, onPlayAgain }) {
  const me = gameState.players[gameState.myIndex];
  const isMyTurn = gameState.currentPlayerIndex === gameState.myIndex;
  const phase = gameState.phase;
  const drawPhaseForMe = phase === 'draw' && isMyTurn;
  const canDrawDeck = drawPhaseForMe && gameState.drawnCard == null;
  const opponents = gameState.players.filter(p => p.index !== gameState.myIndex);
  const sortedHand = [...me.hand].sort((a, b) => a - b);

  return (
    <div className="relative w-screen h-screen overflow-hidden flex flex-col"
         style={{ background: 'radial-gradient(1200px 800px at 50% 50%, #4a1f08 0%, #2b1106 55%, #160803 100%)' }}>
      {/* Header */}
      <div className="flex items-center justify-between px-3 py-2 bg-hearth-900/70 border-b border-hearth-500/40 z-30">
        <div className="font-display text-sm text-ember-200">Round {gameState.round}</div>
        <div className="font-display text-xs text-ember-200/90 italic text-right truncate ml-2">
          {phase === 'won'
            ? 'Game over'
            : isMyTurn
              ? (phase === 'draw' ? 'Your turn — draw' : 'Your turn — discard')
              : `${gameState.players[gameState.currentPlayerIndex].name}'s turn`}
        </div>
      </div>

      {/* Opponents */}
      <div className="flex-1 overflow-y-auto scrollable">
        {opponents.map(p => {
          const isCurrent = gameState.currentPlayerIndex === p.index;
          const hasNinthCard = isCurrent && phase === 'discard';
          const topDiscard = p.discardPile.length ? p.discardPile[p.discardPile.length - 1] : null;
          const canTake = drawPhaseForMe && gameState.drawnCard == null && topDiscard != null;
          return (
            <MobileOpponentRow
              key={p.index}
              p={p}
              isCurrent={isCurrent}
              hasNinthCard={hasNinthCard}
              canTakeDiscard={canTake}
              onDrawDiscard={onDrawDiscard}
            />
          );
        })}
      </div>

      {/* Deck row */}
      <div className="flex items-center justify-center gap-3 py-2 bg-hearth-900/40 border-y border-hearth-500/40">
        <Card
          faceDown
          size="sm"
          onClick={canDrawDeck ? onDrawDeck : undefined}
          highlight={canDrawDeck}
        />
        <div className="text-xs text-ember-200/70 italic">
          {canDrawDeck ? 'tap deck to draw' : 'deck'}
        </div>
      </div>

      {/* Drawn card */}
      {gameState.drawnCard != null && (
        <div className="flex items-center justify-center gap-3 py-2 bg-ember-900/30 animate-fadeup">
          <div className="text-xs text-ember-200 whitespace-nowrap">You drew:</div>
          <Card
            id={gameState.drawnCard}
            size="md"
            onClick={phase === 'discard' ? () => onDiscard(gameState.drawnCard) : undefined}
            highlight
          />
          {phase === 'discard' && (
            <div className="text-[11px] text-ember-200/80 italic">tap any card<br />to discard</div>
          )}
        </div>
      )}

      {/* My hand */}
      <div className="bg-hearth-900/70 border-t border-hearth-500/40 px-2 pt-2 pb-3">
        <div className="flex items-baseline justify-between mb-1 px-1">
          <div className="font-display text-sm text-ember-100">
            {me.name} <span className="text-[10px] italic opacity-60">(you)</span>
          </div>
          <div className="text-[10px] text-ember-100/50">{sortedHand.length} cards</div>
        </div>
        <div className="flex overflow-x-auto scrollable pb-1" style={{ gap: 2 }}>
          {sortedHand.map((id, i) => (
            <div key={`${id}-${i}`} className="flex-shrink-0">
              <Card
                id={id}
                size="md"
                onClick={phase === 'discard' && isMyTurn ? () => onDiscard(id) : undefined}
              />
            </div>
          ))}
        </div>
      </div>

      <MobileActionLog entries={gameState.actionLog || []} />

      {finalState && (
        <WinOverlay
          finalState={finalState}
          myIndex={gameState.myIndex}
          onPlayAgain={onPlayAgain}
          isHost={isHost}
        />
      )}
    </div>
  );
}

function GameScreen({ gameState, finalState, isHost, onDrawDeck, onDrawDiscard, onDiscard, onPlayAgain }) {
  const me = gameState.players[gameState.myIndex];
  const isMyTurn = gameState.currentPlayerIndex === gameState.myIndex;
  const phase = gameState.phase;
  const drawPhaseForMe = phase === 'draw' && isMyTurn;
  const discardPhaseForMe = phase === 'discard' && isMyTurn;

  // Other players
  const opponents = gameState.players.filter(p => p.index !== gameState.myIndex);

  return (
    <div className="relative w-screen h-screen overflow-hidden">
      <TableBackdrop />

      {/* HUD top-left: round indicator */}
      <div className="absolute top-4 left-4 z-30">
        <div className="bg-hearth-900/80 border border-hearth-500/60 rounded-full px-4 py-1.5 font-display text-ember-100">
          Round {gameState.round}
        </div>
      </div>

      {/* Opponents */}
      {opponents.map(p => {
        const seat = seatForIndex(gameState.myIndex, p.index, gameState.players.length);
        return (
          <OpponentSeat
            key={p.index}
            player={p}
            seat={seat}
            isActive
            isCurrentTurn={gameState.currentPlayerIndex === p.index}
          />
        );
      })}

      {/* Center */}
      <CenterArea
        players={gameState.players}
        myIndex={gameState.myIndex}
        drawPhase={drawPhaseForMe}
        onDrawDeck={onDrawDeck}
        onDrawDiscard={onDrawDiscard}
        drawnCard={gameState.drawnCard}
        currentPlayerIndex={gameState.currentPlayerIndex}
      />

      {/* My seat */}
      <MySeat
        me={me}
        isMyTurn={isMyTurn}
        phase={phase}
        drawnCard={gameState.drawnCard}
        onDiscardCard={onDiscard}
        dim={!isMyTurn && phase !== 'won'}
      />

      <ActionLog entries={gameState.actionLog || []} />

      {/* Turn indicator banner */}
      {phase !== 'won' && (
        <div className="absolute left-1/2 -translate-x-1/2 z-30" style={{ top: 56 }}>
          <div className="font-display text-ember-200 italic">
            {isMyTurn ? (phase === 'draw' ? 'Your turn — draw a card' : 'Your turn — discard a card') : `${gameState.players[gameState.currentPlayerIndex].name}'s turn`}
          </div>
        </div>
      )}

      {/* Win overlay */}
      {finalState && (
        <WinOverlay
          finalState={finalState}
          myIndex={gameState.myIndex}
          onPlayAgain={onPlayAgain}
          isHost={isHost}
        />
      )}
    </div>
  );
}

// ---------- App root ----------

function App() {
  const [screen, setScreen] = useState('home'); // 'home' | 'name_host' | 'lobby_list' | 'name_join' | 'lobby' | 'game'
  const [lobbies, setLobbies] = useState([]);
  const [lobbyState, setLobbyState] = useState(null);
  const [gameState, setGameState] = useState(null);
  const [finalState, setFinalState] = useState(null);
  const [pendingJoinLobbyId, setPendingJoinLobbyId] = useState(null);
  const [toast, setToast] = useState(null);
  const [mySocketId, setMySocketId] = useState(socket.id);
  const isMobile = useIsMobile();

  useEffect(() => {
    function onConnect() { setMySocketId(socket.id); }
    function onLobbiesList(p) { setLobbies(p.lobbies || []); }
    function onLobbyCreated(p) {
      setLobbyState(p.lobbyState);
      setScreen('lobby');
    }
    function onLobbyUpdated(p) {
      setLobbyState(p.lobbyState);
      // If we were in 'game' or 'end' and the lobby reset, go back to lobby screen
      setScreen(s => (s === 'lobby' ? 'lobby' : 'lobby'));
      setGameState(null);
      setFinalState(null);
    }
    function onGameStarted(p) {
      setGameState(p.gameState);
      setFinalState(null);
      setScreen('game');
    }
    function onStateUpdate(p) {
      setGameState(p.gameState);
    }
    function onGameOver(p) {
      setFinalState(p.finalState);
      // gameState stays for context; overlay sits on top
    }
    function onErr(p) {
      const msg = p.message || 'Error';
      setToast(msg);
      // Only kick home when the lobby has actually closed under us
      if (msg === 'Host left the lobby' || msg === 'Lobby closed') {
        setScreen('home');
        setLobbyState(null);
        setGameState(null);
        setFinalState(null);
      }
      setTimeout(() => setToast(null), 3500);
    }
    function onLeft() {
      setScreen('home');
      setLobbyState(null);
      setGameState(null);
      setFinalState(null);
    }

    socket.on('connect', onConnect);
    socket.on('lobbies_list', onLobbiesList);
    socket.on('lobby_created', onLobbyCreated);
    socket.on('lobby_updated', onLobbyUpdated);
    socket.on('game_started', onGameStarted);
    socket.on('state_update', onStateUpdate);
    socket.on('game_over', onGameOver);
    socket.on('error', onErr);
    socket.on('left_lobby', onLeft);

    return () => {
      socket.off('connect', onConnect);
      socket.off('lobbies_list', onLobbiesList);
      socket.off('lobby_created', onLobbyCreated);
      socket.off('lobby_updated', onLobbyUpdated);
      socket.off('game_started', onGameStarted);
      socket.off('state_update', onStateUpdate);
      socket.off('game_over', onGameOver);
      socket.off('error', onErr);
      socket.off('left_lobby', onLeft);
    };
  }, []);

  // Periodically refresh lobby list while on the lobby_list screen
  useEffect(() => {
    if (screen !== 'lobby_list') return;
    socket.emit('list_lobbies');
    const id = setInterval(() => socket.emit('list_lobbies'), 3000);
    return () => clearInterval(id);
  }, [screen]);

  const lobbyId = lobbyState?.lobbyId;
  const isHost = !!(lobbyState && lobbyState.hostSocketId === mySocketId)
              || !!(gameState && gameState.hostSocketId === mySocketId);

  // --- Actions ---
  const hostFlow = () => setScreen('name_host');
  const joinFlow = () => { socket.emit('list_lobbies'); setScreen('lobby_list'); };
  const createLobby = (name) => socket.emit('create_lobby', { playerName: name });
  const pickLobby = (id) => { setPendingJoinLobbyId(id); setScreen('name_join'); };
  const joinLobby = (name) => socket.emit('join_lobby', { lobbyId: pendingJoinLobbyId, playerName: name });
  const startGame = () => socket.emit('start_game', { lobbyId });
  const leave = () => socket.emit('leave_lobby');
  const drawDeck = () => socket.emit('draw_from_deck', { lobbyId: gameState.lobbyId });
  const drawDiscard = (fromPlayerIndex) => socket.emit('draw_from_discard', { lobbyId: gameState.lobbyId, fromPlayerIndex });
  const discard = (cardId) => socket.emit('discard_card', { lobbyId: gameState.lobbyId, cardId });
  const playAgain = () => socket.emit('play_again', { lobbyId: gameState.lobbyId });

  // --- Render ---
  let body;
  if (screen === 'home')          body = <HomeScreen onHost={hostFlow} onJoin={joinFlow} />;
  else if (screen === 'name_host')  body = <NamePrompt title="Your name" onSubmit={(n) => createLobby(n)} onCancel={() => setScreen('home')} />;
  else if (screen === 'lobby_list') body = <LobbyListScreen lobbies={lobbies} onPick={pickLobby} onBack={() => setScreen('home')} />;
  else if (screen === 'name_join')  body = <NamePrompt title="Your name" onSubmit={(n) => joinLobby(n)} onCancel={() => setScreen('lobby_list')} />;
  else if (screen === 'lobby' && lobbyState) body = <LobbyScreen lobbyState={lobbyState} isHost={isHost} onStart={startGame} onLeave={leave} />;
  else if (screen === 'game' && gameState) {
    const GameComp = isMobile ? MobileGameScreen : GameScreen;
    body = (
      <GameComp
        gameState={gameState}
        finalState={finalState}
        isHost={isHost}
        onDrawDeck={drawDeck}
        onDrawDiscard={drawDiscard}
        onDiscard={discard}
        onPlayAgain={playAgain}
      />
    );
  }
  else body = <HomeScreen onHost={hostFlow} onJoin={joinFlow} />;

  return (
    <>
      {body}
      {toast && (
        <div className="fixed bottom-4 left-1/2 -translate-x-1/2 z-[100] bg-red-900/90 border border-red-500 text-white px-4 py-2 rounded-full shadow-lg animate-fadeup">
          {toast}
        </div>
      )}
    </>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
