import React, { useEffect, useMemo, useState } from 'react';
import { Routes, Route, Link, useLocation, useNavigate, useParams } from 'react-router-dom';
import { apiFetch, clearToken, getToken, getUsername, setToken, wsUrl } from './api.js';
import logo from './assets/colonist/logo.png';
import iconTrophy from './assets/colonist/icon_trophy.svg';
import iconFriends from './assets/colonist/icon_friends.svg';
import iconPlay from './assets/colonist/icon_play.svg';
import iconCoin from './assets/colonist/icon_coin.svg';
import iconPlayer from './assets/colonist/icon_player.svg';
import iconHamburger from './assets/colonist/icon_hamburger.svg';
import iconPlayers from './assets/colonist/icon_players.svg';
import iconRefresh from './assets/colonist/icon_refresh.svg';
import iconLanguage from './assets/colonist/icon_language.svg';
import landingMap from './assets/colonist/landing_page_map.png';
import overlay from './assets/colonist/landing_page_background_overlay.png';
import overlayMobile from './assets/colonist/landing_page_background_overlay_mobile.png';
import roadBlue from './assets/colonist/road_blue.svg';
import roadRed from './assets/colonist/road_red.svg';
import roadGreen from './assets/colonist/road_green.svg';
import roadOrange from './assets/colonist/road_orange.svg';
import settlementBlue from './assets/colonist/settlement_blue.svg';
import settlementRed from './assets/colonist/settlement_red.svg';
import settlementGreen from './assets/colonist/settlement_green.svg';
import settlementOrange from './assets/colonist/settlement_orange.svg';
import iconBrick from './assets/resources/brick.svg';
import iconLumber from './assets/resources/lumber.svg';
import iconWool from './assets/resources/wool.svg';
import iconGrain from './assets/resources/grain.svg';
import iconOre from './assets/resources/ore.svg';
import iconDevCard from './assets/resources/devcard.svg';
import iconCardBack from './assets/resources/card_back.svg';

const RESOURCE_COLORS = {
  brick: '#c46a44',
  lumber: '#4a6d4a',
  wool: '#8cc071',
  grain: '#e2c065',
  ore: '#7a7c83',
  desert: '#d8c18f',
};

const RESOURCE_ORDER = ['brick', 'lumber', 'wool', 'grain', 'ore'];

const RESOURCE_ICONS = {
  brick: iconBrick,
  lumber: iconLumber,
  wool: iconWool,
  grain: iconGrain,
  ore: iconOre,
};

const RESOURCE_LABELS = {
  brick: 'Brick',
  lumber: 'Lumber',
  wool: 'Wool',
  grain: 'Grain',
  ore: 'Ore',
};

const SIDEBAR_ITEMS = [
  { key: 'leaderboards', label: 'Leaderboards', icon: iconTrophy, to: '/analytics' },
  { key: 'lobby', label: 'Lobby', icon: iconFriends, to: '/' },
  { key: 'play', label: 'Play', icon: iconPlay, to: '/' },
  { key: 'store', label: 'Store', icon: iconCoin, to: '/store' },
  { key: 'profile', label: 'Profile', icon: iconPlayer, to: '/profile' },
];

function isActiveItem(key, path) {
  if (key === 'play') {
    return path.startsWith('/game');
  }
  if (key === 'leaderboards') {
    return path.startsWith('/analytics');
  }
  if (key === 'store') {
    return path.startsWith('/store') || path.startsWith('/replays');
  }
  if (key === 'profile') {
    return path.startsWith('/profile');
  }
  if (key === 'lobby') {
    return path === '/' || path.startsWith('/lobby');
  }
  return false;
}

function Sidebar() {
  const location = useLocation();
  return (
    <aside className="web-sidebar">
      <div className="web-sidebar-logo">
        <Link to="/"><img src={logo} alt="colonist logo" /></Link>
      </div>
      <nav className="web-sidebar-nav">
        {SIDEBAR_ITEMS.map((item) => (
          <Link
            key={item.key}
            to={item.to}
            className={`web-sidebar-nav-item ${isActiveItem(item.key, location.pathname) ? 'active' : ''}`}
          >
            <img src={item.icon} alt={item.label} />
            <span>{item.label}</span>
          </Link>
        ))}
      </nav>
      <div className="web-sidebar-footer">
        <div className="language-button">
          <img src={iconLanguage} alt="Language" />
          <div>en</div>
        </div>
      </div>
    </aside>
  );
}

function Header({ user, onLogout }) {
  const navigate = useNavigate();
  return (
    <header className="web-header">
      <div className="web-header-mobile-left">
        <div className="web-header-burger-left">
          <img src={iconHamburger} alt="Menu" />
        </div>
        <div className="web-header-logo">
          <Link to="/"><img src={logo} alt="colonist logo" /></Link>
        </div>
      </div>
      <div className="web-header-left">
        <div className="web-header-profile">
          {user ? (
            <div className="web-header-profile-loggedin">
              <div className="web-header-profile-avatar">
                <img className="profile-icon" src={iconPlayers} alt="Player Icon" />
              </div>
              <div>
                <p className="web-header-username">{user}</p>
                <p className="web-header-karma">Karma 0</p>
              </div>
            </div>
          ) : (
            <div className="web-header-visitor-container">
              <p className="web-header-username">Guest</p>
              <button className="web-header-login-button" onClick={() => navigate('/login')}>
                Login
              </button>
            </div>
          )}
        </div>
        <div className="header-coins">
          <img src={iconCoin} alt="Coins" />
          <h3>0</h3>
        </div>
      </div>
      <div className="web-header-right">
        {user && (
          <button className="btn_general btn_general_secondary header-logout-button" onClick={onLogout}>
            Logout
          </button>
        )}
        <div className="web-header-burger">
          <img src={iconHamburger} alt="Menu" />
        </div>
      </div>
    </header>
  );
}

function PageShell({ children, side, hideAds }) {
  return (
    <div className={`web-layout-content-with-ads${hideAds ? ' content-wide' : ''}`}>
      <div className="web-layout-main-content">{children}</div>
      {!hideAds && <div className="web-layout-ad-space">{side}</div>}
    </div>
  );
}

function AuthPanel({ onAuth }) {
  const [login, setLogin] = useState({ username: '', password: '' });
  const [register, setRegister] = useState({ username: '', password: '' });
  const navigate = useNavigate();

  async function submitLogin() {
    try {
      const data = await apiFetch('/api/auth/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(login),
      });
      setToken(data.token, data.username);
      onAuth(data.username);
      navigate('/');
    } catch (err) {
      window.alert(err.message);
    }
  }

  async function submitRegister() {
    try {
      const data = await apiFetch('/api/auth/register', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(register),
      });
      setToken(data.token, data.username);
      onAuth(data.username);
      navigate('/');
    } catch (err) {
      window.alert(err.message);
    }
  }

  return (
    <div className="auth-panel">
      <div className="auth-card">
        <h3>Login</h3>
        <input
          className="input_general"
          placeholder="Username"
          value={login.username}
          onChange={(e) => setLogin({ ...login, username: e.target.value })}
        />
        <input
          className="input_general"
          type="password"
          placeholder="Password"
          value={login.password}
          onChange={(e) => setLogin({ ...login, password: e.target.value })}
        />
        <button className="btn_general btn_general_orange" onClick={submitLogin}>
          Enter Lobby
        </button>
      </div>
      <div className="auth-card">
        <h3>Create Account</h3>
        <input
          className="input_general"
          placeholder="Username"
          value={register.username}
          onChange={(e) => setRegister({ ...register, username: e.target.value })}
        />
        <input
          className="input_general"
          type="password"
          placeholder="Password"
          value={register.password}
          onChange={(e) => setRegister({ ...register, password: e.target.value })}
        />
        <button className="btn_general btn_general_secondary" onClick={submitRegister}>
          Register
        </button>
      </div>
    </div>
  );
}

