import * as bus from '../../../core/bus.js';
import * as scene from '../../../core/scene.js';
import * as audio from '../../../core/audio.js';
import * as juice from '../../../core/juice.js';
import * as net from '../../../core/net.js';
import * as store from '../../../core/store.js';
import * as matchLive from '../../../core/match-live.js';
import * as mp from '../../../core/multiplayer.js';
import { t } from '../../../core/i18n.js';
import { emoji } from '../../../core/theme.js';
import * as rules from '../logic/rules.js';
import * as bot from '../logic/bot.js';
import { DominoBoard } from '../canvas/board.js';
import { DominoHand } from '../components/hand.js';
import { DominoDrag } from '../components/drag.js';

let state, board, hand, drag, liveSession;
let botTimeout = null;
let autoPassTimeout = null;

export function mountGame(el, params) {
  const { mode = 'bot', matchId, playerIndex = 0, players, botLevel = 'intermediate' } = params;
  scene.enterGameMode();

  state = createInitialState(mode, matchId, playerIndex, botLevel, players);

  if (mode !== 'live') {
    dealNewRound();
  }

  el.innerHTML = buildLayout(mode);

  const boardContainer = el.querySelector('#domino-board');
  board = new DominoBoard(boardContainer, {
    onEndpointTap: (hit) => handleEndpointTap(el, hit)
  });
  board.setChain(state.chain);

  const handContainer = el.querySelector('#domino-hand-area');
  hand = new DominoHand(handContainer, {
    onTileSelect: (tile) => handleTileSelect(el, tile),
    onDragStart: (tile, info) => handleDragStart(el, tile, info)
  });

  drag = new DominoDrag({
    board,
    onPlace: (tile, end) => executePlacement(el, tile, end),
    onCancel: () => { hand.clearSelection(); state.selectedTile = null; },
    getEnds: () => ({ leftEnd: state.leftEnd, rightEnd: state.rightEnd })
  });

  injectStyles(el);

  updateUI(el);
  refreshHand();

  el.querySelector('#btn-draw').addEventListener('click', () => drawFromBoneyard(el));
  el.querySelector('#btn-pass').addEventListener('click', () => passTurn(el));
  el.querySelector('#btn-resign')?.addEventListener('click', () => confirmResign(el));
  el.querySelector('#btn-emote')?.addEventListener('click', () => showEmoteMenu(el));

  if (mode === 'bot') {
    createServerRecord();
    if (state.currentPlayer !== state.myPlayerIndex) {
      scheduleBotTurn(el);
    }
  } else if (mode === 'live' && matchId) {
    setupLiveMultiplayer(el, matchId);
  }

  bus.emit('game:started', { gameKey: 'domino', mode, matchId });
}

function createInitialState(mode, matchId, playerIndex, botLevel, players) {
  return {
    mode, matchId, myPlayerIndex: playerIndex,
    players: players || [],
    hands: [[], []], boneyard: [], chain: [],
    leftEnd: null, rightEnd: null,
    currentPlayer: 0, numPlayers: 2,
    matchScores: [0, 0], roundNumber: 1, targetScore: 100,
    selectedTile: null, gameOver: false, matchOver: false,
    moveCount: 0, lastSyncMoveCount: 0,
    botPersonality: bot.getPersonality(botLevel),
    botThinking: false,
    lastEmoteHandled: 0,
    lastDrawOfferHandled: 0,
  };
}

function dealNewRound() {
  const allTiles = rules.shuffle(rules.createDominoSet());
  const { hands, boneyard } = rules.dealHands(allTiles, state.numPlayers);
  state.hands = hands;
  state.boneyard = boneyard;
  state.chain = [];
  state.leftEnd = null;
  state.rightEnd = null;
  state.gameOver = false;
  state.selectedTile = null;
}

