import * as scene from '../../../core/scene.js';
import * as audio from '../../../core/audio.js';
import * as bus from '../../../core/bus.js';
import * as store from '../../../core/store.js';
import * as net from '../../../core/net.js';
import * as matchSession from '../../../core/match-session.js';
import { emoji } from '../../../core/theme.js';
import { createGame, rollDice, getValidMoves, applyMove, nextTurn, hasWon, getPipCount, WHITE, BLACK, serializeState } from '../logic/rules.js';
import { getBotMove } from '../logic/bot.js';
import { createMatch, startNewGame, endGame, canUseCube, getMatchState } from '../logic/match.js';
import { createCube, canDouble, offerDouble, acceptDouble, declineDouble, shouldBotDouble, shouldBotAccept } from '../logic/doubling.js';
import { drawBoard, hitTest } from '../canvas/board-renderer.js';
import { drawDice, createRollAnimation } from '../canvas/dice-renderer.js';
import { createMoveAnimation } from '../canvas/move-animator.js';

// ═══ State ═══
let canvas, ctx, layout;
let game, match;
let selectedPiece = null;
let validMoves = [];
let highlights = [];
let isRolling = false;
let isAnimating = false;
let myColor = WHITE;
let params = {};
let turnTimer = null;
let turnTimeLeft = 30;
let rafId = null;
let diceRollFrame = 0;
let diceRollTotal = 24;
let particles = [];
let animatingChecker = null; // {x, y, type, scale}
let lastFrameTime = 0;
let container = null;

export function mountGame(el, p) {
  params = p || {};
  const { mode = 'bot', variant = 'sheshbesh', matchLength = 3, difficulty = 'medium', useCube = true } = params;

  myColor = mode === 'live' ? (params.color === 'black' ? BLACK : WHITE) : WHITE;
  match = createMatch(matchLength, variant);
  if (!useCube) match.cube = null;

  el.innerHTML = `
    <div class="bgg-container">
      <div class="bgg-top-bar">
        <div class="bgg-player-card bgg-player-top">
          <div class="bgg-avatar-ring bgg-opp-ring"><div class="bgg-avatar">🎯</div></div>
          <div class="bgg-player-info">
            <div class="bgg-name" id="name-top">${mode === 'bot' ? `بوت (${getDiffLabel(difficulty)})` : params.opponentName || 'خصم'}</div>
            <div class="bgg-pips" id="pips-top">167 نقطة</div>
          </div>
          <div class="bgg-score-badge" id="score-top">0</div>
        </div>
      </div>

      <div class="bgg-board-area">
        <canvas id="bg-canvas"></canvas>
        <div class="bgg-dice-overlay" id="dice-overlay">
          <button class="bgg-roll-btn" id="btn-roll">${emoji('game_die', '🎲', 26)} ارمي النرد</button>
        </div>
        <div class="bgg-cube-area" id="cube-area" style="display:none;">
          <button class="bgg-cube-btn" id="btn-double">
            <span class="bgg-cube-icon">⬡</span>
            <span class="bgg-cube-label">×2 ضاعف</span>
          </button>
        </div>
        <div class="bgg-double-offer" id="double-offer" style="display:none;">
          <div class="bgg-offer-title">مضاعفة!</div>
          <p class="bgg-offer-desc">الخصم يريد مضاعفة الرهان إلى <strong id="double-val">2</strong></p>
          <div class="bgg-offer-btns">
            <button class="bgg-accept-btn" id="btn-accept-double">${emoji('check', '✓', 16)} قبول</button>
            <button class="bgg-decline-btn" id="btn-decline-double">${emoji('cross', '✕', 16)} رفض</button>
          </div>
        </div>
        <div class="bgg-no-moves-toast" id="no-moves" style="display:none;">لا حركات متاحة!</div>
      </div>

      <div class="bgg-bottom-bar">
        <div class="bgg-player-card bgg-player-bottom">
          <div class="bgg-avatar-ring bgg-my-ring"><div class="bgg-avatar">👤</div></div>
          <div class="bgg-player-info">
            <div class="bgg-name" id="name-bottom">أنت</div>
            <div class="bgg-pips" id="pips-bottom">167 نقطة</div>
          </div>
          <div class="bgg-score-badge bgg-my-score" id="score-bottom">0</div>
        </div>
        <div class="bgg-actions">
          <button class="bgg-action-btn" id="btn-emote">${emoji('sparkles', '✨', 18)}</button>
          <button class="bgg-action-btn bgg-action-quit" id="btn-quit">✕</button>
        </div>
      </div>

      <div class="bgg-turn-badge" id="turn-indicator">دورك</div>
      <div class="bgg-emote-panel" id="emote-panel" style="display:none;"></div>
      <div class="bgg-match-info" id="match-info">
        <span class="bgg-match-label">ماتش ${matchLength}</span>
        <span class="bgg-variant-label">${getVariantLabel(variant)}</span>
      </div>
    </div>
    ${getGameStyles()}
  `;

  container = el.querySelector('.bgg-container');
  canvas = el.querySelector('#bg-canvas');
  ctx = canvas.getContext('2d');

  resizeCanvas();
  startNewGameRound();

  // Event bindings
  canvas.addEventListener('click', onCanvasClick);
  canvas.addEventListener('touchstart', onCanvasTouch, { passive: false });
  el.querySelector('#btn-roll').onclick = onRollClick;
  el.querySelector('#btn-double').onclick = onDoubleClick;
  el.querySelector('#btn-accept-double').onclick = onAcceptDouble;
  el.querySelector('#btn-decline-double').onclick = onDeclineDouble;
  el.querySelector('#btn-emote').onclick = toggleEmotePanel;
  el.querySelector('#btn-quit').onclick = onQuit;
  window.addEventListener('resize', resizeCanvas);

  // Multiplayer
  if (mode === 'live') {
    matchSession.create(params.matchId, 'backgammon', {
      onOpponentMove: handleServerState,
      onOpponentDisconnect: () => bus.emit('toast', { text: 'الخصم انقطع...' }),
      onOpponentAbandon: () => endMatchWithWin()
    });
  }

  setupEmotePanel(el);
  startGameLoop();
}

