using PkmnLib.Dynamic.Models;
using PkmnLib.Dynamic.Models.Choices;
using PkmnLib.Static.Utils;

namespace PkmnLib.Dynamic.AI;

/// <summary>
/// HighestDamageAI is an AI that selects the move that it expects to deal the highest damage.
/// </summary>
public class HighestDamageAI : PokemonAI
{
    /// <inheritdoc />
    public HighestDamageAI() : base("highest_damage")
    {
    }

    /// <inheritdoc />
    public override ITurnChoice GetChoice(IBattle battle, IPokemon pokemon)
    {
        var opponentSide = pokemon.BattleData!.SideIndex == 0 ? (byte)1 : (byte)0;
        var opponent = battle.Sides[opponentSide].Pokemon.WhereNotNull().FirstOrDefault(x => x.IsUsable);
        var moves = pokemon.Moves.WhereNotNull().Where(x => battle.CanUse(new MoveChoice(pokemon, x, opponentSide, 0)))
            .ToList();
        if (opponent == null)
        {
            var move = moves.FirstOrDefault();
            return move != null
                ? new MoveChoice(pokemon, move, opponentSide, 0)
                : battle.Library.MiscLibrary.ReplacementChoice(pokemon, opponentSide, 0);
        }

        var movesWithDamage = moves.Select(move => new
        {
            Move = move,
            Damage = AIHelpers.CalculateDamageEstimation(move.MoveData, pokemon, opponent, battle.Library),
        }).OrderByDescending(x => x.Damage).FirstOrDefault();
        if (movesWithDamage is null)
        {
            return battle.Library.MiscLibrary.ReplacementChoice(pokemon, opponentSide, 0);
        }
        var bestMove = movesWithDamage.Move;
        return new MoveChoice(pokemon, bestMove, opponentSide, 0);
    }
}