using System.Collections.Generic;
using WingsEmu.Game;
using WingsEmu.Game._enum;
using WingsEmu.Game.Battle;
using WingsEmu.Game.Buffs;
using WingsEmu.Game.Characters;
using WingsEmu.Game.Entities;
using WingsEmu.Game.Extensions;
using WingsEmu.Packets.Enums;

namespace WingsEmu.Plugins.BasicImplementations.BCards.Handlers;

public class BCardSpecialDamageHandler : IBCardEffectAsyncHandler
{
    private readonly IRandomGenerator _randomGenerator;

    public BCardSpecialDamageHandler(IRandomGenerator randomGenerator) => _randomGenerator = randomGenerator;

    public BCardType HandledType => BCardType.SpecialDamageAndExplosions;

    public void Execute(IBCardEffectContext ctx)
    {
        IBattleEntity sender = ctx.Sender;
        IBattleEntity target = ctx.Target;

        if (sender == null)
        {
            return;
        }

        if (target == null)
        {
            return;
        }

        if (sender.MapInstance?.Id != target.MapInstance?.Id)
        {
            return;
        }

        int firstData = ctx.BCard.FirstDataValue(sender.Level);
        int secondData = ctx.BCard.SecondDataValue(sender.Level);

        switch ((AdditionalTypes.SpecialDamageAndExplosions)ctx.BCard.SubType)
        {
            case AdditionalTypes.SpecialDamageAndExplosions.ChanceExplosion:
                if (!target.IsAlive())
                {
                    return;
                }

                if (_randomGenerator.RandomNumber() > firstData)
                {
                    return;
                }

                if (target.Hp - secondData <= 0)
                {
                    target.Hp = 1;
                }
                else
                {
                    target.Hp -= secondData;
                }

                target.BroadcastEffectInRange(EffectType.FireExplosion);
                if (target is not IPlayerEntity playerEntity)
                {
                    return;
                }

                playerEntity.Session.RefreshStat();
                break;
            case AdditionalTypes.SpecialDamageAndExplosions.ExplosionCauses:

                IEnumerable<IBattleEntity> targets = sender.GetEnemiesInRange(sender, (byte)firstData);

                foreach (IBattleEntity skillTarget in targets)
                {
                    skillTarget.BroadcastEffectInRange(EffectType.SmokePuff);
                    if (skillTarget.Hp - secondData <= 0)
                    {
                        skillTarget.BroadcastDamage(skillTarget.Hp - 1);
                        skillTarget.Hp = 1;
                    }
                    else
                    {
                        skillTarget.Hp -= secondData;
                        skillTarget.BroadcastDamage(secondData);
                    }

                    if (skillTarget is not IPlayerEntity player)
                    {
                        continue;
                    }

                    player.Session.RefreshStat();
                }

                break;
            case AdditionalTypes.SpecialDamageAndExplosions.ExplosionCausesNegated:

                targets = target.GetAlliesInRange(target, (byte)firstData);

                foreach (IBattleEntity skillTarget in targets)
                {
                    skillTarget.BroadcastEffectInRange(EffectType.FireExplosion);
                    if (skillTarget.Hp - secondData <= 0)
                    {
                        skillTarget.BroadcastDamage(skillTarget.Hp - 1);
                        skillTarget.Hp = 1;
                    }
                    else
                    {
                        skillTarget.Hp -= secondData;
                        skillTarget.BroadcastDamage(secondData);
                    }

                    if (skillTarget is not IPlayerEntity player)
                    {
                        continue;
                    }

                    player.Session.RefreshStat();
                }

                break;
        }
    }
}