export function unmountGame() {
  if (rafId) cancelAnimationFrame(rafId);
  rafId = null;
  window.removeEventListener('resize', resizeCanvas);
  matchSession.destroy();
  clearInterval(turnTimer);
  container = null;
}

// ═══════════════════════════════════════
// 60 FPS GAME LOOP
// ═══════════════════════════════════════

function startGameLoop() {
  lastFrameTime = performance.now();
  function loop(now) {
    const dt = (now - lastFrameTime) / 1000;
    lastFrameTime = now;
    update(dt);
    render();
    rafId = requestAnimationFrame(loop);
  }
  rafId = requestAnimationFrame(loop);
}

function update(dt) {
  // Update particles
  for (let i = particles.length - 1; i >= 0; i--) {
    const p = particles[i];
    p.x += p.vx * dt;
    p.y += p.vy * dt;
    p.vy += (p.gravity || 200) * dt;
    p.alpha -= (p.decay || 1.5) * dt;
    if (p.rot !== undefined) p.rot += p.vr * dt;
    if (p.alpha <= 0) particles.splice(i, 1);
  }
}

function render() {
  if (!ctx || !game) return;
  const w = canvas.width;
  const h = canvas.height;

  layout = drawBoard(ctx, w, h, game.state, {
    highlights,
    selectedPoint: selectedPiece?.from ?? null,
    particles
  });

  // Draw dice
  if (game.dice && !isRolling) {
    const diceCount = game.dice[0] === game.dice[1] ? 4 : 2;
    const allDice = game.dice[0] === game.dice[1] ? [game.dice[0], game.dice[0], game.dice[0], game.dice[0]] : game.dice;
    const totalDiceW = diceCount * 38 + (diceCount - 1) * 12;
    const diceX = w / 2 - totalDiceW / 2;
    const diceY = h / 2 - 19;

    const usedIndices = getUsedDiceIndices();
    drawDice(ctx, diceX, diceY, allDice, { used: usedIndices });
  }

  // Rolling dice animation
  if (isRolling) {
    const fakeVals = [Math.ceil(Math.random() * 6), Math.ceil(Math.random() * 6)];
    const diceX = w / 2 - 44;
    const diceY = h / 2 - 19;
    drawDice(ctx, diceX, diceY, fakeVals, { rolling: true, frame: diceRollFrame, totalFrames: diceRollTotal });
  }

  // Animating checker
  if (animatingChecker) {
    const { x, y, type, scale = 1 } = animatingChecker;
    ctx.save();
    ctx.translate(x, y);
    ctx.scale(scale, scale);
    const r = layout.checkerR;
    const isW = type === WHITE;
    // Shadow
    ctx.beginPath();
    ctx.arc(1, 3, r, 0, Math.PI * 2);
    ctx.fillStyle = 'rgba(0,0,0,0.5)';
    ctx.fill();
    // Checker
    ctx.beginPath();
    ctx.arc(0, 0, r, 0, Math.PI * 2);
    const grad = ctx.createRadialGradient(-r * 0.3, -r * 0.3, r * 0.1, 0, 0, r);
    if (isW) { grad.addColorStop(0, '#FFF'); grad.addColorStop(1, '#C8A882'); }
    else { grad.addColorStop(0, '#555'); grad.addColorStop(1, '#0A0A0A'); }
    ctx.fillStyle = grad;
    ctx.fill();
    ctx.strokeStyle = isW ? 'rgba(160,120,60,0.5)' : 'rgba(100,100,100,0.5)';
    ctx.lineWidth = 1.5;
    ctx.stroke();
    // Glow
    ctx.beginPath();
    ctx.arc(0, 0, r + 4, 0, Math.PI * 2);
    ctx.strokeStyle = 'rgba(255,215,0,0.6)';
    ctx.lineWidth = 2;
    ctx.shadowColor = '#FFD700';
    ctx.shadowBlur = 12;
    ctx.stroke();
    ctx.shadowBlur = 0;
    ctx.restore();
  }
}

