package de.nowchess.bot

import de.nowchess.api.board.PieceType
import de.nowchess.api.game.GameContext
import de.nowchess.api.move.{Move, MoveType, PromotionPiece}

object MoveOrdering:

  /** Score a single move for ordering (higher = search first). */
  def score(context: GameContext, move: Move, ttBestMove: Option[Move]): Int =
    if ttBestMove.exists(m => m.from == move.from && m.to == move.to) then
      Int.MaxValue  // TT best move always first
    else
      move.moveType match
        case MoveType.Promotion(PromotionPiece.Queen) =>
          1_000_000  // Queen promotion is always good
        case MoveType.Normal(true) =>
          100_000 + mvvLva(context, move)  // Capture
        case MoveType.EnPassant =>
          100_000 + mvvLva(context, move)  // En passant is a pawn capture
        case MoveType.Promotion(_) =>
          50_000 + mvvLva(context, move)  // Minor/rook/bishop promotion
        case _ =>
          0  // Quiet move

  /** Sort moves: TT best move first, then by score descending. */
  def sort(context: GameContext, moves: List[Move], ttBestMove: Option[Move]): List[Move] =
    moves.sortBy(m => -score(context, m, ttBestMove))

  /** MVV-LVA score: (victim value * 10) - attacker value.
   *  Higher score = better trade (most valuable victim captured by least valuable attacker). */
  private def mvvLva(context: GameContext, move: Move): Int =
    val victim = victimValue(context, move)
    val attacker = attackerValue(context, move)
    (victim * 10) - attacker

  /** Material value of the attacking piece. */
  private def attackerValue(context: GameContext, move: Move): Int =
    context.board.pieceAt(move.from) match
      case Some(piece) =>
        piece.pieceType match
          case PieceType.Pawn => 1
          case PieceType.Knight => 3
          case PieceType.Bishop => 3
          case PieceType.Rook => 5
          case PieceType.Queen => 9
          case PieceType.King => 200  // King never captures, but include for completeness
      case None => 0

  /** Material value of the captured piece. */
  private def victimValue(context: GameContext, move: Move): Int =
    move.moveType match
      case MoveType.Normal(true) =>
        context.board.pieceAt(move.to) match
          case Some(piece) =>
            piece.pieceType match
              case PieceType.Pawn => 1
              case PieceType.Knight => 3
              case PieceType.Bishop => 3
              case PieceType.Rook => 5
              case PieceType.Queen => 9
              case PieceType.King => 200
          case None => 0
      case MoveType.EnPassant => 1  // En passant captures a pawn
      case MoveType.Promotion(_) => 0  // Promotion is not a capture (destination is empty)
      case _ => 0