function LandingPage({ onAuth }) {
  return (
    <div className="scene_landing_page_container">
      <div className="landing_page_left_side">
        <div className="landing_page_map_container">
          <img className="landing_page_map" src={landingMap} alt="Catan map" />
          <div className="landing_page_map_animation_container">
            <img className="landing_page_map_road landing_page_map_road_1" src={roadBlue} alt="Road" />
            <img className="landing_page_map_road landing_page_map_road_2" src={roadBlue} alt="Road" />
            <img className="landing_page_map_road landing_page_map_road_3" src={roadRed} alt="Road" />
            <img className="landing_page_map_road landing_page_map_road_4" src={roadRed} alt="Road" />
            <img className="landing_page_map_road landing_page_map_road_5" src={roadGreen} alt="Road" />
            <img className="landing_page_map_road landing_page_map_road_6" src={roadGreen} alt="Road" />
            <img className="landing_page_map_road landing_page_map_road_7" src={roadOrange} alt="Road" />
            <img className="landing_page_map_road landing_page_map_road_8" src={roadOrange} alt="Road" />
            <img className="landing_page_map_settlement_1" src={settlementBlue} alt="Settlement" />
            <img className="landing_page_map_settlement_2" src={settlementBlue} alt="Settlement" />
            <img className="landing_page_map_settlement_3" src={settlementRed} alt="Settlement" />
            <img className="landing_page_map_settlement_4" src={settlementRed} alt="Settlement" />
            <img className="landing_page_map_settlement_5" src={settlementGreen} alt="Settlement" />
            <img className="landing_page_map_settlement_6" src={settlementGreen} alt="Settlement" />
            <img className="landing_page_map_settlement_7" src={settlementOrange} alt="Settlement" />
            <img className="landing_page_map_settlement_8" src={settlementOrange} alt="Settlement" />
          </div>
        </div>
      </div>
      <div className="landing_page_right_side">
        <img className="landing_page_logo" src={logo} alt="colonist logo" />
        <div className="landing_page_right_side_content">
          <h1>#1 Catan AI Arena</h1>
          <div className="landing_page_social_proof">
            <span className="landing_page_social_proof_item">
              <b>4000</b> online
            </span>
            <span className="landing_page_social_proof_item">
              <b>180000</b> games today
            </span>
          </div>
          <div className="button_cta_landingpage_container">
            <div className="button_cta_landingpage_main">Play with Friends</div>
            <div className="button_cta_landingpage_sub">Play Online</div>
            <div className="button_cta_landingpage_sub_mobile">Continue on Web</div>
          </div>
        </div>
        <AuthPanel onAuth={onAuth} />
      </div>
      <img className="landing-page-background-overlay" src={overlay} alt="" />
      <img className="landing-page-background-overlay-mobile" src={overlayMobile} alt="" />
    </div>
  );
}

function LoginPage({ onAuth }) {
  return (
    <PageShell hideAds>
      <LandingPage onAuth={onAuth} />
    </PageShell>
  );
}