// ═══════════════════════════════════════
// PARTICLES
// ═══════════════════════════════════════

function spawnHitParticles(x, y) {
  const colors = ['#EF4444', '#F97316', '#FBBF24', '#FFF'];
  for (let i = 0; i < 12; i++) {
    const angle = (Math.PI * 2 * i) / 12 + Math.random() * 0.3;
    const speed = 80 + Math.random() * 120;
    particles.push({
      x, y,
      vx: Math.cos(angle) * speed,
      vy: Math.sin(angle) * speed - 60,
      alpha: 1,
      size: 2 + Math.random() * 3,
      color: colors[Math.floor(Math.random() * colors.length)],
      gravity: 300,
      decay: 2
    });
  }
}

function spawnBearOffParticles(x, y) {
  const colors = ['#10B981', '#34D399', '#6EE7B7', '#FFD700'];
  for (let i = 0; i < 8; i++) {
    const angle = -Math.PI / 2 + (Math.random() - 0.5) * Math.PI * 0.8;
    const speed = 60 + Math.random() * 80;
    particles.push({
      x, y,
      vx: Math.cos(angle) * speed,
      vy: Math.sin(angle) * speed,
      alpha: 1,
      size: 2 + Math.random() * 2.5,
      color: colors[Math.floor(Math.random() * colors.length)],
      shape: Math.random() > 0.5 ? 'star' : 'circle',
      rot: 0, vr: (Math.random() - 0.5) * 8,
      gravity: 150,
      decay: 1.8
    });
  }
}

function spawnWinParticles() {
  const colors = ['#FFD700', '#FFA500', '#FF6347', '#10B981', '#8B5CF6', '#06B6D4'];
  for (let i = 0; i < 30; i++) {
    const x = Math.random() * canvas.width;
    particles.push({
      x, y: canvas.height + 10,
      vx: (Math.random() - 0.5) * 60,
      vy: -(200 + Math.random() * 200),
      alpha: 1,
      size: 3 + Math.random() * 4,
      color: colors[Math.floor(Math.random() * colors.length)],
      shape: 'star',
      rot: 0, vr: (Math.random() - 0.5) * 10,
      gravity: 80,
      decay: 0.7
    });
  }
}

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

function startNewGameRound() {
  game = startNewGame(match);
  selectedPiece = null;
  validMoves = [];
  highlights = [];
  isRolling = false;
  isAnimating = false;
  animatingChecker = null;
  particles = [];
  updateUI();
  updateTurnIndicator();

  if (game.turn !== myColor && params.mode === 'bot') {
    setTimeout(doBotTurn, 1000);
  }
}

function getUsedDiceIndices() {
  const usedIndices = [];
  const isDoubles = game.dice[0] === game.dice[1];
  const allDice = isDoubles ? [game.dice[0], game.dice[0], game.dice[0], game.dice[0]] : [...game.dice];

  for (const played of game.movesPlayed) {
    for (let j = 0; j < allDice.length; j++) {
      if (!usedIndices.includes(j) && allDice[j] === played) {
        usedIndices.push(j);
        break;
      }
    }
  }
  return usedIndices;
}

// ═══════════════════════════════════════
// UI UPDATES
// ═══════════════════════════════════════

function resizeCanvas() {
  if (!canvas) return;
  const area = canvas.parentElement;
  const w = Math.min(area.clientWidth - 8, 420);
  const h = Math.min(w * 1.12, 470);
  const dpr = Math.min(window.devicePixelRatio || 1, 2);
  canvas.width = w * dpr;
  canvas.height = h * dpr;
  canvas.style.width = w + 'px';
  canvas.style.height = h + 'px';
  ctx.scale(dpr, dpr);
  // Reset scale on next render
  canvas._logicalW = w;
  canvas._logicalH = h;
}

function updateUI() {
  if (!game || !container) return;
  const topColor = myColor === WHITE ? BLACK : WHITE;

  setText('#pips-top', getPipCount(game.state, topColor) + ' نقطة');
  setText('#pips-bottom', getPipCount(game.state, myColor) + ' نقطة');
  setText('#score-top', String(match.scores[topColor]));
  setText('#score-bottom', String(match.scores[myColor]));

  const rollBtn = container.querySelector('#btn-roll');
  const isMyTurn = game.turn === myColor;
  const diceOverlay = container.querySelector('#dice-overlay');
  if (diceOverlay) diceOverlay.style.display = (isMyTurn && !game.dice && !isAnimating && !isRolling) ? '' : 'none';

  const cubeArea = container.querySelector('#cube-area');
  if (match.cube && canUseCube(match) && isMyTurn && !game.dice && canDouble(match.cube, myColor)) {
    cubeArea.style.display = '';
  } else {
    cubeArea.style.display = 'none';
  }
}

