using System.Linq;
using Cirno.Scripts.Resources;
using Godot;
using Godot.Collections;

namespace Cirno.Scripts.Components.Actors;

public partial class DamageReceiverActorModule : ActorModule, IHittable
{
    protected Actor _actor;
    
    [Export]
    public ActorResourceProvider HealthProvider { get; private set; }
    
    [Export]
    public bool Invulnerable { get; private set; } = false;

    [Export] public BulletOwner BulletGroup { get; set; } = BulletOwner.None;
    
    [Export] public Array<DamageResistance> DamageResistances { get; set; } = [];
    
    public override void Init(Actor actor)
    {
        _actor = actor;
        
        this.HealthProvider.MaxResource = actor.Health;

        HealthProvider.FillResource();
        HealthProvider.ResourceDepleted += OnDeath;
    }

    public override void Update(double delta)
    {
        
    }

    public override void PhysicsUpdate(double delta)
    {
        
    }
    
    private void _on_damage_hitbox_area_entered(Area2D area)
    {
        if (_actor.IsDestroyed) return;
        if (Invulnerable) return;
        if (area is not Bullet bullet) return;

        if (BulletGroup is BulletOwner.None)
        {
            this.Hit(bullet.Damage, bullet.DamageType);
            bullet.RequestCollisionDestruction();
            return;
        }

        if (bullet.BulletInfo.Owner == BulletGroup) return; 
        
        this.Hit(bullet.Damage, bullet.DamageType);
        bullet.RequestCollisionDestruction();
    }
    
    public void Hit(float damage, DamageType damageType = DamageType.Neutral)
    {
        if (_actor.IsDestroyed) return;
        if (Invulnerable) return;
		
        var dmg = DamageResistances.Aggregate(damage, (current, resistance) => current * resistance.CalculateDamage(current, damageType));

        HealthProvider.CurrentResource -= dmg;
    }
    
    protected void OnDeath()
    {
        _actor.IsDestroyed = true;
        _actor.TriggerDeath();
    }
}