namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;

/// <summary>
/// PreventStatLowering is a generic ability that prevents the user's stats from being lowered by opposing Pokémon.
/// This ability can be configured to prevent lowering of a specific stat or all stats.
/// This ability is used by abilities like Clear Body, White Smoke, and Full Metal Body.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Clear_Body_(Ability)">Bulbapedia - Clear Body</see>
/// <see href="https://bulbapedia.bulbagarden.net/wiki/White_Smoke_(Ability)">Bulbapedia - White Smoke</see>
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Full_Metal_Body_(Ability)">Bulbapedia - Full Metal Body</see>
/// </summary>
[Script(ScriptCategory.Ability, "prevent_stat_lowering")]
public class PreventStatLowering : Script, IScriptOnInitialize, IScriptPreventStatBoostChange
{
    /// <summary>
    /// The statistic that this ability prevents from being lowered.
    /// Null means it prevents all stat lowering.
    /// </summary>
    private Statistic? _statistic;

    /// <inheritdoc />
    public void OnInitialize(IReadOnlyDictionary<StringKey, object?>? parameters)
    {
        if (parameters is null)
            throw new ArgumentNullException(nameof(parameters), "Parameters cannot be null.");
        if (parameters.TryGetValue("stat", out var statObj) && statObj is string statStr)
        {
            if (!Enum.TryParse(statStr, true, out Statistic stat))
                throw new ArgumentException($"Invalid statistic '{statStr}' provided.", nameof(statStr));
            _statistic = stat;
        }
    }

    /// <inheritdoc />
    public void PreventStatBoostChange(IPokemon target, Statistic stat, sbyte amount, bool selfInflicted,
        ref bool prevent)
    {
        if (_statistic is not null && _statistic != stat)
            return;
        if (amount >= 0)
            return;
        if (!selfInflicted)
        {
            target.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
            prevent = true;
        }
    }
}