function buildLayout(mode) {
  const isLive = mode === 'live';
  return `
    <div id="domino-wrap" style="display:flex;flex-direction:column;height:100%;background:#0a0a14;position:relative;">
      <!-- Opponent bar -->
      <div id="domino-opp-bar" style="display:flex;align-items:center;justify-content:space-between;padding:10px 14px;background:#0f0f1e;border-bottom:1px solid rgba(255,255,255,0.06);">
        <div style="display:flex;align-items:center;gap:8px;">
          <div id="opp-avatar" style="width:32px;height:32px;border-radius:50%;background:linear-gradient(135deg,#E4AC38,#F59E0B);display:flex;align-items:center;justify-content:center;font-size:14px;">${isLive ? '👤' : '🤖'}</div>
          <div>
            <div id="opp-name" style="font-size:13px;font-weight:700;color:#f8fafc;">${isLive ? 'خصم' : 'بوت'}</div>
            <div id="opp-count" style="font-size:11px;color:#94a3b8;">7 قطع</div>
          </div>
        </div>
        <div style="display:flex;align-items:center;gap:8px;">
          <div id="bot-thinking" style="font-size:11px;color:#E4AC38;display:none;">يفكر...</div>
          ${isLive ? '<div id="conn-dot" style="width:8px;height:8px;border-radius:50%;background:#4ade80;"></div>' : ''}
          <div id="boneyard-count" style="font-size:11px;color:#94a3b8;background:rgba(255,255,255,0.05);padding:4px 10px;border-radius:8px;border:1px solid rgba(255,255,255,0.06);">المخزن: 14</div>
        </div>
      </div>

      <!-- Emote display area -->
      <div id="emote-display" style="position:absolute;top:56px;left:50%;transform:translateX(-50%);z-index:50;pointer-events:none;"></div>

      <!-- Canvas board -->
      <div id="domino-board" style="flex:1;min-height:0;padding:4px;"></div>

      <!-- Score bar -->
      <div id="score-bar" style="display:flex;align-items:center;justify-content:center;gap:12px;padding:6px 12px;background:#0f0f1e;border-top:1px solid rgba(255,255,255,0.04);">
        <span style="font-size:12px;color:#E4AC38;">أنت: <b id="my-score">0</b></span>
        <span style="font-size:11px;color:#334155;">|</span>
        <span style="font-size:12px;color:#94a3b8;">خصم: <b id="opp-score">0</b></span>
        <span style="font-size:11px;color:#334155;">|</span>
        <span style="font-size:11px;color:#64748b;">${emoji('target', '🎯', 12)} 100</span>
        <span style="font-size:11px;color:#334155;">|</span>
        <span style="font-size:11px;color:#64748b;">ج<span id="round-num">1</span></span>
      </div>

      <!-- Status -->
      <div id="turn-status" style="text-align:center;padding:5px;font-size:13px;font-weight:600;color:#E4AC38;">دورك!</div>

      <!-- Hand area -->
      <div id="domino-hand-area"></div>

      <!-- Controls -->
      <div id="domino-controls" style="display:flex;gap:6px;padding:8px 12px;padding-bottom:calc(8px + env(safe-area-inset-bottom,0px));background:#0f0f1e;border-top:1px solid rgba(255,255,255,0.06);">
        <button class="btn btn-secondary" id="btn-resign" style="flex:0.6;font-size:11px;min-height:44px;background:rgba(239,68,68,0.08);border:1px solid rgba(239,68,68,0.2);color:#fca5a5;border-radius:12px;">استسلام</button>
        <button class="btn btn-secondary" id="btn-emote" style="flex:0.5;font-size:16px;min-height:44px;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);border-radius:12px;">😄</button>
        <button class="btn btn-secondary" id="btn-draw" style="flex:1;font-size:13px;min-height:44px;background:rgba(228,172,56,0.1);border:1px solid rgba(228,172,56,0.25);color:#E4AC38;border-radius:12px;font-weight:700;">سحب</button>
        <button class="btn btn-secondary" id="btn-pass" style="flex:0.7;font-size:12px;min-height:44px;background:rgba(251,191,36,0.08);border:1px solid rgba(251,191,36,0.2);color:#fde68a;border-radius:12px;display:none;">تمرير</button>
      </div>
    </div>
  `;
}

function injectStyles(el) {
  const style = document.createElement('style');
  style.textContent = (hand?.getStyle() || '') + (drag?.getStyle() || '') + `
    @keyframes fadeIn { from{opacity:0} to{opacity:1} }
    @keyframes emoteFloat { 0%{transform:translateX(-50%) scale(0);opacity:0} 20%{transform:translateX(-50%) scale(1.2);opacity:1} 80%{opacity:1} 100%{transform:translateX(-50%) translateY(-20px);opacity:0} }
    .emote-bubble { animation: emoteFloat 2s ease forwards; position:absolute;left:50%;font-size:36px; }
    @keyframes drawPulse { 0%,100%{box-shadow:0 0 4px rgba(228,172,56,0.2)} 50%{box-shadow:0 0 14px rgba(228,172,56,0.5)} }
  `;
  el.appendChild(style);
}

// ═══════════════════════════════════════
// LIVE MULTIPLAYER
// ═══════════════════════════════════════

function setupLiveMultiplayer(el, matchId) {
  liveSession = matchLive.start(matchId, 'domino', {
    onMove: (data) => handleLivePollData(el, data),
    onGameEnd: (data) => {
      if (!state.gameOver && !state.matchOver) {
        endMatch(el, 'loss', 'abandon');
      }
    }
  });

  fetchOpponentProfile(el);
  mp.startDisconnectWatch?.(matchId, 'domino', 60000);

  if (state.myPlayerIndex === 0) {
    dealAndSyncToServer(el, matchId);
  } else {
    fetchInitialState(el, matchId);
  }
}