function updateTurnIndicator() {
  const el = container?.querySelector('#turn-indicator');
  if (!el) return;
  const isMyTurn = game.turn === myColor;
  el.textContent = isMyTurn ? 'دورك' : 'دور الخصم';
  el.className = `bgg-turn-badge ${isMyTurn ? 'bgg-turn-mine' : 'bgg-turn-opp'}`;
}

function setText(sel, text) {
  const el = container?.querySelector(sel);
  if (el) el.textContent = text;
}

// ═══════════════════════════════════════
// INPUT
// ═══════════════════════════════════════

function onCanvasClick(e) {
  if (isAnimating || isRolling) return;
  if (game.turn !== myColor && params.mode !== 'local-multi') return;
  if (!game.dice || game.movesLeft.length === 0) return;

  const rect = canvas.getBoundingClientRect();
  const scaleX = (canvas._logicalW || canvas.width) / rect.width;
  const scaleY = (canvas._logicalH || canvas.height) / rect.height;
  const x = (e.clientX - rect.left) * scaleX;
  const y = (e.clientY - rect.top) * scaleY;
  handleBoardTap(x, y);
}

function onCanvasTouch(e) {
  if (isAnimating || isRolling) return;
  if (game.turn !== myColor && params.mode !== 'local-multi') return;
  if (!game.dice || game.movesLeft.length === 0) return;

  e.preventDefault();
  const touch = e.touches[0];
  const rect = canvas.getBoundingClientRect();
  const scaleX = (canvas._logicalW || canvas.width) / rect.width;
  const scaleY = (canvas._logicalH || canvas.height) / rect.height;
  const x = (touch.clientX - rect.left) * scaleX;
  const y = (touch.clientY - rect.top) * scaleY;
  handleBoardTap(x, y);
}

function handleBoardTap(x, y) {
  const hit = hitTest(x, y, layout, game.state);
  if (!hit) { clearSelection(); return; }

  if (selectedPiece && hit.type === 'point' && highlights.includes(hit.index)) {
    executeMove(hit.index);
    return;
  }
  if (selectedPiece && hit.type === 'bearoff' && highlights.includes('off')) {
    executeMove('off');
    return;
  }

  if (hit.type === 'point') selectPoint(hit.index);
  else if (hit.type === 'bar' && hit.player === game.turn) selectBar();
  else clearSelection();
}

function selectPoint(pointIndex) {
  const pieces = game.state.points[pointIndex];
  if (pieces.length === 0 || pieces[pieces.length - 1].type !== game.turn) {
    clearSelection();
    return;
  }
  const piece = pieces[pieces.length - 1];
  const moves = getValidMoves(game).filter(m => m.piece.id === piece.id);
  if (moves.length === 0) { clearSelection(); return; }

  selectedPiece = { id: piece.id, from: pointIndex, moves };
  highlights = moves.map(m => m.to === 'off' ? 'off' : m.to);
  audio.play('click');
}

function selectBar() {
  const moves = getValidMoves(game).filter(m => m.from === 'bar' || m.from === null);
  if (moves.length === 0) return;
  selectedPiece = { id: moves[0].piece.id, from: 'bar', moves };
  highlights = moves.map(m => m.to);
  audio.play('click');
}

function clearSelection() {
  selectedPiece = null;
  highlights = [];
}

function executeMove(destination) {
  if (!selectedPiece) return;
  const move = selectedPiece.moves.find(m => m.to === destination);
  if (!move) return;

  isAnimating = true;
  const fromPos = selectedPiece.from;
  const toPos = destination;
  const pieceType = game.turn;

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

  // Start arc animation
  createMoveAnimation(fromPos, toPos, layout,
    (frame) => {
      animatingChecker = { x: frame.x, y: frame.y, type: pieceType, scale: frame.scale };
    },
    () => {
      animatingChecker = null;
      const actions = applyMove(game, move.piece.id, move.steps);
      if (!actions) { isAnimating = false; return; }

      if (actions.some(a => a.type === 'hit')) {
        audio.play('sfx_bg_piece_hit', 'game');
        const hitPos = layout ? { x: canvas._logicalW / 2, y: canvas._logicalH / 2 } : { x: 180, y: 200 };
        spawnHitParticles(hitPos.x, hitPos.y);
      }
      if (actions.some(a => a.type === 'bear')) {
        audio.play('sfx_bg_bear_off', 'game');
        spawnBearOffParticles(canvas._logicalW - 20, canvas._logicalH / 2);
      }

      clearSelection();
      isAnimating = false;
      updateUI();

      if (game.isOver) { handleGameOver(); return; }
      if (game.movesLeft.length === 0) { endTurn(); return; }

      const remaining = getValidMoves(game);
      if (remaining.length === 0) endTurn();
    }
  );
}

function endTurn() {
  nextTurn(game);
  updateUI();
  updateTurnIndicator();

  if (params.mode === 'bot' && game.turn !== myColor) {
    setTimeout(doBotTurn, 700);
  } else if (params.mode === 'live') {
    syncToServer();
  }
}

