using PkmnLib.Static.Moves;

namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;

[Script(ScriptCategory.Pokemon, "confusion")]
public class Confusion : Script, IScriptStopBeforeMove
{
    private int _turnsConfused;

    /// <inheritdoc />
    public override void OnAddedToParent(IScriptSource source)
    {
        if (source is not IPokemon pokemon)
            throw new InvalidOperationException("Confusion script can only be added to a Pokemon.");
        var battleData = pokemon.BattleData;
        if (battleData == null)
            throw new InvalidOperationException("Confusion script requires a Pokemon to be in a battle.");
        _turnsConfused = battleData.Battle.Random.GetInt(2, 5);
    }

    /// <inheritdoc />
    public void StopBeforeMove(IExecutingMove move, ref bool stop)
    {
        _turnsConfused--;
        move.Battle.EventHook.Invoke(new DialogEvent("pokemon_is_confused", new Dictionary<string, object>
        {
            { "pokemon", move.User },
        }));
        if (_turnsConfused <= 0)
        {
            RemoveSelf();
            move.Battle.EventHook.Invoke(new DialogEvent("pokemon_snapped_out_of_confusion",
                new Dictionary<string, object>
                {
                    { "pokemon", move.User },
                }));
            return;
        }

        if (move.Battle.Random.GetInt(0, 100) < 33)
        {
            var damage = move.Battle.Library.DamageCalculator.GetDamage(null, MoveCategory.Physical, move.User,
                move.User, 1, 0, new ConfusionHitData());

            EventBatchId batchId = new();

            move.User.Damage(damage, DamageSource.Confusion, batchId);
            move.Battle.EventHook.Invoke(new DialogEvent("pokemon_hit_itself_in_confusion",
                new Dictionary<string, object>
                {
                    { "pokemon", move.User },
                    { "damage", damage },
                })
            {
                BatchId = batchId,
            });

            stop = true;
        }
    }

    private class ConfusionHitData : IHitData
    {
        /// <inheritdoc />
        public bool IsCritical => false;

        /// <inheritdoc />
        public ushort BasePower => 40;

        /// <inheritdoc />
        public float Effectiveness => 1.0f;

        /// <inheritdoc />
        public uint Damage { get; } = 0;

        /// <inheritdoc />
        public TypeIdentifier? Type => null;

        /// <inheritdoc />
        public bool IsContact => true;

        /// <inheritdoc />
        public bool HasFailed => false;

        /// <inheritdoc />
        public void Fail()
        {
        }

        /// <inheritdoc />
        public void SetFlag(StringKey flag)
        {
        }

        /// <inheritdoc />
        public bool HasFlag(StringKey flag) => false;
    }
}