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

namespace PkmnLib.Dynamic.AI.Explicit;

public partial class ExplicitAI
{
    private static readonly StringKey MistyTerrainName = "misty_terrain";
    private static readonly StringKey PoisonName = "poison";
    private static readonly StringKey SteelName = "steel";
    private static readonly StringKey ImmunityName = "immunity";
    private static readonly StringKey PastelVeilName = "pastel_veil";
    private static readonly StringKey FlowerVeilName = "flower_veil";
    private static readonly StringKey LeafGuardName = "leaf_guard";
    private static readonly StringKey ComatoseName = "comatose";
    private static readonly StringKey ShieldsDownName = "shields_down";
    private static readonly StringKey HarshSunlightName = "harsh_sunlight";
    private static readonly StringKey DesolateLandsName = "desolate_lands";
    private static readonly StringKey BulletproofName = "bulletproof";
    private static readonly StringKey FlashFireName = "flash_fire";
    private static readonly StringKey LightningRodName = "lightning_rod";
    private static readonly StringKey MotorDriveName = "motor_drive";
    private static readonly StringKey VoltAbsorbName = "volt_absorb";
    private static readonly StringKey SapSipperName = "sap_sipper";
    private static readonly StringKey SoundproofName = "soundproof";
    private static readonly StringKey StormDrainName = "storm_drain";
    private static readonly StringKey WaterAbsorbName = "water_absorb";
    private static readonly StringKey DrySkinName = "dry_skin";
    private static readonly StringKey TelepathyName = "telepathy";
    private static readonly StringKey WonderGuardName = "wonder_guard";
    private static readonly StringKey FireName = "fire";
    private static readonly StringKey ElectricName = "electric";
    private static readonly StringKey WaterName = "water";

    private static bool CanBePoisoned(IPokemon pokemon, IBattle battle)
    {
        if (battle.TerrainName == MistyTerrainName)
            return false;
        if (pokemon.Types.Any(x => x.Name == PoisonName || x.Name == SteelName))
            return false;
        if (pokemon.ActiveAbility?.Name == ImmunityName)
            return false;
        if (pokemon.ActiveAbility?.Name == PastelVeilName)
            return false;
        if (pokemon.ActiveAbility?.Name == FlowerVeilName && pokemon.Types.Any(x => x.Name == GrassName))
            return false;
        if ((pokemon.ActiveAbility?.Name == LeafGuardName && battle.WeatherName == HarshSunlightName) ||
            battle.WeatherName == DesolateLandsName)
            return false;
        if (pokemon.ActiveAbility?.Name == ComatoseName && pokemon.Species.Name == "komala")
            return false;
        if (pokemon.ActiveAbility?.Name == ShieldsDownName && pokemon.Species.Name == "minior" &&
            pokemon.Form.Name.Contains("-meteor"))
            return false;
        return true;
    }

    private static bool CanAbsorbMove(IPokemon pokemon, IMoveData move, TypeIdentifier moveType, IBattle battle)
    {
        if (pokemon.ActiveAbility == null)
            return false;

        var abilityName = pokemon.ActiveAbility.Name;

        if (abilityName == BulletproofName)
            return move.HasFlag("ballistics");
        if (abilityName == FlashFireName)
            return moveType.Name == FireName;
        if (abilityName == LightningRodName || abilityName == MotorDriveName || abilityName == VoltAbsorbName)
            return moveType.Name == ElectricName;
        if (abilityName == SapSipperName)
            return moveType.Name == GrassName;
        if (abilityName == SoundproofName)
            return move.HasFlag("sound");
        if (abilityName == StormDrainName || abilityName == WaterAbsorbName || abilityName == DrySkinName)
            return moveType.Name == WaterName;
        if (abilityName == TelepathyName)
            return false;
        if (abilityName == WonderGuardName)
        {
            var effectiveness = battle.Library.StaticLibrary.Types.GetEffectiveness(moveType, pokemon.Types);
            return effectiveness <= 1.0f;
        }

        return false;
    }
}