// ═══════════════════════════════════════
// DICE
// ═══════════════════════════════════════

function onRollClick() {
  if (game.dice || isRolling || isAnimating) return;
  if (game.turn !== myColor && params.mode !== 'local-multi') return;

  isRolling = true;
  diceRollFrame = 0;
  audio.play('sfx_bg_dice_roll', 'game');

  createRollAnimation(
    (frame, total) => { diceRollFrame = frame; diceRollTotal = total; },
    () => {
      isRolling = false;
      diceRollFrame = 0;
      rollDice(game);

      if (game.movesLeft.length === 0) {
        showNoMoves();
        setTimeout(endTurn, 1200);
        return;
      }
      updateUI();

      // Auto-play single forced move
      const moves = getValidMoves(game);
      if (moves.length === 1 && game.movesLeft.length === 1) {
        setTimeout(() => {
          selectedPiece = { id: moves[0].piece.id, from: moves[0].from, moves };
          executeMove(moves[0].to);
        }, 400);
      }
    }
  );
}

function showNoMoves() {
  const el = container?.querySelector('#no-moves');
  if (!el) return;
  el.style.display = '';
  el.classList.add('bgg-toast-show');
  setTimeout(() => { el.style.display = 'none'; el.classList.remove('bgg-toast-show'); }, 1200);
}

// ═══════════════════════════════════════
// DOUBLING CUBE
// ═══════════════════════════════════════

function onDoubleClick() {
  if (!match.cube || !canDouble(match.cube, myColor)) return;
  if (game.dice) return;
  audio.play('sfx_bg_double', 'game');

  if (params.mode === 'bot') {
    offerDouble(match.cube, myColor);
    const myPips = getPipCount(game.state, myColor);
    const oppPips = getPipCount(game.state, myColor === WHITE ? BLACK : WHITE);

    if (shouldBotAccept(match.cube, oppPips, myPips, params.difficulty)) {
      acceptDouble(match.cube);
      bus.emit('toast', { text: `البوت قبل المضاعفة! ×${match.cube.value}` });
    } else {
      declineDouble(match.cube);
      bus.emit('toast', { text: 'البوت رفض! فزت بالجولة' });
      const result = endGame(match, myColor, 1);
      showGameResult(result);
      return;
    }
    updateUI();
  } else if (params.mode === 'live') {
    offerDouble(match.cube, myColor);
    syncToServer();
  }
}

function onAcceptDouble() {
  if (!match.cube) return;
  acceptDouble(match.cube);
  audio.play('sfx_bg_double', 'game');
  container.querySelector('#double-offer').style.display = 'none';
  updateUI();
  if (params.mode === 'live') syncToServer();
}

function onDeclineDouble() {
  if (!match.cube) return;
  declineDouble(match.cube);
  container.querySelector('#double-offer').style.display = 'none';
  const result = endGame(match, game.turn, 1);
  showGameResult(result);
}

// ═══════════════════════════════════════
// BOT AI
// ═══════════════════════════════════════

function doBotTurn() {
  if (game.turn === myColor || game.isOver) return;

  // Bot considers doubling
  if (match.cube && canUseCube(match) && canDouble(match.cube, game.turn) && !game.dice) {
    const botPips = getPipCount(game.state, game.turn);
    const myPips = getPipCount(game.state, myColor);
    if (shouldBotDouble(match.cube, botPips, myPips, params.difficulty)) {
      offerDouble(match.cube, game.turn);
      audio.play('sfx_bg_double', 'game');
      const offerUI = container.querySelector('#double-offer');
      const valEl = container.querySelector('#double-val');
      if (offerUI) offerUI.style.display = '';
      if (valEl) valEl.textContent = match.cube.value * 2;
      return;
    }
  }

  // Roll
  audio.play('sfx_bg_dice_roll', 'game');
  isRolling = true;
  diceRollFrame = 0;

  createRollAnimation(
    (frame, total) => { diceRollFrame = frame; diceRollTotal = total; },
    () => {
      isRolling = false;
      rollDice(game);

      if (game.movesLeft.length === 0) {
        setTimeout(endTurn, 700);
        return;
      }
      makeBotMoves();
    }
  );
}

function makeBotMoves() {
  if (game.movesLeft.length === 0 || game.isOver) {
    if (!game.isOver) endTurn();
    else handleGameOver();
    return;
  }

  const move = getBotMove(game, params.difficulty);
  if (!move) { endTurn(); return; }

  const fromPos = move.from;
  const toPos = move.to;
  const pieceType = game.turn;

  isAnimating = true;
  createMoveAnimation(fromPos, toPos, layout,
    (frame) => { animatingChecker = { x: frame.x, y: frame.y, type: pieceType, scale: frame.scale }; },
    () => {
      animatingChecker = null;
      audio.play('sfx_bg_piece_move', 'game');
      const actions = applyMove(game, move.piece.id, move.steps);

      if (actions?.some(a => a.type === 'hit')) {
        audio.play('sfx_bg_piece_hit', 'game');
        spawnHitParticles(canvas._logicalW / 2, canvas._logicalH / 2);
      }
      if (actions?.some(a => a.type === 'bear')) {
        audio.play('sfx_bg_bear_off', 'game');
        spawnBearOffParticles(canvas._logicalW - 20, canvas._logicalH / 2);
      }

      isAnimating = false;
      updateUI();

      if (game.isOver) { handleGameOver(); return; }
      setTimeout(makeBotMoves, 350);
    }
  );
}