async function dealAndSyncToServer(el, matchId) {
  dealNewRound();
  board.setChain(state.chain);
  updateUI(el);
  refreshHand();

  try {
    await net.post('domino-match.php', {
      action: 'move',
      match_id: matchId,
      board: state.chain,
      boneyard: state.boneyard,
      hands: JSON.stringify({ '0': state.hands[0], '1': state.hands[1] }),
      current_turn: state.currentPlayer,
      game_state: JSON.stringify({
        move_count: 0,
        round: 1,
        left_end: state.leftEnd,
        right_end: state.rightEnd,
        scores: { '0': 0, '1': 0 },
        dealt: true,
      })
    });
  } catch (e) {}
}

async function fetchOpponentProfile(el) {
  if (!state.matchId) return;
  try {
    const data = await net.post('domino-match.php', { action: 'get', match_id: state.matchId });
    if (data?.players) {
      const myId = store.get('auth.userId');
      const players = typeof data.players === 'string' ? JSON.parse(data.players) : data.players;
      const oppId = players.find(p => p !== myId);
      if (oppId) {
        try {
          const profile = await net.post('profile.php', { action: 'get', user_id: oppId });
          if (profile?.display_name) {
            const nameEl = el.querySelector('#opp-name');
            if (nameEl) nameEl.textContent = profile.display_name;
          }
        } catch (e) {}
      }
    }
  } catch (e) {}
}

async function fetchInitialState(el, matchId, retries = 0) {
  try {
    const data = await net.post('domino-match.php', { action: 'get', match_id: matchId });

    // If hands not dealt yet (host hasn't synced), retry
    if ((!data?.my_hand || data.my_hand.length === 0) && retries < 10) {
      setTimeout(() => fetchInitialState(el, matchId, retries + 1), 1000);
      return;
    }

    if (data && data.board) {
      const board_data = typeof data.board === 'string' ? JSON.parse(data.board) : data.board;
      if (board_data.length > 0) {
        state.chain = board_data;
        const ends = rules.getEnds(state.chain);
        state.leftEnd = ends.leftEnd;
        state.rightEnd = ends.rightEnd;
      }
    }
    if (data?.my_hand && data.my_hand.length > 0) {
      state.hands[state.myPlayerIndex] = data.my_hand;
    }
    if (data?.game_state) {
      const gs = typeof data.game_state === 'string' ? JSON.parse(data.game_state) : data.game_state;
      if (gs.scores) state.matchScores = [gs.scores['0'] || 0, gs.scores['1'] || 0];
      if (gs.round) state.roundNumber = gs.round;
      if (gs.move_count) { state.moveCount = gs.move_count; state.lastSyncMoveCount = gs.move_count; }
    }
    if (data?.current_turn !== undefined) state.currentPlayer = data.current_turn;
    if (data?.opponent_count !== undefined) {
      const oppIdx = 1 - state.myPlayerIndex;
      state.hands[oppIdx] = new Array(data.opponent_count).fill({ left: 0, right: 0, id: 'hidden' });
    }
    const boneyard = data?.boneyard ? (typeof data.boneyard === 'string' ? JSON.parse(data.boneyard) : data.boneyard) : [];
    state.boneyard = boneyard;

    board.setChain(state.chain);
    updateUI(el);
    refreshHand();
  } catch (e) {}
}

function handleLivePollData(el, data) {
  if (!data || data.error || state.matchOver) return;

  mp.updateConnectionStatus?.(true);
  const connDot = el.querySelector('#conn-dot');
  if (connDot) connDot.style.background = '#4ade80';

  const gs = data.game_state ? (typeof data.game_state === 'string' ? JSON.parse(data.game_state) : data.game_state) : {};
  const myId = store.get('auth.userId');

  checkEmote(el, gs, myId);

  if (data.status === 'completed' && !state.matchOver) {
    const resigned = gs.resigned_by;
    if (resigned && resigned !== myId) {
      endMatch(el, 'win', 'resign');
    } else if (resigned === myId) {
      // Already handled locally
    } else {
      const winnerId = data.winner_id;
      const result = winnerId === myId ? 'win' : 'loss';
      endMatch(el, result, 'completed');
    }
    return;
  }

  const remoteMoveCount = gs.move_count || 0;
  if (remoteMoveCount > state.lastSyncMoveCount) {
    state.lastSyncMoveCount = remoteMoveCount;
    state.moveCount = remoteMoveCount;

    const lastMove = gs.last_move;
    if (lastMove && lastMove.player !== state.myPlayerIndex) {
      applyOpponentMove(el, data, gs, lastMove);
    }
  }

  if (data.current_turn !== undefined) {
    state.currentPlayer = data.current_turn;
  }

  if (data.opponent_count !== undefined) {
    const oppIdx = 1 - state.myPlayerIndex;
    const oppEl = el.querySelector('#opp-count');
    if (oppEl) oppEl.textContent = `${data.opponent_count} قطع`;
  }

  if (gs.scores) {
    state.matchScores = [gs.scores['0'] || 0, gs.scores['1'] || 0];
  }
  if (gs.round && gs.round > state.roundNumber) {
    state.roundNumber = gs.round;
    handleRemoteNewRound(el, data, gs);
  }

  updateUI(el);
  refreshHand();
}

