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

  var C = LudoConstants;
  var UI = LudoUI;
  var Bot = LudoBot;

  var state = {
    activePlayers: [],
    positions: {},
    currentPlayerIdx: 0,
    diceValue: 0,
    phase: C.STATE.DICE_NOT_ROLLED,
    winners: [],
    consecutiveSixes: 0,
    isGameOver: false,
    mode: 'local',
    bots: {},
    botDifficulty: 'easy',
    playerNames: {},
    onGameEnd: null
  };

  function init(options) {
    state.activePlayers = options.players || ['P1', 'P2', 'P3', 'P4'];
    state.mode = options.mode || 'local';
    state.bots = options.bots || {};
    state.botDifficulty = options.difficulty || 'easy';
    state.playerNames = options.playerNames || {};
    state.onGameEnd = options.onGameEnd || null;
    state.currentPlayerIdx = 0;
    state.diceValue = 0;
    state.phase = C.STATE.DICE_NOT_ROLLED;
    state.winners = [];
    state.consecutiveSixes = 0;
    state.isGameOver = false;

    state.positions = {};
    state.activePlayers.forEach(function(p) {
      state.positions[p] = C.BASE_POSITIONS[p].slice();
    });

    UI.renderPieces(state.activePlayers);
    state.activePlayers.forEach(function(p) {
      for (var i = 0; i < 4; i++) {
        UI.setPiecePosition(p, i, state.positions[p][i]);
      }
    });

    UI.setTurn(currentPlayer(), state.playerNames[currentPlayer()]);
    UI.enableDice();
    UI.clearLog();
    UI.hideResult();
    UI.addLogEntry('بدأت اللعبة!');

    UI.listenDiceClick(onDiceClick);
    UI.listenPieceClick(onPieceClick);

    if (isCurrentPlayerBot()) {
      scheduleBotRoll();
    }
  }

  function currentPlayer() {
    return state.activePlayers[state.currentPlayerIdx];
  }

  function isCurrentPlayerBot() {
    return !!state.bots[currentPlayer()];
  }

  function onDiceClick() {
    if (state.isGameOver) return;
    if (state.phase !== C.STATE.DICE_NOT_ROLLED) return;
    if (isCurrentPlayerBot()) return;

    rollDice();
  }

  function rollDice() {
    state.phase = C.STATE.DICE_ROLLED;
    UI.disableDice();

    var value = 1 + Math.floor(Math.random() * 6);
    state.diceValue = value;
    if (typeof App !== 'undefined') {
      App.playSound('dice');
      App.vibrate(15);
    }

    UI.animateDiceRoll(value, function() {
      afterRoll();
    });
  }

  function afterRoll() {
    var player = currentPlayer();
    var eligible = Bot.getEligiblePieces(player, state.diceValue, state.positions, state.activePlayers);

    if (state.diceValue === 6 && typeof App !== 'undefined' && App.playSound) App.playSound('six');
    UI.addLogEntry(getPlayerLabel(player) + ' رمى ' + state.diceValue);

    if (eligible.length === 0) {
      UI.addLogEntry(getPlayerLabel(player) + ' لا يوجد حركة متاحة');
      state.consecutiveSixes = 0;
      setTimeout(function() { nextTurn(); }, 600);
      return;
    }

    if (eligible.length === 1 && isCurrentPlayerBot()) {
      setTimeout(function() { movePiece(player, eligible[0]); }, 500);
      return;
    }

    if (isCurrentPlayerBot()) {
      var chosen = Bot.takeTurn(player, state.diceValue, state.positions, state.activePlayers,
        state.bots[player] || state.botDifficulty);
      setTimeout(function() { movePiece(player, chosen); }, 500);
      return;
    }

    UI.highlightPieces(player, eligible);
    state.phase = C.STATE.DICE_ROLLED;
  }

  function onPieceClick(e) {
    if (state.isGameOver) return;
    if (state.phase !== C.STATE.DICE_ROLLED) return;
    if (isCurrentPlayerBot()) return;

    var target = e.target.closest('.ludo-piece--highlight');
    if (!target) return;

    var player = target.dataset.player;
    var pieceIdx = parseInt(target.dataset.piece, 10);

    if (player !== currentPlayer()) return;

    UI.unhighlightPieces();
    movePiece(player, pieceIdx);
  }

  function movePiece(player, pieceIdx) {
    state.phase = C.STATE.PIECE_MOVING;
    UI.unhighlightPieces();

    var currentPos = state.positions[player][pieceIdx];
    var isInBase = C.BASE_POSITIONS[player].indexOf(currentPos) !== -1;
    var newPos;

    if (isInBase && state.diceValue === 6) {
      newPos = C.START_POSITIONS[player];
    } else {
      newPos = Bot.calculateNewPosition(player, currentPos, state.diceValue);
    }

    if (newPos === null) {
      nextTurn();
      return;
    }

    state.positions[player][pieceIdx] = newPos;
    UI.setPiecePosition(player, pieceIdx, newPos);
    UI.updateStacking(state.positions, state.activePlayers);
    if (typeof App !== 'undefined' && App.playSound) App.playSound('move');

    var killed = checkKill(player, pieceIdx, newPos);
    var reachedHome = newPos === C.HOME_POSITIONS[player];
    var rolledSix = state.diceValue === 6;
    var extraTurn = false;

    if (killed) {
      UI.captureExplosion(killed.player, newPos);
      if (typeof App !== 'undefined') App.vibrate(30);
      UI.addLogEntry(getPlayerLabel(player) + ' اكل قطعة ' + getPlayerLabel(killed.player));
      extraTurn = true;
    }

    if (reachedHome) {
      if (typeof App !== 'undefined' && App.playSound) App.playSound('win');
      UI.addLogEntry(getPlayerLabel(player) + ' وصّل قطعة للبيت!');
      extraTurn = true;

      if (checkPlayerFinished(player)) {
        state.winners.push(player);
        UI.setPlayerFinished(player);
        UI.addLogEntry(getPlayerLabel(player) + ' خلّص! المركز ' + state.winners.length);

        if (checkGameOver()) {
          endGame();
          return;
        }
      }
    }

    if (rolledSix) {
      state.consecutiveSixes++;
      if (state.consecutiveSixes >= 3) {
        UI.addLogEntry(getPlayerLabel(player) + ' 3 ستات متتالية - ضاع الدور');
        state.consecutiveSixes = 0;
        extraTurn = false;
      } else {
        extraTurn = true;
      }
    }

    if (extraTurn && !checkPlayerFinished(player)) {
      state.phase = C.STATE.DICE_NOT_ROLLED;
      UI.enableDice();
      if (isCurrentPlayerBot()) {
        scheduleBotRoll();
      }
    } else {
      state.consecutiveSixes = 0;
      setTimeout(function() { nextTurn(); }, 300);
    }
  }

  function checkKill(player, pieceIdx, position) {
    if (C.SAFE_POSITIONS.indexOf(position) !== -1) return null;
    if (position === C.START_POSITIONS[player]) {
      // can still kill at start
    }
    if (C.HOME_ENTRANCE[player].indexOf(position) !== -1) return null;
    if (position === C.HOME_POSITIONS[player]) return null;

    for (var i = 0; i < state.activePlayers.length; i++) {
      var opponent = state.activePlayers[i];
      if (opponent === player) continue;

      for (var j = 0; j < 4; j++) {
        if (state.positions[opponent][j] === position) {
          state.positions[opponent][j] = C.BASE_POSITIONS[opponent][j];
          UI.setPiecePosition(opponent, j, C.BASE_POSITIONS[opponent][j]);
          UI.updateStacking(state.positions, state.activePlayers);
          return { player: opponent, piece: j };
        }
      }
    }
    return null;
  }

  function checkPlayerFinished(player) {
    for (var i = 0; i < 4; i++) {
      if (state.positions[player][i] !== C.HOME_POSITIONS[player]) return false;
    }
    return true;
  }

  function checkGameOver() {
    var remaining = state.activePlayers.filter(function(p) {
      return state.winners.indexOf(p) === -1;
    });
    return remaining.length <= 1;
  }

  function endGame() {
    state.isGameOver = true;
    UI.disableDice();

    var remaining = state.activePlayers.filter(function(p) {
      return state.winners.indexOf(p) === -1;
    });
    remaining.forEach(function(p) { state.winners.push(p); });

    var winner = state.winners[0];
    var isHumanWinner = !isCurrentPlayerBot() || winner === state.activePlayers[0];
    var title = getPlayerLabel(winner) + ' فاز!';
    var subtitle = 'ترتيب: ' + state.winners.map(function(p, i) {
      return (i + 1) + '. ' + getPlayerLabel(p);
    }).join(' | ');

    if (typeof App !== 'undefined') {
      if (isHumanWinner) {
        App.playSound('win');
        App.celebrate(title);
      } else {
        App.playSound('lose');
      }
    }
    UI.showResult(title, subtitle);
    UI.addLogEntry('انتهت اللعبة! الفائز: ' + getPlayerLabel(winner));

    if (state.onGameEnd) {
      state.onGameEnd(state.winners);
    }
  }

  function nextTurn() {
    var startIdx = state.currentPlayerIdx;
    do {
      state.currentPlayerIdx = (state.currentPlayerIdx + 1) % state.activePlayers.length;
    } while (
      state.winners.indexOf(state.activePlayers[state.currentPlayerIdx]) !== -1 &&
      state.currentPlayerIdx !== startIdx
    );

    if (state.currentPlayerIdx === startIdx && state.winners.indexOf(currentPlayer()) !== -1) {
      endGame();
      return;
    }

    state.phase = C.STATE.DICE_NOT_ROLLED;
    state.consecutiveSixes = 0;
    UI.setTurn(currentPlayer(), state.playerNames[currentPlayer()]);
    UI.enableDice();

    if (isCurrentPlayerBot()) {
      scheduleBotRoll();
    }
  }

  function scheduleBotRoll() {
    UI.disableDice();
    setTimeout(function() {
      if (state.isGameOver) return;
      rollDice();
    }, 800);
  }

  function getPlayerLabel(player) {
    return state.playerNames[player] || C.PLAYER_LABELS[player];
  }

  function getState() {
    return {
      positions: state.positions,
      currentPlayer: currentPlayer(),
      diceValue: state.diceValue,
      phase: state.phase,
      winners: state.winners,
      isGameOver: state.isGameOver
    };
  }

  function restart(options) {
    init(options);
  }

  return {
    init: init,
    restart: restart,
    getState: getState
  };
})();
