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

    var state = null;
    var config = {};
    var botDelay = 800;

    function init(opts) {
        config = {
            mode: opts.mode || '2p',
            playerCount: parseInt(opts.playerCount) || 2,
            difficulty: opts.difficulty || 'easy',
            players: opts.players || [],
            isLocal: opts.isLocal || false
        };

        if (config.isLocal) {
            config.players = [];
            for (var i = 0; i < config.playerCount; i++) {
                config.players.push({ id: 'local_' + i, name: 'لاعب ' + (i + 1), type: 'human', color: 'P' + (i + 1) });
            }
        } else {
            // Bot mode: player 0 is human, rest are bots
            config.players = [{ id: 'human', name: 'أنت', type: 'human', color: 'P1' }];
            for (var b = 1; b < config.playerCount; b++) {
                config.players.push({ id: 'bot_' + b, name: 'بوت ' + b, type: 'bot', color: 'P' + (b + 1), difficulty: config.difficulty });
            }
        }

        DominoUI.init({
            onTilePlay: handleTilePlay,
            onDraw: handleDraw,
            onPass: handlePass
        });

        startNewRound(1, null);
    }

    function startNewRound(roundNumber, previousWinner) {
        var deal = DominoConstants.dealTiles(config.mode, config.playerCount);
        var firstPlayer = DominoConstants.findFirstPlayer(deal.hands, roundNumber, previousWinner);

        state = {
            board: [],
            hands: deal.hands,
            boneyard: deal.boneyard,
            spinner: null,
            currentTurn: firstPlayer,
            scores: state ? state.scores : new Array(config.playerCount).fill(0),
            roundNumber: roundNumber,
            roundHistory: state ? state.roundHistory : [],
            targetScore: (config.mode === '4p_teams') ? 150 : 100,
            moves: [],
            consecutivePasses: 0,
            phase: 'play'
        };

        renderFullState();

        if (config.players[firstPlayer].type === 'bot') {
            setTimeout(executeBotTurn, botDelay);
        }
    }

    function renderFullState() {
        var myIdx = getHumanPlayerIdx();

        DominoUI.renderBoard(state.board, state.spinner);
        DominoUI.renderScores(state.scores, config.players, config.mode, state.targetScore);

        // Render hand
        var ends = DominoConstants.getPlayableEnds(state.board, state.spinner);
        var isMyTurn = (state.currentTurn === myIdx);
        DominoUI.renderHand(state.hands[myIdx], {
            isCurrentPlayer: isMyTurn,
            playableEnds: ends,
            boardEmpty: state.board.length === 0
        });

        // Render end buttons
        DominoUI.renderEndButtons(ends, state.board.length === 0);

        // Render opponents
        var sanitizedHands = {};
        for (var i = 0; i < config.playerCount; i++) {
            if (i === myIdx) sanitizedHands[i] = state.hands[i];
            else sanitizedHands[i] = state.hands[i].length;
        }
        DominoUI.renderOpponentHands(sanitizedHands, config.players, myIdx, config.playerCount);

        // Boneyard
        var canDraw = isMyTurn && config.mode === '2p' && state.boneyard.length > 0 && !DominoConstants.canPlayerPlay(state.hands[myIdx], ends);
        DominoUI.renderBoneyard(state.boneyard.length, canDraw);

        // Actions
        var canPass = isMyTurn && config.mode === '4p_teams' && !DominoConstants.canPlayerPlay(state.hands[myIdx], ends);
        DominoUI.renderActions({ canPass: canPass });

        // Status
        if (isMyTurn) {
            DominoUI.renderStatus('دورك — اختر قطعة', 'success');
        } else {
            DominoUI.renderStatus('دور ' + config.players[state.currentTurn].name, 'info');
        }
    }

    function getHumanPlayerIdx() {
        if (config.isLocal) return state.currentTurn;
        return 0;
    }

    // ─── Player Actions ─────────────────────────────────────────────────────

    function handleTilePlay(tileId, side) {
        var myIdx = getHumanPlayerIdx();
        if (state.currentTurn !== myIdx) return;

        var hand = state.hands[myIdx];
        var tileIdx = -1, tile = null;
        for (var i = 0; i < hand.length; i++) {
            if (hand[i].id === tileId) { tileIdx = i; tile = hand[i]; break; }
        }
        if (!tile) return;

        // First tile on empty board
        if (state.board.length === 0) {
            var isDouble = DominoConstants.isDouble(tile);
            state.board.push({ tile: tile, side: null, isSpinner: isDouble, exposed_end: null });
            if (isDouble) state.spinner = tile;
            state.hands[myIdx].splice(tileIdx, 1);
            state.moves.push({ player: myIdx, action: 'play', tile: tile, side: null });
            state.consecutivePasses = 0;
            afterPlay(myIdx);
            return;
        }

        // Validate
        var ends = DominoConstants.getPlayableEnds(state.board, state.spinner);
        if (side === 'any') {
            // Pick first available end
            for (var s in ends) { side = s; break; }
        }
        if (!ends[side]) return;

        var endValue = ends[side];
        if (!DominoConstants.tileMatchesEnd(tile, endValue)) {
            App.toast('هذه القطعة لا تتطابق', 'error');
            return;
        }

        var exposedEnd = DominoConstants.getExposedEnd(tile, endValue);
        var isDouble2 = DominoConstants.isDouble(tile);
        if (isDouble2) exposedEnd = tile.left;
        if (isDouble2 && !state.spinner) state.spinner = tile;

        state.board.push({ tile: tile, side: side, isSpinner: false, exposed_end: exposedEnd });
        state.hands[myIdx].splice(tileIdx, 1);
        state.moves.push({ player: myIdx, action: 'play', tile: tile, side: side });
        state.consecutivePasses = 0;

        afterPlay(myIdx);
    }

    function handleDraw() {
        var myIdx = getHumanPlayerIdx();
        if (state.currentTurn !== myIdx) return;
        if (config.mode !== '2p') return;
        if (state.boneyard.length === 0) return;

        var ends = DominoConstants.getPlayableEnds(state.board, state.spinner);
        if (DominoConstants.canPlayerPlay(state.hands[myIdx], ends)) {
            App.toast('يمكنك اللعب — اختر قطعة', 'warning');
            return;
        }

        var drawnTile = state.boneyard.pop();
        state.hands[myIdx].push(drawnTile);
        state.moves.push({ player: myIdx, action: 'draw' });

        // Check if can now play
        if (!DominoConstants.canPlayerPlay(state.hands[myIdx], ends)) {
            // Still can't play — check if boneyard still has tiles
            if (state.boneyard.length > 0) {
                renderFullState();
                return; // Let player draw again
            }
            // Boneyard empty, pass
            state.consecutivePasses++;
            state.moves.push({ player: myIdx, action: 'pass' });
            advanceTurn();
        } else {
            renderFullState();
        }
    }

    function handlePass() {
        var myIdx = getHumanPlayerIdx();
        if (state.currentTurn !== myIdx) return;

        var ends = DominoConstants.getPlayableEnds(state.board, state.spinner);
        if (DominoConstants.canPlayerPlay(state.hands[myIdx], ends)) {
            App.toast('يمكنك اللعب!', 'error');
            return;
        }

        state.consecutivePasses++;
        state.moves.push({ player: myIdx, action: 'pass' });
        advanceTurn();
    }

    // ─── After Play ─────────────────────────────────────────────────────────

    function afterPlay(playerIdx) {
        DominoUI.clearSelection();

        // Check round end: player emptied hand
        if (state.hands[playerIdx].length === 0) {
            endRound('domino', playerIdx);
            return;
        }

        // Check if blocked
        if (isGameBlocked()) {
            endRound('blocked', null);
            return;
        }

        advanceTurn();
    }

    function advanceTurn() {
        state.currentTurn = (state.currentTurn + 1) % config.playerCount;

        // Check if blocked
        if (state.consecutivePasses >= config.playerCount) {
            endRound('blocked', null);
            return;
        }

        renderFullState();

        if (config.players[state.currentTurn].type === 'bot') {
            setTimeout(executeBotTurn, botDelay);
        }
    }

    function isGameBlocked() {
        if (config.mode === '2p' && state.boneyard.length > 0) return false;
        var ends = DominoConstants.getPlayableEnds(state.board, state.spinner);
        for (var i = 0; i < config.playerCount; i++) {
            if (DominoConstants.canPlayerPlay(state.hands[i], ends)) return false;
        }
        return true;
    }

    // ─── Bot Turn ───────────────────────────────────────────────────────────

    function executeBotTurn() {
        if (state.phase !== 'play') return;
        var player = config.players[state.currentTurn];
        if (player.type !== 'bot') return;

        var hand = state.hands[state.currentTurn];
        var ends = DominoConstants.getPlayableEnds(state.board, state.spinner);
        var difficulty = player.difficulty || config.difficulty;

        // First tile on empty board
        if (state.board.length === 0) {
            var tile = DominoBot.chooseFirstTile(hand, difficulty);
            var isDouble = DominoConstants.isDouble(tile);
            state.board.push({ tile: tile, side: null, isSpinner: isDouble, exposed_end: null });
            if (isDouble) state.spinner = tile;
            state.hands[state.currentTurn] = hand.filter(function(t) { return t.id !== tile.id; });
            state.moves.push({ player: state.currentTurn, action: 'play', tile: tile, side: null, bot: true });
            state.consecutivePasses = 0;
            afterPlay(state.currentTurn);
            return;
        }

        if (DominoConstants.canPlayerPlay(hand, ends)) {
            var play = DominoBot.choosePlay(hand, ends, state.board, difficulty, state.moves);
            if (!play) { botPass(); return; }

            var tile2 = play.tile;
            var side = play.side;
            var endValue = ends[side];
            var exposedEnd = DominoConstants.getExposedEnd(tile2, endValue);
            var isDouble2 = DominoConstants.isDouble(tile2);
            if (isDouble2) exposedEnd = tile2.left;
            if (isDouble2 && !state.spinner) state.spinner = tile2;

            state.board.push({ tile: tile2, side: side, isSpinner: false, exposed_end: exposedEnd });
            state.hands[state.currentTurn] = hand.filter(function(t) { return t.id !== tile2.id; });
            state.moves.push({ player: state.currentTurn, action: 'play', tile: tile2, side: side, bot: true });
            state.consecutivePasses = 0;
            afterPlay(state.currentTurn);
        } else if (config.mode === '2p' && state.boneyard.length > 0) {
            // Draw until can play or boneyard empty
            botDraw();
        } else {
            botPass();
        }
    }

    function botDraw() {
        var ends = DominoConstants.getPlayableEnds(state.board, state.spinner);

        while (state.boneyard.length > 0 && !DominoConstants.canPlayerPlay(state.hands[state.currentTurn], ends)) {
            var drawnTile = state.boneyard.pop();
            state.hands[state.currentTurn].push(drawnTile);
            state.moves.push({ player: state.currentTurn, action: 'draw', bot: true });
        }

        // Now try to play
        if (DominoConstants.canPlayerPlay(state.hands[state.currentTurn], ends)) {
            var hand = state.hands[state.currentTurn];
            var difficulty = config.players[state.currentTurn].difficulty || config.difficulty;
            var play = DominoBot.choosePlay(hand, ends, state.board, difficulty, state.moves);
            if (play) {
                var tile = play.tile;
                var endValue = ends[play.side];
                var exposedEnd = DominoConstants.getExposedEnd(tile, endValue);
                var isDouble = DominoConstants.isDouble(tile);
                if (isDouble) exposedEnd = tile.left;
                if (isDouble && !state.spinner) state.spinner = tile;

                state.board.push({ tile: tile, side: play.side, isSpinner: false, exposed_end: exposedEnd });
                state.hands[state.currentTurn] = hand.filter(function(t) { return t.id !== tile.id; });
                state.moves.push({ player: state.currentTurn, action: 'play', tile: tile, side: play.side, bot: true });
                state.consecutivePasses = 0;
                afterPlay(state.currentTurn);
                return;
            }
        }

        botPass();
    }

    function botPass() {
        state.consecutivePasses++;
        state.moves.push({ player: state.currentTurn, action: 'pass', bot: true });
        advanceTurn();
    }

    // ─── Round End ──────────────────────────────────────────────────────────

    function endRound(type, winnerIdx) {
        state.phase = 'round_over';
        var roundScore = 0;

        if (type === 'domino') {
            roundScore = calcRoundScore(winnerIdx);
        } else {
            var blocked = calcBlockedScore();
            winnerIdx = blocked.winnerIdx;
            roundScore = blocked.score;
        }

        // Award score
        if (winnerIdx !== null) {
            if (config.mode === '4p_teams') {
                var team = winnerIdx % 2;
                state.scores[team] = (state.scores[team] || 0) + roundScore;
            } else {
                state.scores[winnerIdx] = (state.scores[winnerIdx] || 0) + roundScore;
            }
        }

        state.roundHistory.push({
            round: state.roundNumber,
            winner_idx: winnerIdx,
            score: roundScore,
            type: type
        });

        renderFullState();

        // Check match over
        var matchWinner = null;
        for (var i = 0; i < state.scores.length; i++) {
            if (state.scores[i] >= state.targetScore) { matchWinner = i; break; }
        }

        var winnerName = winnerIdx !== null ? config.players[winnerIdx].name : null;
        if (config.mode === '4p_teams' && winnerIdx !== null) {
            winnerName = 'فريق ' + ((winnerIdx % 2) + 1);
        }

        DominoUI.showRoundOverlay({
            round: state.roundNumber,
            type: type,
            winnerName: winnerName,
            score: roundScore,
            matchOver: matchWinner !== null
        });

        if (matchWinner === null) {
            // Set up next round after user dismisses overlay
            setTimeout(function() {
                state.phase = 'play';
                startNewRound(state.roundNumber + 1, winnerIdx);
            }, 3000);
        }
    }

    function calcRoundScore(winnerIdx) {
        var total = 0;
        if (config.mode === '4p_teams') {
            var winnerTeam = winnerIdx % 2;
            for (var i = 0; i < config.playerCount; i++) {
                if (i % 2 !== winnerTeam) total += DominoConstants.pipCount(state.hands[i]);
            }
        } else {
            for (var j = 0; j < config.playerCount; j++) {
                if (j !== winnerIdx) total += DominoConstants.pipCount(state.hands[j]);
            }
        }
        return total;
    }

    function calcBlockedScore() {
        if (config.mode === '4p_teams') {
            var team0 = DominoConstants.pipCount(state.hands[0]) + DominoConstants.pipCount(state.hands[2]);
            var team1 = DominoConstants.pipCount(state.hands[1]) + DominoConstants.pipCount(state.hands[3]);
            if (team0 < team1) return { winnerIdx: 0, score: team1 - team0 };
            if (team1 < team0) return { winnerIdx: 1, score: team0 - team1 };
            return { winnerIdx: null, score: 0 };
        }

        var minPips = Infinity, winnerIdx = 0;
        for (var i = 0; i < config.playerCount; i++) {
            var pips = DominoConstants.pipCount(state.hands[i]);
            if (pips < minPips) { minPips = pips; winnerIdx = i; }
        }
        var total = 0;
        for (var j = 0; j < config.playerCount; j++) {
            if (j !== winnerIdx) total += DominoConstants.pipCount(state.hands[j]);
        }
        return { winnerIdx: winnerIdx, score: total - minPips };
    }

    return {
        init: init
    };
})();