function applyOpponentMove(el, data, gs, lastMove) {
  const boardData = data.board ? (typeof data.board === 'string' ? JSON.parse(data.board) : data.board) : state.chain;
  state.chain = boardData;

  if (gs.left_end !== undefined) state.leftEnd = gs.left_end;
  if (gs.right_end !== undefined) state.rightEnd = gs.right_end;

  const boneyard = data.boneyard ? (typeof data.boneyard === 'string' ? JSON.parse(data.boneyard) : data.boneyard) : state.boneyard;
  state.boneyard = boneyard;

  board.animatePlacement({ left: 0, right: 0, id: lastMove.tile_id || 'opp' }, lastMove.end || 'right', () => {
    board.setChain(state.chain);
  });

  audio.play('place', 'game');

  if (data.my_hand) {
    state.hands[state.myPlayerIndex] = data.my_hand;
  }
}

function handleRemoteNewRound(el, data, gs) {
  state.gameOver = false;
  if (data.my_hand) state.hands[state.myPlayerIndex] = data.my_hand;

  const boardData = data.board ? (typeof data.board === 'string' ? JSON.parse(data.board) : data.board) : [];
  state.chain = boardData;
  const ends = rules.getEnds(state.chain);
  state.leftEnd = ends.leftEnd;
  state.rightEnd = ends.rightEnd;

  const boneyard = data.boneyard ? (typeof data.boneyard === 'string' ? JSON.parse(data.boneyard) : data.boneyard) : [];
  state.boneyard = boneyard;

  board.setChain(state.chain);
}

async function syncMoveToServer(tile, end) {
  if (state.mode !== 'live' || !state.matchId) return;
  try {
    await net.post('domino-match.php', {
      action: 'move',
      match_id: state.matchId,
      board: state.chain,
      boneyard: state.boneyard,
      hands: JSON.stringify({ [state.myPlayerIndex]: state.hands[state.myPlayerIndex] }),
      current_turn: state.currentPlayer,
      game_state: JSON.stringify({
        move_count: state.moveCount,
        last_move: { player: state.myPlayerIndex, tile_id: tile.id, end, t: Date.now() },
        left_end: state.leftEnd,
        right_end: state.rightEnd,
        scores: { '0': state.matchScores[0], '1': state.matchScores[1] },
        round: state.roundNumber,
      })
    });
  } catch (e) {}
}

async function syncDrawToServer() {
  if (state.mode !== 'live' || !state.matchId) return;
  try {
    await net.post('domino-match.php', {
      action: 'move',
      match_id: state.matchId,
      boneyard: state.boneyard,
      hands: JSON.stringify({ [state.myPlayerIndex]: state.hands[state.myPlayerIndex] }),
      current_turn: state.currentPlayer,
      game_state: JSON.stringify({
        move_count: state.moveCount,
        left_end: state.leftEnd,
        right_end: state.rightEnd,
      })
    });
  } catch (e) {}
}

async function syncPassToServer() {
  if (state.mode !== 'live' || !state.matchId) return;
  try {
    await net.post('domino-match.php', {
      action: 'move',
      match_id: state.matchId,
      current_turn: state.currentPlayer,
      game_state: JSON.stringify({
        move_count: ++state.moveCount,
        last_move: { player: state.myPlayerIndex, action: 'pass', t: Date.now() },
        left_end: state.leftEnd,
        right_end: state.rightEnd,
      })
    });
  } catch (e) {}
}

async function syncRoundEndToServer(winnerIdx, roundPoints) {
  if (state.mode !== 'live' || !state.matchId) return;
  try {
    await net.post('domino-match.php', {
      action: 'move',
      match_id: state.matchId,
      board: state.chain,
      current_turn: state.currentPlayer,
      game_state: JSON.stringify({
        move_count: state.moveCount,
        scores: { '0': state.matchScores[0], '1': state.matchScores[1] },
        round: state.roundNumber,
        round_ended: true,
        round_winner: winnerIdx,
        round_points: roundPoints,
      })
    });
  } catch (e) {}
}

// ═══════════════════════════════════════
// EMOTES
// ═══════════════════════════════════════

function checkEmote(el, gs, myId) {
  if (!gs.emote) return;
  const emote = gs.emote;
  if (emote.from === myId) return;
  if (emote.t <= state.lastEmoteHandled) return;
  if (Date.now() - emote.t > 15000) return;

  state.lastEmoteHandled = emote.t;
  showEmoteBubble(el, emote.key);
}

function showEmoteBubble(el, emoteKey) {
  const emotes = { laugh: '😂', think: '🤔', wow: '😮', angry: '😡', gg: '👏', love: '❤️', fire: '🔥', cry: '😢' };
  const display = el.querySelector('#emote-display');
  if (!display) return;

  const bubble = document.createElement('div');
  bubble.className = 'emote-bubble';
  bubble.textContent = emotes[emoteKey] || '😄';
  display.appendChild(bubble);
  audio.play('notification');

  setTimeout(() => bubble.remove(), 2000);
}

