namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;

/// <summary>
/// PowerUpTypeAtLowHealth is a generic ability that increases the power of moves of a specific type when the user's HP is below a certain threshold.
/// The power increase is 1.5x when the user's HP falls below the specified threshold.
/// This ability is used by abilities like Blaze, Torrent, Overgrow, and Swarm.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Blaze_(Ability)">Bulbapedia - Blaze</see>
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Torrent_(Ability)">Bulbapedia - Torrent</see>
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Overgrow_(Ability)">Bulbapedia - Overgrow</see>
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Swarm_(Ability)">Bulbapedia - Swarm</see>
/// </summary>
[Script(ScriptCategory.Ability, "power_up_type_at_low_health")]
public class PowerUpTypeAtLowHealth : Script, IScriptOnInitialize, IScriptChangeDamageModifier
{
    private StringKey _type;
    private float _threshold;

    /// <inheritdoc />
    public void OnInitialize(IReadOnlyDictionary<StringKey, object?>? parameters)
    {
        if (parameters == null)
            throw new ArgumentNullException(nameof(parameters));

        if (!parameters.TryGetValue("type", out var type) || type is not string typeName)
            throw new ArgumentException("Parameter 'type' is required and must be a string.", nameof(parameters));
        if (!parameters.TryGetValue("threshold", out var threshold) || threshold is not float thresholdValue)
            throw new ArgumentException("Parameter 'threshold' is required and must be a float.", nameof(parameters));

        if (thresholdValue is < 0 or > 1)
            throw new ArgumentOutOfRangeException(nameof(threshold), "Threshold must be between 0 and 1.");

        _type = typeName;
        _threshold = thresholdValue;
    }

    /// <inheritdoc />
    public void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
    {
        var currentHealthFraction = move.User.CurrentHealth / (float)move.User.MaxHealth;
        if (currentHealthFraction <= _threshold && move.GetHitData(target, hit).Type?.Name == _type)
        {
            modifier *= 1.5f;
        }
    }
}