function LobbyPage() {
  const [games, setGames] = useState([]);
  const [models, setModels] = useState([]);
  const [stats, setStats] = useState(null);
  const [create, setCreate] = useState({ name: '', max_players: 4 });
  const navigate = useNavigate();

  async function load() {
    const [lobby, modelList, statsData] = await Promise.all([
      apiFetch('/api/lobby'),
      apiFetch('/api/models'),
      apiFetch('/api/stats'),
    ]);
    setGames(lobby.games || []);
    setModels(modelList.models || []);
    setStats(statsData);
  }

  useEffect(() => {
    load().catch(console.error);
  }, []);

  async function createGame() {
    const payload = {
      ...create,
      name: create.name || 'Room',
    };
    await apiFetch('/api/games', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
    });
    await load();
  }

  async function joinGame(id) {
    await apiFetch(`/api/games/${id}/join`, { method: 'POST' });
    navigate(`/game/${id}`);
  }

  async function joinById() {
    const id = window.prompt('Game id');
    if (!id) return;
    await joinGame(id);
  }

  async function addAi(id) {
    const type = window.prompt('AI type: random or model?', 'random');
    if (!type) return;
    const payload = { ai_type: type };
    if (type === 'model') {
      payload.model_name = window.prompt(`Model name: ${models.join(', ')}`);
    }
    await apiFetch(`/api/games/${id}/add-ai`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
    });
    await load();
  }

  async function startGame(id) {
    await apiFetch(`/api/games/${id}/start`, { method: 'POST' });
    navigate(`/game/${id}`);
  }

  const side = (
    <div className="side-stack">
      <div className="panel-card">
        <h3>Create Room</h3>
        <div className="form-stack">
          <input
            className="input_general"
            placeholder="Game name"
            value={create.name}
            onChange={(e) => setCreate({ ...create, name: e.target.value })}
          />
          <select
            className="input_general"
            value={create.max_players}
            onChange={(e) => setCreate({ ...create, max_players: parseInt(e.target.value, 10) })}
          >
            <option value={3}>3 players</option>
            <option value={4}>4 players</option>
          </select>
          <button className="btn_general btn_general_orange" onClick={createGame}>
            Create Room
          </button>
        </div>
      </div>
      <div className="panel-card">
        <h3>Stats</h3>
        {stats ? (
          <div className="stat-grid">
            <div>
              <strong>{stats.total_games}</strong>
              <span>Total games</span>
            </div>
            <div>
              <strong>{stats.finished_games}</strong>
              <span>Finished</span>
            </div>
            <div>
              <strong>{stats.user_games}</strong>
              <span>Your games</span>
            </div>
            <div>
              <strong>{stats.user_wins}</strong>
              <span>Your wins</span>
            </div>
            <div>
              <strong>{Number(stats.avg_turns || 0).toFixed(1)}</strong>
              <span>Avg turns</span>
            </div>
          </div>
        ) : (
          <div className="muted">Loading stats...</div>
        )}
      </div>
      <div className="panel-card">
        <h3>AI Models</h3>
        <div className="model-grid">
          {models.map((model) => (
            <span key={model} className="model-pill">
              {model}
            </span>
          ))}
          {models.length === 0 && <div className="muted">No models found.</div>}
        </div>
      </div>
    </div>
  );

  return (
    <PageShell side={side}>
      <div className="homepage-lobby-container">
        <div className="m-lobby-container">
          <div className="scene_lobby_mid_tabs">
            <div className="scene_lobby_mid_tabs_active">
              <div>Rooms</div>
            </div>
            <div className="scene_lobby_mid_tabs_inactive">
              <div>Spectate</div>
            </div>
          </div>
          <div className="lobby_center_tables_container">
            <div className="lobby-table">
              <table className="lobby-table-table">
                <thead>
                  <tr>
                    <th className="mode">
                      <div>Mode</div>
                    </th>
                    <th className="map">
                      <div>Map</div>
                    </th>
                    <th className="speed">
                      <div>Turn Timer</div>
                    </th>
                    <th className="refresh">
                      <img
                        src={iconRefresh}
                        alt="Refresh"
                        className="refresh-icon"
                        onClick={load}
                      />
                    </th>
                  </tr>
                </thead>
                <tbody>
                  {games.length === 0 && (
                    <tr>
                      <td colSpan={4} className="muted">
                        No active rooms.
                      </td>
                    </tr>
                  )}
                  {games.map((game) => (
                    <tr key={game.id}>
                      <td>
                        <div className="lobby-room-title">{game.name || 'Room'}</div>
                        <div className="lobby-room-sub">Classic - {game.status}</div>
                      </td>
                      <td>
                        <div className="lobby-room-sub">Base Map</div>
                        <div className="lobby-room-players">
                          {game.players.map((slot) => (
                            <span key={slot.slot_id} className="player-pill">
                              {slot.name || 'Open'}
                            </span>
                          ))}
                        </div>
                      </td>
                      <td>
                        <div className="lobby-room-sub">No timer</div>
                        <div>{game.max_players} players</div>
                      </td>
                      <td>
                        <div className="lobby-room-actions">
                          <button className="btn_general btn_general_secondary" onClick={() => joinGame(game.id)}>
                            Join
                          </button>
                          <button className="btn_general btn_general_secondary" onClick={() => addAi(game.id)}>
                            AI
                          </button>
                          <button className="btn_general btn_general_orange" onClick={() => startGame(game.id)}>
                            Start
                          </button>
                        </div>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
          <div className="m-lobby-buttons-container">
            <div className="m-lobby-create-room-button" onClick={createGame}>
              Create Room
            </div>
            <div className="m-lobby-join-room-button" onClick={joinById}>
              Join Room
            </div>
          </div>
        </div>
      </div>
    </PageShell>
  );
}

function cubeToPixel(coord, scale) {
  const [x, , z] = coord;
  const sqrt3 = Math.sqrt(3);
  return {
    x: scale * (sqrt3 * x + (sqrt3 / 2) * z),
    y: scale * (1.5 * z),
  };
}

function hexCorners(cx, cy, size) {
  const points = [];
  for (let i = 0; i < 6; i += 1) {
    const angle = (Math.PI / 180) * (60 * i - 30);
    points.push([cx + size * Math.cos(angle), cy + size * Math.sin(angle)]);
  }
  return points;
}

function Board({
  board,
  game,
  highlightCorners = [],
  highlightEdges = [],
  highlightHexes = [],
  selectedCorner,
  selectedEdges = [],
  selectedHex,
  onCornerClick,
  onEdgeClick,
  onHexClick,
}) {
  if (!board || !game) return null;
  const size = 46;
  const cornerScale = size / 3;
  const hexes = Object.entries(board.hexes || {}).map(([id, hex]) => ({
    id: Number(id),
    ...hex,
  }));
  const corners = board.corners || {};
  const edges = Object.entries(board.edges || {}).map(([id, edge]) => ({
    id: Number(id),
    ...edge,
  }));

  const hexPositions = hexes.map((hex) => ({ ...hex, pos: cubeToPixel(hex.coord, size) }));
  const cornerPositions = {};
  Object.entries(corners).forEach(([id, corner]) => {
    cornerPositions[id] = { ...corner, pos: cubeToPixel(corner.coord, cornerScale) };
  });

  const allPositions = [
    ...hexPositions.map((h) => h.pos),
    ...Object.values(cornerPositions).map((c) => c.pos),
  ];
  const minX = Math.min(...allPositions.map((p) => p.x));
  const maxX = Math.max(...allPositions.map((p) => p.x));
  const minY = Math.min(...allPositions.map((p) => p.y));
  const maxY = Math.max(...allPositions.map((p) => p.y));
  const padding = 80;
  const viewBox = `${minX - padding} ${minY - padding} ${maxX - minX + padding * 2} ${maxY - minY + padding * 2}`;

  const playerColors = {};
  Object.entries(game.players || {}).forEach(([name, pdata]) => {
    playerColors[name] = pdata.color || '#333';
  });

  const cornerSet = new Set(highlightCorners.map((v) => Number(v)));
  const edgeSet = new Set(highlightEdges.map((v) => Number(v)));
  const hexSet = new Set(highlightHexes.map((v) => Number(v)));
  const selectedEdgeSet = new Set(selectedEdges.map((v) => Number(v)));

  return (
    <svg className="board-svg" viewBox={viewBox}>
      {hexPositions.map((hex) => {
        const points = hexCorners(hex.pos.x, hex.pos.y, size - 4)
          .map((pt) => pt.join(','))
          .join(' ');
        const fill = RESOURCE_COLORS[hex.resource] || '#e0c89a';
        const number = hex.number || '';
        const highlight = hexSet.has(hex.id);
        const selected = selectedHex === hex.id;
        return (
          <g key={`hex-${hex.id}`} className="hex-group">
            <polygon
              points={points}
              fill={fill}
              className={`hex ${highlight ? 'hex--highlight' : ''} ${selected ? 'hex--selected' : ''}`}
              stroke="rgba(0,0,0,0.2)"
              strokeWidth="2"
              onClick={() => highlight && onHexClick && onHexClick(hex.id)}
            />
            {number ? (
              <text
                x={hex.pos.x}
                y={hex.pos.y}
                textAnchor="middle"
                fontSize="16"
                fill="#3a2a1a"
                fontWeight="600"
              >
                {number}
              </text>
            ) : null}
            {hex.robber ? (
              <circle cx={hex.pos.x} cy={hex.pos.y + 20} r="8" fill="rgba(0,0,0,0.35)" />
            ) : null}
          </g>
        );
      })}
      {edges.map((edge) => {
        const a = cornerPositions[edge.a];
        const b = cornerPositions[edge.b];
        if (!a || !b) return null;
        const highlight = edgeSet.has(edge.id);
        const selected = selectedEdgeSet.has(edge.id);
        return (
          <g key={`edge-${edge.id}`}>
            {edge.owner ? (
              <line
                x1={a.pos.x}
                y1={a.pos.y}
                x2={b.pos.x}
                y2={b.pos.y}
                stroke={playerColors[edge.owner] || '#222'}
                strokeWidth="6"
                strokeLinecap="round"
              />
            ) : null}
            <line
              x1={a.pos.x}
              y1={a.pos.y}
              x2={b.pos.x}
              y2={b.pos.y}
              className={`edge-hit ${highlight ? 'edge-hit--active' : ''} ${selected ? 'edge-hit--selected' : ''}`}
              strokeWidth="12"
              strokeLinecap="round"
              onClick={() => highlight && onEdgeClick && onEdgeClick(edge.id)}
            />
          </g>
        );
      })}
      {Object.entries(cornerPositions).map(([label, corner]) => {
        const cornerId = Number(label);
        const radius = corner.building === 'city' ? 10 : 7;
        const highlight = cornerSet.has(cornerId);
        const selected = selectedCorner === cornerId;
        return (
          <g key={`corner-${label}`}>
            {corner.owner ? (
              <circle
                cx={corner.pos.x}
                cy={corner.pos.y}
                r={radius}
                fill={playerColors[corner.owner] || '#222'}
                stroke="#fff"
                strokeWidth="2"
              />
            ) : null}
            <circle
              cx={corner.pos.x}
              cy={corner.pos.y}
              r="10"
              className={`corner-hit ${highlight ? 'corner-hit--active' : ''} ${selected ? 'corner-hit--selected' : ''}`}
              onClick={() => highlight && onCornerClick && onCornerClick(cornerId)}
            />
          </g>
        );
      })}
    </svg>
  );
}

function emptyResourceMap() {
  return Object.fromEntries(RESOURCE_ORDER.map((res) => [res, 0]));
}

function GamePage() {
  const { gameId } = useParams();
  const [state, setState] = useState(null);
  const [legalActions, setLegalActions] = useState([]);
  const [uiMode, setUiMode] = useState(null);
  const [selectedCorner, setSelectedCorner] = useState(null);
  const [selectedEdges, setSelectedEdges] = useState([]);
  const [selectedHex, setSelectedHex] = useState(null);
  const [selectedVictim, setSelectedVictim] = useState('');
  const [tradeOpen, setTradeOpen] = useState(false);
  const [tradeMode, setTradeMode] = useState('player');
  const [tradeOffer, setTradeOffer] = useState(() => ({
    offer: emptyResourceMap(),
    request: emptyResourceMap(),
    to_player: '',
  }));
  const [bankTrade, setBankTrade] = useState({ give: 'brick', receive: 'ore' });
  const [discardCards, setDiscardCards] = useState(() => emptyResourceMap());
  const [yearPick, setYearPick] = useState({ first: 'brick', second: 'brick' });
  const [monopolyPick, setMonopolyPick] = useState('brick');

  useEffect(() => {
    let socket;
    async function load() {
      const data = await apiFetch(`/api/games/${gameId}`);
      setState(data);
      setLegalActions(data.legal_actions || []);
      socket = new WebSocket(wsUrl(`/ws/games/${gameId}`));
      socket.onmessage = (event) => {
        const msg = JSON.parse(event.data);
        if (msg.type === 'state') {
          setState(msg.data);
          setLegalActions(msg.data.legal_actions || []);
        }
      };
    }
    load().catch(console.error);
    return () => socket && socket.close();
  }, [gameId]);

  const username = getUsername();
  const currentPlayer = state?.game?.current_player;
  const isMyTurn = currentPlayer === username;
  const myPlayer = state?.game?.players?.[username];
  const myResources = myPlayer?.resources || {};

  const actionsByType = useMemo(() => {
    const grouped = {};
    (legalActions || []).forEach((action) => {
      if (!grouped[action.type]) {
        grouped[action.type] = [];
      }
      grouped[action.type].push(action);
    });
    return grouped;
  }, [legalActions]);

  const setupActions = actionsByType.place_initial || [];
  const setupCornerMap = useMemo(() => {
    const map = {};
    setupActions.forEach((action) => {
      const corner = Number(action.payload.corner);
      const road = Number(action.payload.road);
      if (!map[corner]) {
        map[corner] = [];
      }
      map[corner].push(road);
    });
    return map;
  }, [setupActions]);

  const buildRoadEdges = useMemo(
    () => (actionsByType.build_road || []).map((action) => Number(action.payload.edge)),
    [actionsByType],
  );
  const buildSettlementCorners = useMemo(
    () => (actionsByType.build_settlement || []).map((action) => Number(action.payload.corner)),
    [actionsByType],
  );
  const buildCityCorners = useMemo(
    () => (actionsByType.build_city || []).map((action) => Number(action.payload.corner)),
    [actionsByType],
  );
  const roadBuildingEdges = useMemo(() => {
    const action = (actionsByType.play_road_building || [])[0];
    const edges = action?.payload?.edges || [];
    return edges.map((edge) => Number(edge));
  }, [actionsByType]);
  const robberOptions = useMemo(() => {
    const action = uiMode === 'play_knight'
      ? (actionsByType.play_knight || [])[0]
      : (actionsByType.move_robber || [])[0];
    return action?.payload?.options || [];
  }, [actionsByType, uiMode]);

  const bankTradeMap = useMemo(() => {
    const map = {};
    (actionsByType.trade_bank || []).forEach((action) => {
      const give = action.payload.give;
      const receive = action.payload.receive;
      const ratio = action.payload.ratio || 4;
      if (!map[give]) {
        map[give] = {};
      }
      map[give][receive] = ratio;
    });
    return map;
  }, [actionsByType]);

  const canRoll = (actionsByType.roll || []).length > 0;
  const canEndTurn = (actionsByType.end_turn || []).length > 0;
  const canBuyDev = (actionsByType.buy_development || []).length > 0;
  const canTradeBank = (actionsByType.trade_bank || []).length > 0;
  const canPlayKnight = (actionsByType.play_knight || []).length > 0;
  const canPlayRoadBuilding = (actionsByType.play_road_building || []).length > 0;
  const canPlayYearOfPlenty = (actionsByType.play_year_of_plenty || []).length > 0;
  const canPlayMonopoly = (actionsByType.play_monopoly || []).length > 0;

  useEffect(() => {
    if ((actionsByType.discard || []).length > 0) {
      setUiMode('discard');
      setDiscardCards(emptyResourceMap());
      return;
    }
    if ((actionsByType.move_robber || []).length > 0 && uiMode !== 'play_knight') {
      setUiMode('move_robber');
      return;
    }
    if ((actionsByType.place_initial || []).length > 0) {
      setUiMode('place_initial');
      return;
    }
    if (['discard', 'move_robber', 'place_initial'].includes(uiMode)) {
      setUiMode(null);
    }
  }, [actionsByType, uiMode]);

  function resetSelection() {
    setSelectedCorner(null);
    setSelectedEdges([]);
    setSelectedHex(null);
    setSelectedVictim('');
  }

  function startMode(mode) {
    setUiMode(mode);
    resetSelection();
  }

  async function sendAction(type, payload = {}) {
    try {
      await apiFetch(`/api/games/${gameId}/action`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ type, payload }),
      });
    } catch (err) {
      window.alert(err.message);
    }
  }

  async function submitTradeOffer() {
    const offer = Object.fromEntries(
      Object.entries(tradeOffer.offer).filter(([, amt]) => amt > 0),
    );
    const request = Object.fromEntries(
      Object.entries(tradeOffer.request).filter(([, amt]) => amt > 0),
    );
    if (!Object.keys(offer).length || !Object.keys(request).length) {
      return;
    }
    await apiFetch(`/api/games/${gameId}/trade/offer`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        from_player: username,
        to_player: tradeOffer.to_player || null,
        offer,
        request,
      }),
    });
    setTradeOffer({ offer: emptyResourceMap(), request: emptyResourceMap(), to_player: '' });
    setTradeOpen(false);
  }

  async function respondTrade(tradeId, accept) {
    await apiFetch(`/api/games/${gameId}/trade/${tradeId}/respond`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ player: username, accept }),
    });
  }

  function handleCornerClick(label) {
    if (!isMyTurn) return;
    const corner = Number(label);
    if (uiMode === 'place_initial') {
      if (setupCornerMap[corner]) {
        setSelectedCorner(corner);
      }
      return;
    }
    if (uiMode === 'build_settlement' && buildSettlementCorners.includes(corner)) {
      sendAction('build_settlement', { corner });
      setUiMode(null);
      resetSelection();
      return;
    }
    if (uiMode === 'build_city' && buildCityCorners.includes(corner)) {
      sendAction('build_city', { corner });
      setUiMode(null);
      resetSelection();
    }
  }

  function handleEdgeClick(label) {
    if (!isMyTurn) return;
    const edge = Number(label);
    if (uiMode === 'build_road' && buildRoadEdges.includes(edge)) {
      sendAction('build_road', { edge });
      setUiMode(null);
      resetSelection();
      return;
    }
    if (uiMode === 'place_initial' && selectedCorner) {
      const options = setupCornerMap[selectedCorner] || [];
      if (options.includes(edge)) {
        sendAction('place_initial', { corner: selectedCorner, road: edge });
        setUiMode(null);
        resetSelection();
      }
      return;
    }
    if (uiMode === 'play_road_building' && roadBuildingEdges.includes(edge)) {
      const updated = selectedEdges.includes(edge)
        ? selectedEdges.filter((id) => id !== edge)
        : [...selectedEdges, edge].slice(0, 2);
      setSelectedEdges(updated);
      if (updated.length === 2) {
        sendAction('play_road_building', { edges: updated });
        setUiMode(null);
        resetSelection();
      }
    }
  }

  function handleHexClick(hexId) {
    if (!isMyTurn) return;
    if (!['move_robber', 'play_knight'].includes(uiMode)) return;
    const option = robberOptions.find((opt) => opt.hex === hexId);
    if (!option) return;
    setSelectedHex(hexId);
    if (!option.victims || option.victims.length <= 1) {
      const victim = option.victims?.[0];
      const actionType = uiMode === 'play_knight' ? 'play_knight' : 'move_robber';
      sendAction(actionType, { hex: hexId, victim });
      setUiMode(null);
      resetSelection();
    } else {
      setSelectedVictim('');
    }
  }

  function confirmRobberSelection() {
    if (!selectedHex) return;
    const option = robberOptions.find((opt) => opt.hex === selectedHex);
    if (!option) return;
    if (option.victims?.length && !selectedVictim) return;
    const actionType = uiMode === 'play_knight' ? 'play_knight' : 'move_robber';
    sendAction(actionType, { hex: selectedHex, victim: selectedVictim || undefined });
    setUiMode(null);
    resetSelection();
  }

  function updateTradeAmount(group, resource, delta, max) {
    setTradeOffer((prev) => {
      const next = { ...prev, [group]: { ...prev[group] } };
      const current = next[group][resource] || 0;
      const updated = Math.max(0, Math.min(max, current + delta));
      next[group][resource] = updated;
      return next;
    });
  }

  function updateDiscard(resource, delta, max) {
    setDiscardCards((prev) => {
      const next = { ...prev };
      const current = next[resource] || 0;
      next[resource] = Math.max(0, Math.min(max, current + delta));
      return next;
    });
  }

  const discardAction = (actionsByType.discard || [])[0];
  const discardRequired = discardAction?.payload?.required || 0;
  const discardResources = discardAction?.payload?.resources || {};
  const discardTotal = Object.values(discardCards).reduce((sum, value) => sum + value, 0);
  const canSubmitDiscard = discardRequired > 0 && discardTotal === discardRequired;

  const highlightCorners = useMemo(() => {
    if (uiMode === 'build_settlement') return buildSettlementCorners;
    if (uiMode === 'build_city') return buildCityCorners;
    if (uiMode === 'place_initial') {
      if (selectedCorner) return [];
      return Object.keys(setupCornerMap).map((key) => Number(key));
    }
    return [];
  }, [uiMode, buildSettlementCorners, buildCityCorners, setupCornerMap, selectedCorner]);

  const highlightEdges = useMemo(() => {
    if (uiMode === 'build_road') return buildRoadEdges;
    if (uiMode === 'play_road_building') return roadBuildingEdges;
    if (uiMode === 'place_initial' && selectedCorner) {
      return setupCornerMap[selectedCorner] || [];
    }
    return [];
  }, [uiMode, buildRoadEdges, roadBuildingEdges, setupCornerMap, selectedCorner]);

  const highlightHexes = useMemo(() => {
    if (uiMode === 'move_robber' || uiMode === 'play_knight') {
      return robberOptions.map((opt) => opt.hex);
    }
    return [];
  }, [uiMode, robberOptions]);

  const robberVictims = useMemo(() => {
    if (!selectedHex) return [];
    const option = robberOptions.find((opt) => opt.hex === selectedHex);
    return option?.victims || [];
  }, [robberOptions, selectedHex]);

  const bankGiveOptions = Object.keys(bankTradeMap);
  const bankReceiveOptions = bankTrade.give ? Object.keys(bankTradeMap[bankTrade.give] || {}) : [];
  const bankRatio = bankTradeMap[bankTrade.give]?.[bankTrade.receive] || null;

  const tradeDisabled = !isMyTurn || canRoll || uiMode === 'discard' || uiMode === 'move_robber';
  const actionMessage = {
    build_road: 'Select a road to build.',
    build_settlement: 'Select a settlement spot.',
    build_city: 'Select a settlement to upgrade.',
    place_initial: selectedCorner ? 'Select a connected road.' : 'Place your initial settlement.',
    play_road_building: selectedEdges.length ? 'Select the second road.' : 'Select two roads.',
    move_robber: 'Move the robber.',
    play_knight: 'Move the robber.',
  }[uiMode];

  if (!state) {
    return (
      <PageShell hideAds>
        <div className="screen">Loading...</div>
      </PageShell>
    );
  }

  return (
    <PageShell hideAds>
      <div className="game-shell">
        <div className="game-topbar">
          {(state.game && Object.entries(state.game.players).map(([name, pdata]) => {
            const resourceInfo = pdata.resources || {};
            const cardCount = resourceInfo.hidden !== undefined
              ? resourceInfo.hidden
              : Object.values(resourceInfo).reduce((sum, value) => sum + value, 0);
            const devCount = pdata.dev_cards ?? 0;
            return (
              <div key={name} className={`player-chip ${currentPlayer === name ? 'player-chip--active' : ''}`}>
                <span className="player-color" style={{ background: pdata.color || '#333' }} />
                <div className="player-chip-body">
                  <div className="player-name">{name}</div>
                  <div className="player-meta">VP {pdata.victory_points}</div>
                </div>
                <div className="player-hand">
                  <div className="card-stack">
                    <img className="card-back" src={iconCardBack} alt="Resource cards" />
                    <img className="card-back card-back--offset" src={iconCardBack} alt="" />
                    <span className="card-count">{cardCount}</span>
                  </div>
                  <div className="card-stack card-stack--dev">
                    <img className="card-back" src={iconDevCard} alt="Dev cards" />
                    <span className="card-count">{devCount}</span>
                  </div>
                </div>
              </div>
            );
          })) || null}
        </div>
        <div className="game-main">
          <div className="game-board-area">
            <Board
              board={state.board}
              game={state.game}
              highlightCorners={highlightCorners}
              highlightEdges={highlightEdges}
              highlightHexes={highlightHexes}
              selectedCorner={selectedCorner}
              selectedEdges={selectedEdges}
              selectedHex={selectedHex}
              onCornerClick={handleCornerClick}
              onEdgeClick={handleEdgeClick}
              onHexClick={handleHexClick}
            />
          </div>
          <aside className="game-side">
            <div className="panel-card trade-panel">
              <div className="trade-header">
                <h3>Trades</h3>
                <button
                  className="btn_general btn_general_secondary"
                  onClick={() => setTradeOpen(true)}
                  disabled={tradeDisabled}
                >
                  New Trade
                </button>
              </div>
              <div className="trade-offer-list">
                {state.pending_trades?.length === 0 && <div className="muted">No offers.</div>}
                {state.pending_trades?.map((offer) => (
                  <div key={offer.id} className="trade-offer">
                    <div className="trade-offer-meta">
                      {offer.from_player} → {offer.to_player || 'any'}
                    </div>
                    <div className="trade-offer-row">
                      <div className="trade-offer-label">Offer</div>
                      <div className="trade-chip-row">
                        {Object.entries(offer.offer).map(([res, amt]) => (
                          <span key={`${offer.id}-offer-${res}`} className={`trade-chip trade-chip--${res}`}>
                            <img className="trade-chip-icon" src={RESOURCE_ICONS[res]} alt="" />
                            <span>{amt}</span>
                          </span>
                        ))}
                      </div>
                    </div>
                    <div className="trade-offer-row">
                      <div className="trade-offer-label">Request</div>
                      <div className="trade-chip-row">
                        {Object.entries(offer.request).map(([res, amt]) => (
                          <span key={`${offer.id}-req-${res}`} className={`trade-chip trade-chip--${res}`}>
                            <img className="trade-chip-icon" src={RESOURCE_ICONS[res]} alt="" />
                            <span>{amt}</span>
                          </span>
                        ))}
                      </div>
                    </div>
                    {(offer.to_player === username || offer.to_player === null) ? (
                      <div className="trade-actions">
                        <button className="btn_general btn_general_orange" onClick={() => respondTrade(offer.id, true)}>
                          Accept
                        </button>
                        <button className="btn_general btn_general_secondary" onClick={() => respondTrade(offer.id, false)}>
                          Decline
                        </button>
                      </div>
                    ) : null}
                  </div>
                ))}
              </div>
            </div>
            <div className="panel-card">
              <h3>Status</h3>
              <div className="panel-stack">
                <div>Phase: {state.game?.phase || '-'}</div>
                <div>Current: {state.game?.current_player || '-'}</div>
                <div>Last roll: {state.game?.last_roll || '-'}</div>
                <div>Winner: {state.game?.winner || '-'}</div>
              </div>
            </div>
            <div className="panel-card">
              <h3>History</h3>
              <div className="history-list">
                {(state.history || []).slice().reverse().map((entry) => (
                  <div key={entry.idx} className="muted">{entry.actor}: {entry.action.type}</div>
                ))}
              </div>
            </div>
          </aside>
        </div>
        <div className="game-bottom">
          <div className="resource-bar">
            {RESOURCE_ORDER.map((res) => (
              <div key={res} className="resource-card" style={{ background: RESOURCE_COLORS[res] }}>
                <img className="resource-icon" src={RESOURCE_ICONS[res]} alt={RESOURCE_LABELS[res]} />
                <span className="resource-card-label">{RESOURCE_LABELS[res]}</span>
                <strong className="resource-card-count">{myResources?.[res] || 0}</strong>
              </div>
            ))}
            <div className="resource-card resource-card--dev">
              <img className="resource-icon" src={iconDevCard} alt="Dev Cards" />
              <span className="resource-card-label">Dev Cards</span>
              <strong className="resource-card-count">{myPlayer?.dev_cards ?? 0}</strong>
            </div>
          </div>
          {actionMessage && (
            <div className="action-banner">
              <span>{actionMessage}</span>
              {uiMode && !['discard'].includes(uiMode) && (
                <button className="btn_general btn_general_secondary" onClick={() => setUiMode(null)}>
                  Cancel
                </button>
              )}
            </div>
          )}
          {robberVictims.length > 1 && (
            <div className="robber-panel">
              <select
                className="input_general"
                value={selectedVictim}
                onChange={(e) => setSelectedVictim(e.target.value)}
              >
                <option value="">Select victim</option>
                {robberVictims.map((victim) => (
                  <option key={victim} value={victim}>{victim}</option>
                ))}
              </select>
              <button className="btn_general btn_general_orange" onClick={confirmRobberSelection}>
                Steal
              </button>
            </div>
          )}
          <div className="action-bar">
            {canRoll && (
              <button className="action-button action-button--primary" onClick={() => sendAction('roll', {})}>
                Roll Dice
              </button>
            )}
            <button
              className={`action-button ${uiMode === 'build_road' ? 'action-button--active' : ''}`}
              onClick={() => startMode('build_road')}
              disabled={!isMyTurn || buildRoadEdges.length === 0}
            >
              Build Road
            </button>
            <button
              className={`action-button ${uiMode === 'build_settlement' ? 'action-button--active' : ''}`}
              onClick={() => startMode('build_settlement')}
              disabled={!isMyTurn || buildSettlementCorners.length === 0}
            >
              Build Settlement
            </button>
            <button
              className={`action-button ${uiMode === 'build_city' ? 'action-button--active' : ''}`}
              onClick={() => startMode('build_city')}
              disabled={!isMyTurn || buildCityCorners.length === 0}
            >
              Build City
            </button>
            <button
              className="action-button"
              onClick={() => sendAction('buy_development', {})}
              disabled={!isMyTurn || !canBuyDev}
            >
              Buy Dev Card
            </button>
            <button
              className={`action-button ${uiMode === 'play_knight' ? 'action-button--active' : ''}`}
              onClick={() => startMode('play_knight')}
              disabled={!isMyTurn || !canPlayKnight}
            >
              Knight
            </button>
            <button
              className={`action-button ${uiMode === 'play_road_building' ? 'action-button--active' : ''}`}
              onClick={() => startMode('play_road_building')}
              disabled={!isMyTurn || !canPlayRoadBuilding}
            >
              Road Building
            </button>
            <button
              className={`action-button ${uiMode === 'play_year_of_plenty' ? 'action-button--active' : ''}`}
              onClick={() => startMode('play_year_of_plenty')}
              disabled={!isMyTurn || !canPlayYearOfPlenty}
            >
              Year of Plenty
            </button>
            <button
              className={`action-button ${uiMode === 'play_monopoly' ? 'action-button--active' : ''}`}
              onClick={() => startMode('play_monopoly')}
              disabled={!isMyTurn || !canPlayMonopoly}
            >
              Monopoly
            </button>
            <button
              className="action-button"
              onClick={() => setTradeOpen(true)}
              disabled={tradeDisabled}
            >
              Trade
            </button>
            <button
              className="action-button action-button--primary"
              onClick={() => sendAction('end_turn', {})}
              disabled={!isMyTurn || !canEndTurn}
            >
              End Turn
            </button>
          </div>
        </div>
      </div>

      {tradeOpen && (
        <div className="modal-backdrop" onClick={() => setTradeOpen(false)}>
          <div className="trade-modal" onClick={(e) => e.stopPropagation()}>
            <div className="trade-tabs">
              <button
                className={`trade-tab ${tradeMode === 'player' ? 'active' : ''}`}
                onClick={() => setTradeMode('player')}
              >
                Domestic
              </button>
              <button
                className={`trade-tab ${tradeMode === 'bank' ? 'active' : ''}`}
                onClick={() => setTradeMode('bank')}
                disabled={!canTradeBank}
              >
                Bank
              </button>
            </div>
            {tradeMode === 'player' ? (
              <div className="trade-content">
                <div className="trade-row">
                  <label>Offer to</label>
                  <select
                    className="input_general"
                    value={tradeOffer.to_player}
                    onChange={(e) => setTradeOffer((prev) => ({ ...prev, to_player: e.target.value }))}
                  >
                    <option value="">Any</option>
                    {Object.keys(state.game?.players || {}).filter((name) => name !== username).map((name) => (
                      <option key={name} value={name}>{name}</option>
                    ))}
                  </select>
                </div>
                <div className="trade-section">
                  <h4>Offer</h4>
                  <div className="trade-grid">
                    {RESOURCE_ORDER.map((res) => (
                      <div key={`offer-${res}`} className="trade-resource">
                        <div className="trade-resource-name">
                          <img className="trade-resource-icon" src={RESOURCE_ICONS[res]} alt={RESOURCE_LABELS[res]} />
                          <span>{RESOURCE_LABELS[res]}</span>
                        </div>
                        <div className="trade-stepper">
                          <button
                            className="stepper-btn"
                            onClick={() => updateTradeAmount('offer', res, -1, myResources?.[res] || 0)}
                          >
                            -
                          </button>
                          <div className="stepper-value">{tradeOffer.offer[res]}</div>
                          <button
                            className="stepper-btn"
                            onClick={() => updateTradeAmount('offer', res, 1, myResources?.[res] || 0)}
                            disabled={(tradeOffer.offer[res] || 0) >= (myResources?.[res] || 0)}
                          >
                            +
                          </button>
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
                <div className="trade-section">
                  <h4>Request</h4>
                  <div className="trade-grid">
                    {RESOURCE_ORDER.map((res) => (
                      <div key={`request-${res}`} className="trade-resource">
                        <div className="trade-resource-name">
                          <img className="trade-resource-icon" src={RESOURCE_ICONS[res]} alt={RESOURCE_LABELS[res]} />
                          <span>{RESOURCE_LABELS[res]}</span>
                        </div>
                        <div className="trade-stepper">
                          <button
                            className="stepper-btn"
                            onClick={() => updateTradeAmount('request', res, -1, 4)}
                          >
                            -
                          </button>
                          <div className="stepper-value">{tradeOffer.request[res]}</div>
                          <button
                            className="stepper-btn"
                            onClick={() => updateTradeAmount('request', res, 1, 4)}
                          >
                            +
                          </button>
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
                <div className="trade-actions-row">
                  <button className="btn_general btn_general_secondary" onClick={() => setTradeOpen(false)}>
                    Cancel
                  </button>
                  <button className="btn_general btn_general_orange" onClick={submitTradeOffer}>
                    Send Offer
                  </button>
                </div>
              </div>
            ) : (
              <div className="trade-content">
                <div className="trade-row">
                  <label>Give</label>
                  <select
                    className="input_general"
                    value={bankTrade.give}
                    onChange={(e) => setBankTrade((prev) => ({
                      ...prev,
                      give: e.target.value,
                      receive: Object.keys(bankTradeMap[e.target.value] || {})[0] || 'brick',
                    }))}
                  >
                    {bankGiveOptions.map((res) => (
                      <option key={res} value={res}>{RESOURCE_LABELS[res] || res}</option>
                    ))}
                  </select>
                </div>
                <div className="trade-row">
                  <label>Receive</label>
                  <select
                    className="input_general"
                    value={bankTrade.receive}
                    onChange={(e) => setBankTrade((prev) => ({ ...prev, receive: e.target.value }))}
                  >
                    {bankReceiveOptions.map((res) => (
                      <option key={res} value={res}>{RESOURCE_LABELS[res] || res}</option>
                    ))}
                  </select>
                </div>
                <div className="trade-row muted">
                  Ratio: {bankRatio ? `${bankRatio}:1` : 'n/a'}
                </div>
                <div className="trade-actions-row">
                  <button className="btn_general btn_general_secondary" onClick={() => setTradeOpen(false)}>
                    Cancel
                  </button>
                  <button
                    className="btn_general btn_general_orange"
                    disabled={!bankRatio}
                    onClick={() => {
                      sendAction('trade_bank', {
                        give: bankTrade.give,
                        receive: bankTrade.receive,
                        amount: 1,
                        ratio: bankRatio,
                      });
                      setTradeOpen(false);
                    }}
                  >
                    Trade with Bank
                  </button>
                </div>
              </div>
            )}
          </div>
        </div>
      )}

      {uiMode === 'play_year_of_plenty' && (
        <div className="modal-backdrop" onClick={() => setUiMode(null)}>
          <div className="trade-modal" onClick={(e) => e.stopPropagation()}>
            <h3>Year of Plenty</h3>
            <div className="trade-row">
              <label>First resource</label>
              <select
                className="input_general"
                value={yearPick.first}
                onChange={(e) => setYearPick((prev) => ({ ...prev, first: e.target.value }))}
              >
                {RESOURCE_ORDER.map((res) => (
                  <option key={res} value={res}>{RESOURCE_LABELS[res]}</option>
                ))}
              </select>
            </div>
            <div className="trade-row">
              <label>Second resource</label>
              <select
                className="input_general"
                value={yearPick.second}
                onChange={(e) => setYearPick((prev) => ({ ...prev, second: e.target.value }))}
              >
                {RESOURCE_ORDER.map((res) => (
                  <option key={res} value={res}>{RESOURCE_LABELS[res]}</option>
                ))}
              </select>
            </div>
            <div className="trade-actions-row">
              <button className="btn_general btn_general_secondary" onClick={() => setUiMode(null)}>
                Cancel
              </button>
              <button
                className="btn_general btn_general_orange"
                onClick={() => {
                  sendAction('play_year_of_plenty', { resources: [yearPick.first, yearPick.second] });
                  setUiMode(null);
                }}
              >
                Take
              </button>
            </div>
          </div>
        </div>
      )}

      {uiMode === 'play_monopoly' && (
        <div className="modal-backdrop" onClick={() => setUiMode(null)}>
          <div className="trade-modal" onClick={(e) => e.stopPropagation()}>
            <h3>Monopoly</h3>
            <div className="trade-grid">
              {RESOURCE_ORDER.map((res) => (
                <button
                  key={res}
                  className={`action-button ${monopolyPick === res ? 'action-button--active' : ''}`}
                  onClick={() => setMonopolyPick(res)}
                >
                  {RESOURCE_LABELS[res]}
                </button>
              ))}
            </div>
            <div className="trade-actions-row">
              <button className="btn_general btn_general_secondary" onClick={() => setUiMode(null)}>
                Cancel
              </button>
              <button
                className="btn_general btn_general_orange"
                onClick={() => {
                  sendAction('play_monopoly', { resource: monopolyPick });
                  setUiMode(null);
                }}
              >
                Claim
              </button>
            </div>
          </div>
        </div>
      )}

      {uiMode === 'discard' && discardRequired > 0 && (
        <div className="modal-backdrop">
          <div className="trade-modal">
            <h3>Discard {discardRequired} cards</h3>
                <div className="trade-grid">
                  {RESOURCE_ORDER.map((res) => (
                    <div key={`discard-${res}`} className="trade-resource">
                      <div className="trade-resource-name">
                        <img className="trade-resource-icon" src={RESOURCE_ICONS[res]} alt={RESOURCE_LABELS[res]} />
                        <span>{RESOURCE_LABELS[res]}</span>
                      </div>
                      <div className="trade-stepper">
                        <button
                          className="stepper-btn"
                      onClick={() => updateDiscard(res, -1, discardResources[res] || 0)}
                    >
                      -
                    </button>
                    <div className="stepper-value">{discardCards[res]}</div>
                    <button
                      className="stepper-btn"
                      onClick={() => updateDiscard(res, 1, discardResources[res] || 0)}
                      disabled={(discardCards[res] || 0) >= (discardResources[res] || 0)}
                    >
                      +
                    </button>
                  </div>
                </div>
              ))}
            </div>
            <div className="trade-actions-row">
              <button
                className="btn_general btn_general_orange"
                disabled={!canSubmitDiscard}
                onClick={() => {
                  const cards = Object.fromEntries(
                    Object.entries(discardCards).filter(([, amt]) => amt > 0),
                  );
                  sendAction('discard', { player: username, cards });
                  setUiMode(null);
                  resetSelection();
                }}
              >
                Discard
              </button>
            </div>
          </div>
        </div>
      )}
    </PageShell>
  );
}

function AnalyticsPage() {
  const [stats, setStats] = useState(null);
  useEffect(() => {
    apiFetch('/api/stats').then(setStats).catch(console.error);
  }, []);
  return (
    <PageShell hideAds>
      <div className="panel-card">
        <h2>Global Stats</h2>
        {stats ? (
          <div className="stat-grid">
            <div>
              <strong>{stats.total_games}</strong>
              <span>Total games</span>
            </div>
            <div>
              <strong>{stats.finished_games}</strong>
              <span>Finished</span>
            </div>
            <div>
              <strong>{Number(stats.avg_turns || 0).toFixed(1)}</strong>
              <span>Average turns</span>
            </div>
          </div>
        ) : (
          <div className="muted">Loading stats...</div>
        )}
      </div>
    </PageShell>
  );
}

function ReplaysPage() {
  const [replays, setReplays] = useState([]);
  const navigate = useNavigate();
  useEffect(() => {
    apiFetch('/api/replays').then((data) => setReplays(data.replays || [])).catch(console.error);
  }, []);

  async function exportReplay(id) {
    const data = await apiFetch(`/api/replays/${id}/export`);
    const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = `catan-replay-${id}.json`;
    link.click();
    URL.revokeObjectURL(url);
  }

  return (
    <PageShell hideAds>
      <div className="panel-card">
        <h2>Replays</h2>
        <div className="replay-table">
          {replays.map((replay) => (
            <div key={replay.id} className="replay-row">
              <div>
                <strong>{replay.players.join(', ')}</strong>
                <div className="muted">Winner: {replay.winner || '-'}</div>
              </div>
              <div className="replay-actions">
                <button className="btn_general btn_general_orange" onClick={() => navigate(`/replays/${replay.id}`)}>
                  View
                </button>
                <button className="btn_general btn_general_secondary" onClick={() => exportReplay(replay.id)}>
                  Export
                </button>
              </div>
            </div>
          ))}
          {replays.length === 0 && <div className="muted">No replays yet.</div>}
        </div>
      </div>
    </PageShell>
  );
}

function ReplayViewer() {
  const { replayId } = useParams();
  const [detail, setDetail] = useState(null);
  const [step, setStep] = useState(0);
  const [state, setState] = useState(null);

  useEffect(() => {
    apiFetch(`/api/replays/${replayId}`).then(setDetail).catch(console.error);
  }, [replayId]);

  useEffect(() => {
    apiFetch(`/api/replays/${replayId}/state?step=${step}`).then(setState).catch(console.error);
  }, [replayId, step]);

  if (!detail) {
    return (
      <PageShell hideAds>
        <div className="screen">Loading replay...</div>
      </PageShell>
    );
  }

  return (
    <PageShell hideAds>
      <div className="panel-card replay-viewer">
        <h2>Replay {detail.id}</h2>
        <div className="panel-stack">
          <div>Players: {detail.players.join(', ')}</div>
          <div>Winner: {detail.winner || '-'}</div>
          <input
            className="input_general"
            type="range"
            min="0"
            max={detail.total_actions}
            value={step}
            onChange={(e) => setStep(parseInt(e.target.value, 10))}
          />
          <div className="muted">Step {step}</div>
        </div>
      </div>
      <div className="game-board-area replay-board">
        <Board board={state?.board} game={state?.game} />
      </div>
    </PageShell>
  );
}

function ProfilePage() {
  const [stats, setStats] = useState(null);
  useEffect(() => {
    apiFetch('/api/stats').then(setStats).catch(console.error);
  }, []);
  return (
    <PageShell hideAds>
      <div className="panel-card">
        <h2>Profile</h2>
        <div className="panel-stack">
          <div className="muted">Signed in as {getUsername() || 'Guest'}</div>
          {stats && (
            <div className="stat-grid">
              <div>
                <strong>{stats.user_games}</strong>
                <span>Your games</span>
              </div>
              <div>
                <strong>{stats.user_wins}</strong>
                <span>Your wins</span>
              </div>
            </div>
          )}
          <Link className="btn_general btn_general_orange" to="/replays">
            View Replays
          </Link>
        </div>
      </div>
    </PageShell>
  );
}

function StorePage() {
  const [models, setModels] = useState([]);
  const [replays, setReplays] = useState([]);

  useEffect(() => {
    Promise.all([apiFetch('/api/models'), apiFetch('/api/replays')])
      .then(([modelList, replayList]) => {
        setModels(modelList.models || []);
        setReplays(replayList.replays || []);
      })
      .catch(console.error);
  }, []);

  return (
    <PageShell hideAds>
      <div className="panel-card">
        <h2>Store</h2>
        <div className="panel-stack">
          <h3>AI Models</h3>
          <div className="model-grid">
            {models.map((model) => (
              <span key={model} className="model-pill">
                {model}
              </span>
            ))}
            {models.length === 0 && <div className="muted">No models found.</div>}
          </div>
          <h3>Recent Replays</h3>
          <div className="replay-list">
            {replays.slice(0, 5).map((replay) => (
              <div key={replay.id} className="replay-row compact">
                <div>
                  <strong>{replay.players.join(', ')}</strong>
                  <div className="muted">Winner: {replay.winner || '-'}</div>
                </div>
                <Link className="btn_general btn_general_secondary" to={`/replays/${replay.id}`}>
                  View
                </Link>
              </div>
            ))}
            {replays.length === 0 && <div className="muted">No replays yet.</div>}
          </div>
        </div>
      </div>
    </PageShell>
  );
}

export default function App() {
  const [user, setUser] = useState(getUsername());
  const hasToken = getToken();

  useEffect(() => {
    if (!hasToken) {
      setUser(null);
    }
  }, [hasToken]);

  function handleLogout() {
    clearToken();
    setUser(null);
  }

  return (
    <div className="web-layout-container" id="web-layout-container">
      <Sidebar />
      <Header user={user} onLogout={handleLogout} />
      <Routes>
        <Route path="/login" element={<LoginPage onAuth={setUser} />} />
        <Route path="/" element={user ? <LobbyPage /> : <LoginPage onAuth={setUser} />} />
        <Route path="/game/:gameId" element={user ? <GamePage /> : <LoginPage onAuth={setUser} />} />
        <Route path="/analytics" element={user ? <AnalyticsPage /> : <LoginPage onAuth={setUser} />} />
        <Route path="/replays" element={user ? <ReplaysPage /> : <LoginPage onAuth={setUser} />} />
        <Route path="/replays/:replayId" element={user ? <ReplayViewer /> : <LoginPage onAuth={setUser} />} />
        <Route path="/profile" element={user ? <ProfilePage /> : <LoginPage onAuth={setUser} />} />
        <Route path="/store" element={user ? <StorePage /> : <LoginPage onAuth={setUser} />} />
      </Routes>
    </div>
  );
}