function showEmoteMenu(el) {
  const emotes = [
    { key: 'laugh', icon: '😂' }, { key: 'think', icon: '🤔' },
    { key: 'wow', icon: '😮' }, { key: 'angry', icon: '😡' },
    { key: 'gg', icon: '👏' }, { key: 'love', icon: '❤️' },
    { key: 'fire', icon: '🔥' }, { key: 'cry', icon: '😢' }
  ];

  const existing = el.querySelector('#emote-menu');
  if (existing) { existing.remove(); return; }

  const menu = document.createElement('div');
  menu.id = 'emote-menu';
  menu.style.cssText = `
    position:absolute;bottom:110px;left:50%;transform:translateX(-50%);
    display:flex;gap:6px;padding:10px 14px;background:#1a1a2e;
    border-radius:16px;border:1px solid rgba(228,172,56,0.15);
    box-shadow:0 8px 24px rgba(0,0,0,0.6);z-index:60;
    animation:fadeIn 0.2s ease;
  `;
  menu.innerHTML = emotes.map(e => `
    <button data-emote="${e.key}" style="font-size:24px;background:none;border:none;cursor:pointer;padding:4px;border-radius:8px;transition:transform 0.1s;">
      ${e.icon}
    </button>
  `).join('');

  const wrap = el.querySelector('#domino-wrap');
  wrap.appendChild(menu);

  menu.querySelectorAll('button').forEach(btn => {
    btn.addEventListener('click', () => {
      const key = btn.dataset.emote;
      sendEmote(key);
      showEmoteBubble(el, key);
      menu.remove();
    });
  });

  setTimeout(() => menu.remove(), 5000);
}

async function sendEmote(key) {
  if (!state.matchId) return;
  const myId = store.get('auth.userId');
  try {
    await net.post('domino-match.php', {
      action: 'move',
      match_id: state.matchId,
      game_state: JSON.stringify({ emote: { key, from: myId, t: Date.now() } })
    });
  } catch (e) {}
}

// ═══════════════════════════════════════
// INTERACTION HANDLERS
// ═══════════════════════════════════════

function handleTileSelect(el, tile) {
  if (state.currentPlayer !== state.myPlayerIndex || state.gameOver) return;

  const playEnd = rules.determinePlayEnd(tile, state.leftEnd, state.rightEnd);
  if (!playEnd) return;

  // Deselect if same tile tapped again
  if (state.selectedTile?.id === tile.id) {
    state.selectedTile = null;
    hand.clearSelection();
    board.clearActiveEndpoint();
    updateUI(el);
    return;
  }

  // Select the tile and highlight valid placement locations
  state.selectedTile = tile;
  hand.setSelected(tile.id);

  // First tile on empty board → show center endpoint
  if (state.chain.length === 0) {
    board.setActiveEndpoint('both');
  } else {
    board.setActiveEndpoint(playEnd);
  }

  updateUI(el);
}

function handleEndpointTap(el, hit) {
  if (!state.selectedTile) return;
  const tile = state.selectedTile;

  // First tile on empty board — place on any tap
  if (state.chain.length === 0) {
    executePlacement(el, tile, 'right');
    return;
  }

  const canPlayOnEnd = tile.left === hit.value || tile.right === hit.value;
  if (canPlayOnEnd) {
    executePlacement(el, tile, hit.end);
  }
}

function handleDragStart(el, tile, info) {
  if (state.currentPlayer !== state.myPlayerIndex || state.gameOver) return;
  state.selectedTile = tile;
  hand.setSelected(tile.id);
  drag.start(tile, info);
}

// ═══════════════════════════════════════
// GAME LOGIC
// ═══════════════════════════════════════

function executePlacement(el, tile, end) {
  if (state.gameOver) return;

  const actualEnd = state.chain.length === 0 ? 'right' : end;
  const result = rules.placeTile(state.chain, tile, actualEnd);
  state.chain = result.chain;
  state.leftEnd = result.leftEnd;
  state.rightEnd = result.rightEnd;

  state.hands[state.myPlayerIndex] = state.hands[state.myPlayerIndex].filter(t => t.id !== tile.id);
  state.selectedTile = null;
  state.moveCount++;

  board.clearActiveEndpoint();
  hand.clearSelection();
  board.animatePlacement(tile, actualEnd, () => {
    board.setChain(state.chain);
  });

  audio.play('place', 'game');
  juice.hapticMedium?.();

  syncMoveToServer(tile, actualEnd);

  if (checkRoundEnd(el)) return;
  nextTurn(el);
}