// ═══════════════════════════════════════
// GAME OVER
// ═══════════════════════════════════════

function handleGameOver() {
  const winner = game.winner;
  const isMyWin = winner === myColor;
  const result = endGame(match, winner, game.score || 1);

  audio.play(isMyWin ? 'sfx_bg_win_game' : 'lose', 'game');
  if (isMyWin) spawnWinParticles();

  showGameResult(result);
}

function showGameResult(result) {
  updateUI();

  if (result.matchOver) {
    audio.play(result.winner === myColor ? 'sfx_bg_win_match' : 'lose', 'game');
    if (result.winner === myColor) spawnWinParticles();
    setTimeout(() => {
      if (params.mode === 'live') syncComplete(result);
      scene.replace('backgammon-result', {
        winner: result.winner === myColor ? 'you' : 'opponent',
        scores: result.scores,
        matchLength: match.length,
        mode: params.mode
      });
    }, 2000);
  } else {
    const who = result.winner === myColor ? 'فزت' : 'البوت فاز';
    const scoreLabel = result.gameScore === 3 ? 'باكگمون!' : result.gameScore === 2 ? 'گامون!' : '';
    bus.emit('toast', { text: `${who} بالجولة ${scoreLabel} (+${result.stake})` });
    setTimeout(startNewGameRound, 2500);
  }
}

function endMatchWithWin() {
  scene.replace('backgammon-result', {
    winner: 'you', scores: match.scores, matchLength: match.length,
    mode: params.mode, reason: 'abandon'
  });
}

// ═══════════════════════════════════════
// MULTIPLAYER SYNC
// ═══════════════════════════════════════

function syncToServer() {
  if (params.mode !== 'live') return;
  net.post('backgammon-match.php', {
    action: 'move', match_id: params.matchId,
    game_state: serializeState(game),
    match_state: getMatchState(match),
    cube: match.cube
  }).catch(() => {});
}

function syncComplete(result) {
  net.post('backgammon-match.php', {
    action: 'complete', match_id: params.matchId,
    winner: result.winner === myColor ? store.get('auth.userId') : 'opponent',
    reason: 'normal'
  }).catch(() => {});
}

function handleServerState(data) {
  if (!data || data.error) return;
  matchSession.markOpponentActive();
  if (data.game_state) {
    Object.assign(game, data.game_state);
    if (data.match_state) match.scores = data.match_state.scores || match.scores;
    if (data.cube) match.cube = data.cube;
    updateUI();
    updateTurnIndicator();
  }
}

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

function setupEmotePanel(el) {
  const panel = el.querySelector('#emote-panel');
  const emotes = ['🎲', '😤', '🤔', '👏', '😂', '🔥', '💀', '🫡'];
  const phrases = ['!لعبة حلوة', '!حركة ممتازة', '!حظ', '...فكّر أسرع', '?ريماتش', 'gg wp'];

  panel.innerHTML = `
    <div class="bgg-emotes">${emotes.map(e => `<button class="bgg-emote-btn">${e}</button>`).join('')}</div>
    <div class="bgg-phrases">${phrases.map(p => `<button class="bgg-phrase-btn">${p}</button>`).join('')}</div>
  `;

  let lastEmote = 0;
  panel.querySelectorAll('.bgg-emote-btn').forEach(btn => {
    btn.onclick = () => {
      if (Date.now() - lastEmote < 3000) return;
      lastEmote = Date.now();
      audio.play('sfx_emote');
      showBubble(btn.textContent, 'emote');
      panel.style.display = 'none';
      if (params.mode === 'live') {
        net.post('backgammon-match.php', { action: 'emote', match_id: params.matchId, emote: btn.textContent }).catch(() => {});
      }
    };
  });
  panel.querySelectorAll('.bgg-phrase-btn').forEach(btn => {
    btn.onclick = () => {
      if (Date.now() - lastEmote < 3000) return;
      lastEmote = Date.now();
      audio.play('sfx_emote');
      showBubble(btn.textContent, 'phrase');
      panel.style.display = 'none';
    };
  });
}

function toggleEmotePanel() {
  const panel = container?.querySelector('#emote-panel');
  if (panel) panel.style.display = panel.style.display === 'none' ? '' : 'none';
}

function showBubble(text, type) {
  if (!container) return;
  const bubble = document.createElement('div');
  bubble.className = `bgg-bubble bgg-bubble-${type}`;
  bubble.textContent = text;
  container.appendChild(bubble);
  setTimeout(() => bubble.remove(), 2500);
}

