using System.Diagnostics;
using Godot;
using Godot.Collections;

namespace Cirno.Scripts.Components;

public partial class CameraPlayerDetection  : PlayerDetection
{
    
    [Export] public float SweepAngle = 90f; // In degrees
    [Export] public float SweepSpeed = 1f;  // Speed of sweeping
    [Export] public bool Debug = false;     // Enable debug lines
    [Export] public NodePath SpritePath;
    
    private float _currentAngle;
    private float _sweepDirection = 1f;
    private float _raycastLength;
    
    private AnimatedSprite2D _animatedSprite;

    public override void _Ready()
    {
        base._Ready();
        
        _animatedSprite = GetNode<AnimatedSprite2D>(SpritePath);
        
        var collisionShape = GetNode<CollisionShape2D>("CollisionShape2D");
        if (collisionShape.Shape is CircleShape2D circle)
        {
            _raycastLength = circle.Radius;
        }
    }
    
    public override void _PhysicsProcess(double delta)
    {
        base._PhysicsProcess(delta);
        SweepCamera((float)delta);
        
        UpdateSpriteDirection();
    }
    
    private void SweepCamera(float delta)
    {
        _currentAngle += _sweepDirection * SweepSpeed * delta;

        // Clamp angle within the sweep range
        float halfAngle = SweepAngle / 2f;
        if (_currentAngle > halfAngle || _currentAngle < -halfAngle)
        {
            _sweepDirection *= -1f;
            _currentAngle = Mathf.Clamp(_currentAngle, -halfAngle, halfAngle);
        }
        
        // if (result.Count > 0 && result["collider"] is InteractionController interactionController && interactionController == _cachedPlayer)
        // {
        //     GD.Print("Player detected!");
        //     // Handle detection logic here
        // }
    }

    private void DrawDebugLine(Vector2 endPoint)
    {
        // Request the node to redraw
        QueueRedraw();
        _debugLineEndPoint = endPoint;
    }

    private void UpdateSpriteDirection()
    {
        if (_animatedSprite == null) return;

        var frames = _animatedSprite.SpriteFrames.GetFrameCount("default");
        
        // Map angle (-SweepAngle/2 to +SweepAngle/2) to frame (0 to 5)
        float normalizedAngle = (_currentAngle + (SweepAngle / 2)) / SweepAngle;
        int frame = Mathf.Clamp((int)(normalizedAngle * frames), 0, frames);

        _animatedSprite.Frame = frame;
    }
    
    private Vector2 _debugLineEndPoint;

    public override void _Draw()
    {
        if (Debug)
        {
            DrawLine(Vector2.Zero, ToLocal(_debugLineEndPoint), Colors.Red, 2);
        }
    }
    
    public override bool IsPlayerInSight(uint collisionMask)
    {
        if (_cachedPlayer == null) return false;
        
        Vector2 direction = new Vector2(0, 1).Rotated(Mathf.DegToRad(_currentAngle));
        Vector2 rayEnd = GlobalPosition + direction * _raycastLength;

        // Perform raycast
        var spaceState = GetWorld2D().DirectSpaceState;
        var query = PhysicsRayQueryParameters2D.Create(GlobalPosition, rayEnd);
        query.Exclude = [GetRid()];
        query.CollideWithAreas = true;
        query.CollideWithBodies = true;
        query.CollisionMask = collisionMask;

        var result = spaceState.IntersectRay(query);

        bool detected = false;
        
        Vector2 debugLineEnd = rayEnd;
        if (result.Count > 0)
        {
            Node colliderNode = result["collider"].As<Node>();
            if (colliderNode is InteractionController interactionController && interactionController == _cachedPlayer)
            {
                detected = true;
            }
            // Adjust debug line to collision point
            debugLineEnd = (Vector2)result["position"];
        }
        
        if (Debug)
        {
            DrawDebugLine(debugLineEnd);
        }
        
        return detected;
    }
    
    private void _on_area_entered(Area2D area)
    {
        // Assume area is player for now
        if (area is not InteractionController player) return;
        
        GD.Print("Enemy detection area Entered by interaction controller");

        _cachedPlayer = player;

        IsPlayerInRange = true;
    }

    private void _on_area_exited(Area2D area)
    {
        if (area is not InteractionController player) return;
        IsPlayerInRange = false;
    }
}