// Bot AI for Backgammon — 3 difficulty levels
import { getValidMoves, applyMove, cloneState, getPipCount, WHITE, BLACK } from './rules.js';

export function getBotMove(game, difficulty = 'medium') {
  const moves = getValidMoves(game);
  if (moves.length === 0) return null;

  if (difficulty === 'easy') return getEasyMove(moves);
  if (difficulty === 'hard') return getHardMove(game, moves);
  return getMediumMove(game, moves);
}

function getEasyMove(moves) {
  return moves[Math.floor(Math.random() * moves.length)];
}

function getMediumMove(game, moves) {
  let best = moves[0];
  let bestScore = -Infinity;

  for (const move of moves) {
    const score = scoreMoveSimple(game, move);
    if (score > bestScore) {
      bestScore = score;
      best = move;
    }
  }
  return best;
}

function getHardMove(game, moves) {
  let best = moves[0];
  let bestScore = -Infinity;

  for (const move of moves) {
    const score = scoreMoveAdvanced(game, move);
    if (score > bestScore) {
      bestScore = score;
      best = move;
    }
  }
  return best;
}

function scoreMoveSimple(game, move) {
  let score = 0;
  for (const action of move.actions) {
    if (action.type === 'hit') score += 30;
    if (action.type === 'bear') score += 50;
  }
  // Prefer moving from bar
  if (move.from === 'bar') score += 20;
  // Prefer making points (landing where we already have pieces)
  if (move.to !== 'off' && move.to >= 0 && move.to <= 23) {
    const destCount = game.state.points[move.to].filter(p => p.type === game.turn).length;
    if (destCount === 1) score += 15; // making a point
  }
  // Avoid leaving blots
  if (move.from >= 0 && move.from <= 23) {
    const remaining = game.state.points[move.from].filter(p => p.type === game.turn).length - 1;
    if (remaining === 1) score -= 10;
  }
  return score;
}

function scoreMoveAdvanced(game, move) {
  let score = 0;
  const type = game.turn;
  const opp = type === WHITE ? BLACK : WHITE;

  // Hit value — sending opponent back is huge
  for (const action of move.actions) {
    if (action.type === 'hit') score += 40;
    if (action.type === 'bear') score += 60;
  }

  // Blot safety — penalize leaving blots
  if (move.from >= 0 && move.from <= 23) {
    const remaining = game.state.points[move.from].filter(p => p.type === type).length - 1;
    if (remaining === 1) {
      // How exposed is this blot?
      const exposure = calculateBlotExposure(game.state, move.from, opp);
      score -= exposure * 8;
    }
  }

  // Point-making — landing to create a 2+ stack
  if (move.to !== 'off' && move.to >= 0 && move.to <= 23) {
    const friendsAtDest = game.state.points[move.to].filter(p => p.type === type).length;
    if (friendsAtDest === 1) score += 20; // making a new point
    if (friendsAtDest >= 2) score += 5; // adding to existing point
  }

  // Prime building — consecutive blocked points
  if (move.to !== 'off' && move.to >= 0 && move.to <= 23) {
    score += primeBonus(game.state, move.to, type) * 8;
  }

  // Anchor value — holding points deep in opponent's board
  if (move.to !== 'off' && move.to >= 0 && move.to <= 23) {
    const norm = type === WHITE ? move.to : 23 - move.to;
    if (norm >= 18) score += 12; // anchor in opponent's home
  }

  // Race — prefer bearing off and advancing when ahead
  const myPips = getPipCount(game.state, type);
  const oppPips = getPipCount(game.state, opp);
  if (myPips < oppPips) {
    score += move.steps * 2; // racing advantage, advance further
  }

  // Advancing runners from deep position
  if (move.from >= 0 && move.from <= 23) {
    const normFrom = type === WHITE ? move.from : 23 - move.from;
    if (normFrom >= 20) score += 8; // escape back runners
  }

  return score;
}

function calculateBlotExposure(state, pos, opponentType) {
  let threats = 0;
  for (let dist = 1; dist <= 6; dist++) {
    const fromPos = opponentType === WHITE ? pos + dist : pos - dist;
    if (fromPos < 0 || fromPos > 23) continue;
    if (state.points[fromPos].some(p => p.type === opponentType)) {
      threats++;
    }
  }
  // Also count bar pieces as threats
  if (state.bar[opponentType].length > 0) {
    const barEntry = opponentType === WHITE ? (23 - pos) : pos;
    if (barEntry >= 1 && barEntry <= 6) threats += state.bar[opponentType].length;
  }
  return threats;
}

function primeBonus(state, point, type) {
  let consecutive = 0;
  for (let i = point - 3; i <= point + 3; i++) {
    if (i < 0 || i > 23) continue;
    if (state.points[i].filter(p => p.type === type).length >= 2) {
      consecutive++;
    } else {
      if (i > point) break;
      consecutive = 0;
    }
  }
  return Math.max(0, consecutive - 1);
}
