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

    function choosePlay(hand, ends, board, difficulty, moves) {
        var validPlays = DominoConstants.getValidPlays(hand, ends);
        if (validPlays.length === 0) return null;

        if (difficulty === 'easy') {
            return validPlays[Math.floor(Math.random() * validPlays.length)];
        }

        if (difficulty === 'medium') {
            // Prefer highest pip count tiles to get rid of heavy ones
            validPlays.sort(function(a, b) {
                return (b.tile.left + b.tile.right) - (a.tile.left + a.tile.right);
            });
            return validPlays[0];
        }

        // Hard: strategic scoring
        var bestScore = -999;
        var bestPlay = validPlays[0];

        for (var i = 0; i < validPlays.length; i++) {
            var play = validPlays[i];
            var score = scorePlay(play, hand, ends, board, moves);
            if (score > bestScore) {
                bestScore = score;
                bestPlay = play;
            }
        }

        return bestPlay;
    }

    function scorePlay(play, hand, ends, board, moves) {
        var score = 0;
        var tile = play.tile;

        // 1. Prefer high-pip tiles (shed weight early)
        score += (tile.left + tile.right) * 2;

        // 2. Play doubles early (they're harder to place later)
        if (DominoConstants.isDouble(tile)) score += 8;

        // 3. Keep variety — count unique values remaining after this play
        var remaining = hand.filter(function(t) { return t.id !== tile.id; });
        var values = {};
        for (var r = 0; r < remaining.length; r++) {
            values[remaining[r].left] = true;
            values[remaining[r].right] = true;
        }
        score += Object.keys(values).length * 3;

        // 4. Try to play values that opponents might be short on
        var opponentDraws = countOpponentDraws(moves);
        var exposedEnd = DominoConstants.getExposedEnd(tile, ends[play.side]);
        if (DominoConstants.isDouble(tile)) exposedEnd = tile.left;
        // If we expose a value opponents drew on (couldn't match), that's good (blocking)
        if (opponentDraws[exposedEnd]) score += opponentDraws[exposedEnd] * 4;

        // 5. Avoid leaving yourself with a single value type
        var valueCounts = {};
        for (var v = 0; v < remaining.length; v++) {
            valueCounts[remaining[v].left] = (valueCounts[remaining[v].left] || 0) + 1;
            valueCounts[remaining[v].right] = (valueCounts[remaining[v].right] || 0) + 1;
        }
        var maxConcentration = 0;
        for (var k in valueCounts) {
            if (valueCounts[k] > maxConcentration) maxConcentration = valueCounts[k];
        }
        score -= maxConcentration * 2;

        return score;
    }

    function countOpponentDraws(moves) {
        var draws = {};
        if (!moves) return draws;

        for (var i = 0; i < moves.length; i++) {
            var move = moves[i];
            if (move.action === 'draw' || move.action === 'pass') {
                // After a draw/pass, the board ends at that moment tell us what the opponent couldn't match
                // Simplified: track which values forced passes
                if (i > 0 && moves[i-1].action === 'play' && moves[i-1].tile) {
                    var prevTile = moves[i-1].tile;
                    var exposed = prevTile.right;
                    draws[exposed] = (draws[exposed] || 0) + 1;
                }
            }
        }
        return draws;
    }

    function chooseFirstTile(hand, difficulty) {
        // Always prefer [6|6], then highest double, then highest pip
        var doubles = hand.filter(function(t) { return DominoConstants.isDouble(t); });
        if (doubles.length > 0) {
            doubles.sort(function(a, b) { return b.left - a.left; });
            return doubles[0];
        }
        var sorted = hand.slice().sort(function(a, b) {
            return (b.left + b.right) - (a.left + a.right);
        });
        return sorted[0];
    }

    function shouldDraw(hand, ends) {
        return !DominoConstants.canPlayerPlay(hand, ends);
    }

    return {
        choosePlay: choosePlay,
        chooseFirstTile: chooseFirstTile,
        shouldDraw: shouldDraw
    };
})();