function drawFromBoneyard(el) {
  if (state.currentPlayer !== state.myPlayerIndex) return;
  if (state.boneyard.length === 0) return;
  if (state.gameOver) return;
  if (rules.hasValidMove(state.hands[state.myPlayerIndex], state.leftEnd, state.rightEnd)) return;

  const tile = state.boneyard.pop();
  state.hands[state.myPlayerIndex].push(tile);
  audio.play('click');
  juice.hapticLight?.();

  syncDrawToServer();
  updateUI(el);
  refreshHand();
}

function passTurn(el) {
  if (state.currentPlayer !== state.myPlayerIndex) return;
  if (state.boneyard.length > 0) return;
  if (rules.hasValidMove(state.hands[state.myPlayerIndex], state.leftEnd, state.rightEnd)) return;

  syncPassToServer();
  nextTurn(el);
}

function nextTurn(el) {
  state.currentPlayer = (state.currentPlayer + 1) % state.numPlayers;
  updateUI(el);
  refreshHand();

  if (state.mode === 'bot' && state.currentPlayer !== state.myPlayerIndex) {
    scheduleBotTurn(el);
  }
}

function checkRoundEnd(el) {
  if (state.hands[state.currentPlayer]?.length === 0) {
    endRound(el, state.currentPlayer);
    return true;
  }
  if (rules.checkRoundEnd(state.hands, state.boneyard, state.chain)) {
    const { winner } = rules.getRoundWinner(state.hands);
    endRound(el, winner);
    return true;
  }
  return false;
}

function endRound(el, winnerIdx) {
  state.gameOver = true;
  const roundPoints = rules.scoreRound(state.hands, winnerIdx);
  state.matchScores[winnerIdx] += roundPoints;

  const isMyWin = winnerIdx === state.myPlayerIndex;
  audio.play(isMyWin ? 'win' : 'lose', 'game');

  if (isMyWin) {
    juice.hapticSuccess?.();
    const boardEl = el.querySelector('#domino-board');
    if (boardEl) {
      const rect = boardEl.getBoundingClientRect();
      juice.confetti?.(rect.left + rect.width / 2, rect.top + rect.height / 2, 20);
    }
  }

  syncRoundEndToServer(winnerIdx, roundPoints);
  updateUI(el);

  if (state.matchScores[0] >= state.targetScore || state.matchScores[1] >= state.targetScore) {
    const matchWinner = state.matchScores[0] >= state.targetScore ? 0 : 1;
    const result = matchWinner === state.myPlayerIndex ? 'win' : 'loss';
    endMatch(el, result, 'score');
  } else {
    showRoundOverlay(el, winnerIdx, roundPoints);
  }
}

function showRoundOverlay(el, winnerIdx, points) {
  const isMyWin = winnerIdx === state.myPlayerIndex;
  const overlay = document.createElement('div');
  overlay.id = 'round-overlay';
  overlay.style.cssText = `
    position:absolute;inset:0;z-index:100;display:flex;flex-direction:column;
    align-items:center;justify-content:center;gap:12px;
    background:rgba(0,0,0,0.85);animation:fadeIn 0.3s ease;
  `;
  overlay.innerHTML = `
    <div style="font-size:48px;">${isMyWin ? emoji('trophy', '🏆', 48) : emoji('skull', '💀', 48)}</div>
    <div style="font-size:20px;font-weight:800;color:${isMyWin ? '#4ade80' : '#fca5a5'};">
      ${isMyWin ? 'فزت بالجولة!' : 'خسرت الجولة'}
    </div>
    <div style="font-size:14px;color:#94a3b8;">+${points} نقطة</div>
    <div style="display:flex;gap:16px;margin-top:8px;">
      <div style="text-align:center;">
        <div style="font-size:24px;font-weight:800;color:#4ade80;">${state.matchScores[state.myPlayerIndex]}</div>
        <div style="font-size:11px;color:#6ee7b7;">أنت</div>
      </div>
      <div style="font-size:20px;color:#475569;align-self:center;">—</div>
      <div style="text-align:center;">
        <div style="font-size:24px;font-weight:800;color:#fca5a5;">${state.matchScores[1 - state.myPlayerIndex]}</div>
        <div style="font-size:11px;color:#fca5a5;">خصم</div>
      </div>
    </div>
    <div style="font-size:12px;color:#64748b;margin-top:8px;">الجولة التالية تبدأ...</div>
  `;

  const wrap = el.querySelector('#domino-wrap');
  wrap.appendChild(overlay);

  setTimeout(() => {
    overlay.remove();
    startNewRound(el);
  }, 2500);
}

function startNewRound(el) {
  state.roundNumber++;
  state.currentPlayer = state.matchScores[0] <= state.matchScores[1] ? 0 : 1;

  if (state.mode === 'live') {
    if (state.myPlayerIndex === 0) {
      dealNewRound();
      syncNewRoundToServer();
      board.setChain(state.chain);
      updateUI(el);
      refreshHand();
    }
    // Guest will receive the new round data via poll
  } else {
    dealNewRound();
    board.setChain(state.chain);
    updateUI(el);
    refreshHand();

    if (state.currentPlayer !== state.myPlayerIndex) {
      scheduleBotTurn(el);
    }
  }
}

