using Cirno.Scripts.Enums;
using Godot;

namespace Cirno.Scripts.Components.Actors;

public partial class EnemyTurretRotationMovement : MovementHandler
{
    public override Vector2 MovementDirection
    {
        get => _parent.MovementDirection;
        set => _parent.MovementDirection = value;
    }
    public override Vector2 FacingDirection
    {
        get => _parent.FacingDirection;
        set => _parent.FacingDirection = value;
    }
    
    [Export] public float PlayerDisengageRange = 500f;

    [Export(PropertyHint.Layers2DPhysics)]
    public uint CollisionMask { get; set; }
    
    public bool IsDestroyed => _parent.IsDestroyed;
    
    [Export] public Weapon EquippedWeapon;
    
    [Export] private PlayerDetection _playerDetection;
    
    private Vector2? _lastPlayerPosition = null;
    
    private ActorAi _actorAi;
    
    private bool IsPlayerInRange => _playerDetection is { IsPlayerInRange: true };

    private bool IsPlayerInSight =>
        _playerDetection is not null && _playerDetection.IsPlayerInSight(CollisionMask);
    
    public override void Init(Actor parent)
    {
        base.Init(parent);

        MovementDirection = Vector2.Zero;
        FacingDirection = Vector2.Down;

        _actorAi = parent.GetNode<ActorAi>("ActorAi");
        
    }
    
    public override void Update(double delta)
    {
        
    }

    public override void PhysicsUpdate(double delta)
    {
        if (IsDestroyed) return;
        if (_actorAi.Ai is not AiState.Enabled)
            return;
        
        switch (_actorAi.State)
        {
            case EnemyState.Idle:
                if (_playerDetection != null && IsPlayerInRange && IsPlayerInSight)
                {
                    _actorAi.State = EnemyState.Alert;
                }

                break;
            case EnemyState.Alert:

                // Update last known player position if it's in range
                if (IsPlayerInRange)
                {
                    _lastPlayerPosition = _playerDetection.CachedPlayer.GlobalPosition;
                }
                
                if (IsPlayerInRange && IsPlayerInSight)
                {
                    Shoot();
                }
                else
                {
                    _actorAi.State = EnemyState.Idle;
                }
                break;
        }
    }

    private void Shoot()
    {
        if (EquippedWeapon == null || !_lastPlayerPosition.HasValue) return;
        
        var direction = (_lastPlayerPosition.Value - _parent.GlobalPosition).Normalized();
        
        // Shoot at the player's last known position
        EquippedWeapon.ShootDirection = direction;
        FacingDirection = direction;
        
        EquippedWeapon.Shoot();
    }
}