var BackgammonGame = (function() {
  'use strict';

  var C = BackgammonConstants;
  var UI = BackgammonUI;
  var Bot = BackgammonBot;

  var state = null;
  var undoStack = [];

  function init(opts) {
    state = {
      mode: opts.mode || 'local',
      players: opts.players || [
        { id: 'p0', name: 'اللاعب 1', type: 'human' },
        { id: 'p1', name: 'اللاعب 2', type: 'human' }
      ],
      board: C.INITIAL_BOARD.slice(),
      bar: [0, 0],
      borneOff: [0, 0],
      currentTurn: 0,
      dice: null,
      diceRemaining: [],
      phase: 'awaiting_roll',
      scores: [0, 0],
      matchLength: opts.matchLength || 1,
      doublingCube: { value: 1, owner: null },
      moves: [],
      onGameEnd: opts.onGameEnd || null
    };

    if (opts.bots) {
      for (var i = 0; i < opts.bots.length; i++) {
        var botIdx = opts.bots[i].index;
        state.players[botIdx].type = 'bot';
        state.players[botIdx].difficulty = opts.bots[i].difficulty || 'medium';
        state.players[botIdx].name = 'بوت (' + (opts.bots[i].difficulty === 'easy' ? 'سهل' : opts.bots[i].difficulty === 'hard' ? 'صعب' : 'متوسط') + ')';
      }
    }

    UI.init(state);
    doOpeningRoll();
  }

  function doOpeningRoll() {
    var d1 = Math.ceil(Math.random() * 6);
    var d2 = Math.ceil(Math.random() * 6);
    while (d1 === d2) {
      d1 = Math.ceil(Math.random() * 6);
      d2 = Math.ceil(Math.random() * 6);
    }

    state.currentTurn = (d1 > d2) ? 0 : 1;
    state.dice = [d1, d2];
    state.diceRemaining = [d1, d2];
    state.phase = 'moving';

    UI.showLog('رمي الافتتاح: ' + d1 + ' و ' + d2 + ' — ' + state.players[state.currentTurn].name + ' يبدأ');
    UI.render(state);

    if (state.players[state.currentTurn].type === 'bot') {
      UI.setStatus('انتظر...');
      setTimeout(function() { executeBotTurn(); }, 600);
    } else {
      beginHumanTurn();
    }
  }

  // ─── Auto-roll at start of turn ────────────────────────────────────────────

  function rollDice() {
    if (state.phase !== 'awaiting_roll') return;
    if (state.players[state.currentTurn].type !== 'human') return;

    var d1 = Math.ceil(Math.random() * 6);
    var d2 = Math.ceil(Math.random() * 6);
    state.dice = [d1, d2];
    state.diceRemaining = C.getDiceRemaining(d1, d2);
    state.phase = 'moving';
    undoStack = [];

    UI.showLog(state.players[state.currentTurn].name + ' رمى ' + d1 + ' و ' + d2);
    UI.render(state);
    beginHumanTurn();
  }

  // ─── Smart turn start ──────────────────────────────────────────────────────

  function beginHumanTurn() {
    if (!C.canMove(state.board, state.bar, state.borneOff, state.currentTurn, state.diceRemaining)) {
      UI.setStatus('لا توجد حركة متاحة');
      UI.showLog('لا توجد حركة — تخطي');
      setTimeout(function() { endTurn(); }, 1000);
      return;
    }

    // Check if only one complete sequence exists — auto-execute with confirmation
    var allSeqs = C.getAllMovesForDice(state.board, state.bar, state.borneOff, state.currentTurn, state.diceRemaining);
    if (allSeqs.length === 1 && allSeqs[0].length === state.diceRemaining.length) {
      UI.setStatus('حركة واحدة ممكنة — جاري التنفيذ...');
      autoExecuteSequence(allSeqs[0]);
      return;
    }

    UI.setStatus('اختر قطعة');
    showMovableSources();
  }

  // ─── Show which pieces can move ───────────────────────────────────────────

  function showMovableSources() {
    var sources = getMovableSources();
    UI.highlightSources(sources);
  }

  function getMovableSources() {
    var sources = [];
    var player = state.currentTurn;

    // Bar first
    if (state.bar[player] > 0) {
      return ['bar'];
    }

    for (var i = 0; i < 24; i++) {
      var count = state.board[i];
      var isOwn = (player === 0) ? count > 0 : count < 0;
      if (isOwn) {
        var moves = getValidMovesForFrom(i);
        if (moves.length > 0) sources.push(i);
      }
    }
    return sources;
  }

  // ─── Main click handler ────────────────────────────────────────────────────

  function handlePointClick(pointOrAction) {
    if (pointOrAction === 'roll') { rollDice(); return; }
    if (pointOrAction === 'undo') { undoMove(); return; }

    if (state.phase !== 'moving') return;
    if (state.players[state.currentTurn].type !== 'human') return;

    var selected = UI.getSelected();

    // Nothing selected — try to select source
    if (selected === null) {
      selectSource(pointOrAction);
      return;
    }

    // Same point clicked — deselect
    if (isSamePoint(selected, pointOrAction)) {
      deselect();
      return;
    }

    // Try as destination
    var to = parseTarget(pointOrAction);
    var validMoves = getValidMovesForFrom(selected);
    var validMove = null;
    for (var i = 0; i < validMoves.length; i++) {
      if (validMoves[i].to === to) { validMove = validMoves[i]; break; }
    }

    if (validMove) {
      executeMove(validMove);
    } else if (isOwnPiece(pointOrAction)) {
      // Clicked another own piece — swap selection
      deselect();
      selectSource(pointOrAction);
    }
  }

  // ─── Source selection ──────────────────────────────────────────────────────

  function selectSource(pointOrAction) {
    var player = state.currentTurn;

    // Must enter from bar first
    if (state.bar[player] > 0) {
      if (pointOrAction !== 'bar') {
        UI.setStatus('أدخل قطعتك من البار أولاً');
        return;
      }
      var moves = getValidMovesForFrom('bar');
      if (moves.length === 0) return;

      // Auto-move if only one destination
      if (moves.length === 1) {
        UI.setSelected('bar');
        setTimeout(function() { executeMove(moves[0]); }, 150);
        return;
      }

      UI.setSelected('bar');
      UI.highlightTargets(moves.map(function(m) { return m.to; }));
      UI.setStatus('اختر وجهة');
      return;
    }

    var point = parseInt(pointOrAction);
    if (isNaN(point)) return;

    var count = state.board[point];
    var isOwn = (player === 0) ? count > 0 : count < 0;
    if (!isOwn) return;

    var moves = getValidMovesForFrom(point);
    if (moves.length === 0) return;

    // Auto-move if only one destination
    if (moves.length === 1) {
      UI.setSelected(point);
      UI.render(state);
      setTimeout(function() { executeMove(moves[0]); }, 150);
      return;
    }

    UI.setSelected(point);
    UI.highlightTargets(moves.map(function(m) { return m.to; }));
    UI.setStatus('اختر وجهة');
  }

  // ─── Execute move ──────────────────────────────────────────────────────────

  function executeMove(move) {
    // Save undo state
    undoStack.push({
      board: state.board.slice(),
      bar: state.bar.slice(),
      borneOff: state.borneOff.slice(),
      diceRemaining: state.diceRemaining.slice()
    });

    var result = C.applyMove(state.board, state.bar, state.borneOff, state.currentTurn, move);
    state.board = result.board;
    state.bar = result.bar;
    state.borneOff = result.borneOff;

    // Remove used die
    var idx = state.diceRemaining.indexOf(move.dieUsed);
    if (idx !== -1) state.diceRemaining.splice(idx, 1);

    state.moves.push({ player: state.currentTurn, from: move.from, to: move.to, die: move.dieUsed, hit: move.hit });

    if (move.hit) UI.showLog('ضرب!');

    UI.clearSelected();
    UI.clearHighlights();
    UI.render(state);

    // Check win
    if (C.checkWin(state.borneOff, state.currentTurn)) {
      handleWin();
      return;
    }

    // Check if more moves available
    if (state.diceRemaining.length === 0) {
      setTimeout(function() { endTurn(); }, 400);
      return;
    }

    if (!C.canMove(state.board, state.bar, state.borneOff, state.currentTurn, state.diceRemaining)) {
      UI.setStatus('لا توجد حركة أخرى');
      setTimeout(function() { endTurn(); }, 800);
      return;
    }

    // Continue — show next movable sources
    beginHumanTurn();
  }

  // ─── Auto-execute single sequence ─────────────────────────────────────────

  function autoExecuteSequence(moves) {
    var i = 0;
    function next() {
      if (i >= moves.length) {
        setTimeout(function() { endTurn(); }, 300);
        return;
      }
      var move = moves[i];
      var result = C.applyMove(state.board, state.bar, state.borneOff, state.currentTurn, move);
      state.board = result.board;
      state.bar = result.bar;
      state.borneOff = result.borneOff;
      var dIdx = state.diceRemaining.indexOf(move.dieUsed);
      if (dIdx !== -1) state.diceRemaining.splice(dIdx, 1);
      state.moves.push({ player: state.currentTurn, from: move.from, to: move.to, die: move.dieUsed, hit: move.hit });
      UI.render(state);
      i++;
      if (C.checkWin(state.borneOff, state.currentTurn)) { handleWin(); return; }
      setTimeout(next, 200);
    }
    next();
  }

  // ─── Undo ──────────────────────────────────────────────────────────────────

  function undoMove() {
    if (undoStack.length === 0) return;
    var prev = undoStack.pop();
    state.board = prev.board;
    state.bar = prev.bar;
    state.borneOff = prev.borneOff;
    state.diceRemaining = prev.diceRemaining;
    state.moves.pop();
    UI.clearSelected();
    UI.clearHighlights();
    UI.render(state);
    beginHumanTurn();
  }

  // ─── Helpers ───────────────────────────────────────────────────────────────

  function deselect() {
    UI.clearSelected();
    UI.clearHighlights();
    UI.setStatus('اختر قطعة');
    showMovableSources();
  }

  function isSamePoint(a, b) {
    if (a === 'bar' && b === 'bar') return true;
    return parseInt(a) === parseInt(b);
  }

  function parseTarget(val) {
    if (val === 'off') return 'off';
    if (val === 'bar') return 'bar';
    var n = parseInt(val);
    return isNaN(n) ? val : n;
  }

  function isOwnPiece(val) {
    if (val === 'bar') return state.bar[state.currentTurn] > 0;
    if (val === 'off') return false;
    var p = parseInt(val);
    if (isNaN(p)) return false;
    var count = state.board[p];
    return (state.currentTurn === 0) ? count > 0 : count < 0;
  }

  function getValidMovesForFrom(from) {
    var allMoves = [];
    for (var i = 0; i < state.diceRemaining.length; i++) {
      var die = state.diceRemaining[i];
      var moves = C.getValidMoves(state.board, state.bar, state.borneOff, state.currentTurn, die);
      for (var j = 0; j < moves.length; j++) {
        if (moves[j].from === from) {
          var move = { from: moves[j].from, to: moves[j].to, hit: moves[j].hit, dieUsed: die };
          var isDup = false;
          for (var k = 0; k < allMoves.length; k++) {
            if (allMoves[k].to === move.to && allMoves[k].dieUsed === move.dieUsed) { isDup = true; break; }
          }
          if (!isDup) allMoves.push(move);
        }
      }
    }
    return allMoves;
  }

  // ─── End turn ──────────────────────────────────────────────────────────────

  function endTurn() {
    undoStack = [];
    state.currentTurn = 1 - state.currentTurn;
    state.dice = null;
    state.diceRemaining = [];
    state.phase = 'awaiting_roll';

    UI.clearSelected();
    UI.clearHighlights();
    UI.render(state);

    if (state.players[state.currentTurn].type === 'bot') {
      UI.setStatus('انتظر...');
      setTimeout(function() { executeBotTurn(); }, 600);
    } else {
      // Auto-roll for human
      UI.setStatus('');
      setTimeout(function() { rollDice(); }, 400);
    }
  }

  // ─── Bot turn ──────────────────────────────────────────────────────────────

  function executeBotTurn() {
    // Roll for bot
    var d1 = Math.ceil(Math.random() * 6);
    var d2 = Math.ceil(Math.random() * 6);
    state.dice = [d1, d2];
    state.diceRemaining = C.getDiceRemaining(d1, d2);
    state.phase = 'moving';

    UI.showLog(state.players[state.currentTurn].name + ': ' + d1 + '، ' + d2);
    UI.render(state);

    if (!C.canMove(state.board, state.bar, state.borneOff, state.currentTurn, state.diceRemaining)) {
      UI.showLog(state.players[state.currentTurn].name + ' — لا حركة');
      setTimeout(function() { endTurn(); }, 800);
      return;
    }

    var difficulty = state.players[state.currentTurn].difficulty || 'medium';
    var moves = Bot.chooseMove(state.board, state.bar, state.borneOff, state.currentTurn, state.diceRemaining, difficulty);

    if (!moves || moves.length === 0) {
      setTimeout(function() { endTurn(); }, 600);
      return;
    }

    executeBotMoves(moves, 0);
  }

  function executeBotMoves(moves, idx) {
    if (idx >= moves.length) {
      setTimeout(function() { endTurn(); }, 400);
      return;
    }

    var move = moves[idx];
    var result = C.applyMove(state.board, state.bar, state.borneOff, state.currentTurn, move);
    state.board = result.board;
    state.bar = result.bar;
    state.borneOff = result.borneOff;

    var dieIdx = state.diceRemaining.indexOf(move.dieUsed);
    if (dieIdx !== -1) state.diceRemaining.splice(dieIdx, 1);

    state.moves.push({ player: state.currentTurn, from: move.from, to: move.to, die: move.dieUsed, hit: move.hit });

    UI.render(state);

    if (C.checkWin(state.borneOff, state.currentTurn)) {
      handleWin();
      return;
    }

    setTimeout(function() { executeBotMoves(moves, idx + 1); }, 300);
  }

  // ─── Win ───────────────────────────────────────────────────────────────────

  function handleWin() {
    var winner = state.currentTurn;
    var winType = C.getWinType(state.board, state.bar, state.borneOff, winner);
    var points = (winType === 'backgammon') ? 3 : (winType === 'gammon') ? 2 : 1;
    points *= state.doublingCube.value;

    state.scores[winner] += points;
    state.phase = 'game_over';

    var winLabel = (winType === 'backgammon') ? 'باكغمّون!' : (winType === 'gammon') ? 'غمّون!' : 'فوز!';
    UI.showLog(state.players[winner].name + ' — ' + winLabel);
    UI.showResult(state.players[winner].name, winType, points);
    UI.render(state);

    if (state.onGameEnd) {
      state.onGameEnd({ winner: winner, winType: winType, points: points, scores: state.scores });
    }
  }

  function getState() { return state; }

  return {
    init: init,
    rollDice: rollDice,
    handlePointClick: handlePointClick,
    getState: getState
  };
})();