async function syncNewRoundToServer() {
  if (!state.matchId) return;
  try {
    await net.post('domino-match.php', {
      action: 'move',
      match_id: state.matchId,
      board: state.chain,
      boneyard: state.boneyard,
      hands: JSON.stringify({ '0': state.hands[0], '1': state.hands[1] }),
      current_turn: state.currentPlayer,
      game_state: JSON.stringify({
        move_count: state.moveCount,
        scores: { '0': state.matchScores[0], '1': state.matchScores[1] },
        round: state.roundNumber,
        left_end: state.leftEnd,
        right_end: state.rightEnd,
        dealt: true,
      })
    });
  } catch (e) {}
}

function endMatch(el, result, reason) {
  if (state.matchOver) return;
  state.matchOver = true;
  state.gameOver = true;

  liveSession?.cleanup?.();
  mp.stopDisconnectWatch?.();

  if (result === 'win') {
    audio.play('win', 'reward');
    juice.hapticSuccess?.();
    const boardEl = el.querySelector('#domino-board');
    if (boardEl) {
      const rect = boardEl.getBoundingClientRect();
      juice.confetti?.(rect.left + rect.width / 2, rect.top + rect.height / 2, 40);
    }
  } else {
    audio.play('lose', 'game');
  }

  if (state.matchId && state.mode === 'live') {
    const myId = store.get('auth.userId');
    net.post('domino-match.php', {
      action: 'complete',
      match_id: state.matchId,
      result: result === 'win' ? 'player' + (state.myPlayerIndex + 1) + '_wins' : 'player' + (2 - state.myPlayerIndex) + '_wins',
      winner_id: result === 'win' ? myId : undefined,
      scores: JSON.stringify({ '0': state.matchScores[0], '1': state.matchScores[1] })
    }).catch(() => {});
  }

  setTimeout(() => {
    scene.exitGameMode();
    scene.replace('domino-result', {
      result, reason, mode: state.mode,
      myScore: state.matchScores[state.myPlayerIndex],
      oppScore: state.matchScores[1 - state.myPlayerIndex],
      rounds: state.roundNumber,
      matchId: state.matchId
    });
    bus.emit('game:ended', { gameKey: 'domino', result, mode: state.mode });
  }, 1200);
}

// ═══════════════════════════════════════
// BOT
// ═══════════════════════════════════════

function scheduleBotTurn(el) {
  state.botThinking = true;
  const thinkEl = el.querySelector('#bot-thinking');
  if (thinkEl) thinkEl.style.display = 'block';

  const delay = bot.getThinkDelay(state.botPersonality);
  botTimeout = setTimeout(() => executeBotTurn(el), delay);
}

function executeBotTurn(el) {
  if (state.gameOver || state.matchOver) return;
  state.botThinking = false;
  const thinkEl = el.querySelector('#bot-thinking');
  if (thinkEl) thinkEl.style.display = 'none';

  const botIdx = state.currentPlayer;
  const botHand = state.hands[botIdx];

  if (!rules.hasValidMove(botHand, state.leftEnd, state.rightEnd)) {
    if (state.boneyard.length > 0) {
      botHand.push(state.boneyard.pop());
      audio.play('click');
      updateUI(el);
      botTimeout = setTimeout(() => executeBotTurn(el), 400);
      return;
    }
    if (checkRoundEnd(el)) return;
    nextTurn(el);
    return;
  }

  const oppCount = state.hands[state.myPlayerIndex].length;
  const move = bot.pickMove(botHand, state.leftEnd, state.rightEnd, state.chain, oppCount, state.botPersonality);
  if (!move) { nextTurn(el); return; }

  const actualEnd = state.chain.length === 0 ? 'right' : (move.end === 'first' ? 'right' : move.end);
  const result = rules.placeTile(state.chain, move.tile, actualEnd);
  state.chain = result.chain;
  state.leftEnd = result.leftEnd;
  state.rightEnd = result.rightEnd;
  state.hands[botIdx] = botHand.filter(t => t.id !== move.tile.id);
  state.moveCount++;

  board.animatePlacement(move.tile, actualEnd, () => {
    board.setChain(state.chain);
  });
  audio.play('place', 'game');

  if (bot.shouldEmote(state.botPersonality)) {
    setTimeout(() => showEmoteBubble(el, bot.getRandomEmote()), 300);
  }

  updateUI(el);

  if (checkRoundEnd(el)) return;
  nextTurn(el);
}

// ═══════════════════════════════════════
// UI
// ═══════════════════════════════════════