function onQuit() {
  audio.play('click');
  if (params.mode === 'live') {
    net.post('backgammon-match.php', { action: 'leave', match_id: params.matchId }).catch(() => {});
    matchSession.destroy();
  }
  scene.exitGameMode();
  scene.replace('backgammon-room', { mode: 'menu' });
}

// ═══════════════════════════════════════
// HELPERS
// ═══════════════════════════════════════

function getDiffLabel(d) {
  if (d === 'easy') return 'سهل';
  if (d === 'hard') return 'صعب';
  return 'متوسط';
}

function getVariantLabel(v) {
  if (v === 'mahbousa') return 'محبوسة';
  if (v === 'thirtyone') return '٣١';
  return 'شيش بيش';
}

function getGameStyles() {
  return `<style>
.bgg-container {
  position:relative;display:flex;flex-direction:column;
  height:100%;background:linear-gradient(180deg,#060A10 0%,#0A1020 100%);
  color:#f8fafc;overflow:hidden;font-family:var(--font-ar,'IBM Plex Sans Arabic',sans-serif);
}
.bgg-top-bar,.bgg-bottom-bar {
  display:flex;align-items:center;padding:10px 14px;gap:10px;
  background:rgba(0,0,0,0.4);backdrop-filter:blur(8px);
  border-bottom:1px solid rgba(255,255,255,0.04);
}
.bgg-bottom-bar { border-bottom:none;border-top:1px solid rgba(255,255,255,0.04);justify-content:space-between; }
.bgg-player-card { display:flex;align-items:center;gap:10px;flex:1; }
.bgg-avatar-ring {
  width:40px;height:40px;border-radius:50%;padding:2px;
  background:conic-gradient(from 0deg,rgba(148,163,184,0.3),rgba(148,163,184,0.1));
}
.bgg-my-ring { background:conic-gradient(from 0deg,rgba(16,185,129,0.5),rgba(16,185,129,0.2)); }
.bgg-opp-ring { background:conic-gradient(from 0deg,rgba(239,68,68,0.4),rgba(239,68,68,0.15)); }
.bgg-avatar {
  width:100%;height:100%;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,0.04);font-size:18px;
}
.bgg-player-info { flex:1; }
.bgg-name { font-size:13px;font-weight:700;color:#f8fafc; }
.bgg-pips { font-size:11px;color:#64748b; }
.bgg-score-badge {
  font-size:18px;font-weight:800;color:#94a3b8;
  min-width:28px;height:28px;border-radius:8px;
  display:flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.06);
}
.bgg-my-score { color:#d4940a;border-color:rgba(212,148,10,0.2);background:rgba(212,148,10,0.06); }

.bgg-board-area {
  flex:1;display:flex;align-items:center;justify-content:center;
  position:relative;padding:4px;
}
#bg-canvas { border-radius:8px;touch-action:none;cursor:pointer; }

.bgg-dice-overlay {
  position:absolute;bottom:16px;left:50%;transform:translateX(-50%);z-index:5;
}
.bgg-roll-btn {
  display:flex;align-items:center;gap:8px;
  padding:14px 28px;border-radius:16px;border:none;
  background:linear-gradient(135deg,#d4940a 0%,#8B4513 100%);
  color:#fff;font-size:16px;font-weight:800;cursor:pointer;
  box-shadow:0 6px 24px rgba(212,148,10,0.5),inset 0 1px 0 rgba(255,255,255,0.2);
  animation:rollPulse 2.5s ease-in-out infinite;
  transition:transform 0.15s var(--ease-spring);
}
.bgg-roll-btn:active { transform:scale(0.92);animation:none; }
@keyframes rollPulse {
  0%,100%{box-shadow:0 6px 24px rgba(212,148,10,0.4)}
  50%{box-shadow:0 6px 32px rgba(212,148,10,0.7),0 0 60px rgba(212,148,10,0.15)}
}

.bgg-cube-area { position:absolute;top:12px;right:12px;z-index:5; }
.bgg-cube-btn {
  display:flex;align-items:center;gap:6px;
  padding:8px 14px;border-radius:10px;border:none;
  background:rgba(139,92,246,0.15);border:1.5px solid rgba(139,92,246,0.4);
  color:#a78bfa;font-size:12px;font-weight:700;cursor:pointer;
  transition:all 0.2s;
}
.bgg-cube-btn:active { transform:scale(0.9);background:rgba(139,92,246,0.3); }
.bgg-cube-icon { font-size:16px; }

.bgg-double-offer {
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  background:rgba(10,16,32,0.95);border:1.5px solid rgba(212,148,10,0.5);
  border-radius:20px;padding:24px 28px;text-align:center;z-index:20;
  backdrop-filter:blur(12px);box-shadow:0 12px 40px rgba(0,0,0,0.6);
  animation:offerIn 0.3s var(--ease-spring);
}
@keyframes offerIn { from{opacity:0;transform:translate(-50%,-50%) scale(0.85)} to{opacity:1;transform:translate(-50%,-50%) scale(1)} }
.bgg-offer-title { font-size:18px;font-weight:800;color:#d4940a;margin-bottom:8px; }
.bgg-offer-desc { font-size:13px;color:#94a3b8;margin:0 0 16px; }
.bgg-offer-btns { display:flex;gap:10px;justify-content:center; }
.bgg-accept-btn,.bgg-decline-btn {
  padding:10px 22px;border-radius:12px;border:none;font-weight:700;font-size:13px;cursor:pointer;
  transition:transform 0.15s var(--ease-spring);
}
.bgg-accept-btn { background:linear-gradient(135deg,#10B981,#059669);color:#fff;box-shadow:0 4px 12px rgba(16,185,129,0.3); }
.bgg-decline-btn { background:linear-gradient(135deg,#EF4444,#DC2626);color:#fff;box-shadow:0 4px 12px rgba(239,68,68,0.3); }
.bgg-accept-btn:active,.bgg-decline-btn:active { transform:scale(0.9); }

.bgg-no-moves-toast {
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  padding:12px 24px;border-radius:12px;
  background:rgba(239,68,68,0.15);border:1px solid rgba(239,68,68,0.3);
  color:#f87171;font-size:14px;font-weight:700;
  animation:toastIn 0.3s var(--ease-spring);
}
@keyframes toastIn { from{opacity:0;transform:translate(-50%,-50%) scale(0.8)} }

.bgg-actions { display:flex;gap:8px; }
.bgg-action-btn {
  width:38px;height:38px;border-radius:12px;border:none;
  background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.06);
  color:#94a3b8;font-size:16px;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  transition:all 0.15s;
}
.bgg-action-btn:active { transform:scale(0.85);background:rgba(255,255,255,0.08); }
.bgg-action-quit { color:#ef4444;border-color:rgba(239,68,68,0.2); }

.bgg-turn-badge {
  position:absolute;top:50%;left:6px;transform:translateY(-50%);
  writing-mode:vertical-rl;font-size:10px;font-weight:800;letter-spacing:0.5px;
  padding:8px 5px;border-radius:8px;
  transition:all 0.3s var(--ease-spring);
}
.bgg-turn-mine { background:rgba(16,185,129,0.12);color:#34D399;border:1px solid rgba(16,185,129,0.2); }
.bgg-turn-opp { background:rgba(239,68,68,0.1);color:#f87171;border:1px solid rgba(239,68,68,0.15); }

.bgg-match-info {
  position:absolute;top:50%;right:6px;transform:translateY(-50%);
  display:flex;flex-direction:column;align-items:center;gap:4px;
}
.bgg-match-label,.bgg-variant-label {
  writing-mode:vertical-rl;font-size:9px;font-weight:600;color:#475569;
  padding:4px 3px;border-radius:4px;background:rgba(255,255,255,0.02);
}

.bgg-emote-panel {
  position:absolute;bottom:64px;right:14px;
  background:rgba(10,16,32,0.95);border:1px solid rgba(255,255,255,0.08);
  border-radius:16px;padding:14px;z-index:25;max-width:260px;
  backdrop-filter:blur(12px);box-shadow:0 8px 32px rgba(0,0,0,0.5);
  animation:panelIn 0.2s var(--ease-spring);
}
@keyframes panelIn { from{opacity:0;transform:translateY(8px) scale(0.95)} }
.bgg-emotes { display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px; }
.bgg-emote-btn {
  width:38px;height:38px;border-radius:10px;border:none;
  background:rgba(255,255,255,0.05);font-size:20px;cursor:pointer;
  transition:transform 0.15s var(--ease-spring);
}
.bgg-emote-btn:active { transform:scale(0.85);background:rgba(255,255,255,0.1); }
.bgg-phrases { display:flex;flex-direction:column;gap:4px; }
.bgg-phrase-btn {
  padding:7px 12px;border-radius:8px;border:none;
  background:rgba(255,255,255,0.03);color:#94a3b8;
  font-size:12px;cursor:pointer;text-align:right;
  transition:background 0.15s;
}
.bgg-phrase-btn:active { background:rgba(255,255,255,0.08); }

.bgg-bubble {
  position:absolute;pointer-events:none;z-index:30;
  animation:bubbleFloat 2.5s ease-out forwards;
}
.bgg-bubble-emote { bottom:80px;right:60px;font-size:44px; }
.bgg-bubble-phrase {
  bottom:80px;right:20px;
  padding:10px 16px;border-radius:14px;
  background:rgba(212,148,10,0.12);border:1px solid rgba(212,148,10,0.25);
  color:#d4940a;font-size:13px;font-weight:700;
}
@keyframes bubbleFloat {
  0%{opacity:1;transform:translateY(0) scale(1)}
  70%{opacity:1}
  100%{opacity:0;transform:translateY(-50px) scale(1.15)}
}
</style>`;
}