function updateUI(el) {
  const isMyTurn = state.currentPlayer === state.myPlayerIndex;
  const turnEl = el.querySelector('#turn-status');
  if (turnEl) {
    if (state.gameOver) {
      turnEl.textContent = 'انتهت الجولة';
      turnEl.style.color = '#94a3b8';
    } else if (isMyTurn && state.selectedTile) {
      turnEl.textContent = 'اختر مكان الوضع';
      turnEl.style.color = '#E4AC38';
    } else if (isMyTurn) {
      turnEl.textContent = 'دورك!';
      turnEl.style.color = '#E4AC38';
    } else {
      turnEl.textContent = 'الخصم يلعب...';
      turnEl.style.color = '#64748b';
    }
  }

  const oppCountEl = el.querySelector('#opp-count');
  if (oppCountEl) {
    const oppIdx = 1 - state.myPlayerIndex;
    oppCountEl.textContent = `${state.hands[oppIdx]?.length || 0} قطع`;
  }

  const boneEl = el.querySelector('#boneyard-count');
  if (boneEl) boneEl.textContent = `المخزن: ${state.boneyard.length}`;

  const myScoreEl = el.querySelector('#my-score');
  const oppScoreEl = el.querySelector('#opp-score');
  if (myScoreEl) myScoreEl.textContent = state.matchScores[state.myPlayerIndex];
  if (oppScoreEl) oppScoreEl.textContent = state.matchScores[1 - state.myPlayerIndex];

  const roundEl = el.querySelector('#round-num');
  if (roundEl) roundEl.textContent = state.roundNumber;

  const drawBtn = el.querySelector('#btn-draw');
  const passBtn = el.querySelector('#btn-pass');
  const myHand = state.hands[state.myPlayerIndex];
  const hasMove = rules.hasValidMove(myHand, state.leftEnd, state.rightEnd);

  if (isMyTurn && !hasMove && state.boneyard.length > 0 && !state.gameOver) {
    if (drawBtn) { drawBtn.style.display = ''; drawBtn.style.animation = 'drawPulse 1.5s ease-in-out infinite'; }
    if (passBtn) passBtn.style.display = 'none';
  } else if (isMyTurn && !hasMove && state.boneyard.length === 0 && !state.gameOver) {
    if (drawBtn) drawBtn.style.display = 'none';
    if (passBtn) passBtn.style.display = '';
    if (!autoPassTimeout) {
      autoPassTimeout = setTimeout(() => { autoPassTimeout = null; passTurn(el); }, 1500);
    }
  } else {
    if (autoPassTimeout) { clearTimeout(autoPassTimeout); autoPassTimeout = null; }
    if (drawBtn) { drawBtn.style.display = ''; drawBtn.style.animation = ''; }
    if (passBtn) passBtn.style.display = 'none';
  }
}

function refreshHand() {
  const myHand = state.hands[state.myPlayerIndex];
  const validIds = new Set();

  if (state.currentPlayer === state.myPlayerIndex && !state.gameOver) {
    const moves = state.chain.length === 0
      ? myHand.map(t => ({ tile: t }))
      : rules.getValidMoves(myHand, state.leftEnd, state.rightEnd);
    moves.forEach(m => validIds.add(m.tile.id));
  }

  hand.setTiles(myHand, validIds);
  hand.setDisabled(state.currentPlayer !== state.myPlayerIndex || state.gameOver);
}

function confirmResign(el) {
  if (state.gameOver || state.matchOver) return;
  const confirmed = confirm('هل تريد الاستسلام؟');
  if (!confirmed) return;

  state.matchOver = true;
  state.gameOver = true;

  if (state.matchId) {
    net.post('domino-match.php', { action: 'resign', match_id: state.matchId }).catch(() => {});
  }

  audio.play('lose', 'game');
  setTimeout(() => {
    scene.exitGameMode();
    scene.replace('domino-result', {
      result: 'loss', mode: state.mode, resigned: true,
      myScore: state.matchScores[state.myPlayerIndex],
      oppScore: state.matchScores[1 - state.myPlayerIndex],
      rounds: state.roundNumber, matchId: state.matchId
    });
    bus.emit('game:ended', { gameKey: 'domino', result: 'loss', mode: state.mode });
  }, 500);
}

// ═══════════════════════════════════════
// SERVER
// ═══════════════════════════════════════

async function createServerRecord() {
  try {
    const data = await net.post('domino-match.php', {
      action: 'start',
      mode: 'bot',
      bot_level: state.botPersonality.strategy
    });
    if (data?.id) state.matchId = data.id;
  } catch (e) {}
}

// ═══════════════════════════════════════
// CLEANUP
// ═══════════════════════════════════════

export function unmountGame() {
  if (botTimeout) { clearTimeout(botTimeout); botTimeout = null; }
  if (autoPassTimeout) { clearTimeout(autoPassTimeout); autoPassTimeout = null; }
  liveSession?.cleanup?.();
  mp.stopDisconnectWatch?.();
  board?.destroy();
  hand?.destroy();
  drag?.destroy();
  state = null;
  liveSession = null;
}
