using UnityEngine;
using Pathfinding;
using UnityEngine.SceneManagement;

public class FollowerController : MonoBehaviour
{
    [Header("Follower Settings")]
    public float followDistance = 1.5f; // Desired distance behind player
    public bool debugDrawTarget = true;
    public float followUpdateInterval = 0.1f; // How often to update follow logic
    public float manualMoveSmooth = 8f; // Smoothing factor for manual movement

    private Transform playerTransform;
    private AIPath playerAIPath;
    private AIPath aiPath;
    private Vector3 targetPoint;
    private float timer;
    private bool usePathfinding = false;
    private bool isManualFollowing = true; // Default to manual following
    private Vector3 lastMoveDir = Vector3.right; // Default direction
    private float currentSpeed = 0f;

    [Header("Speed Settings")]
    public float acceleration = 10f;
    public float deceleration = 12f;
    public float thresholdFar = 2.5f;
    public float thresholdNear = 0.5f;
    public float stopThreshold = 0.1f; // Stop moving when within this distance
    private float playerMaxSpeed = 5f;

    void Awake()
    {
        aiPath = GetComponent<AIPath>();
    }

    void OnEnable()
    {
        SceneManager.sceneLoaded += OnSceneLoaded;
        FindPlayerReference();
    }

    void OnDisable()
    {
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }

    void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        FindPlayerReference();
    }

    void FindPlayerReference()
    {
        GameObject playerObj = GameObject.FindGameObjectWithTag("Player");
        if (playerObj != null)
        {
            playerTransform = playerObj.transform;
            playerAIPath = playerObj.GetComponent<AIPath>();
            if (playerAIPath != null)
            {
                playerMaxSpeed = playerAIPath.maxSpeed;
            }
        }
        else
        {
            playerTransform = null;
            playerAIPath = null;
        }
    }

    void Start()
    {
        FindPlayerReference();
    }

    void UpdateFollowTarget()
    {
        if (playerTransform == null)
        {
            // Try to reacquire reference if lost
            FindPlayerReference();
            if (playerTransform == null)
                return; // Still missing, skip update
        }
        // Determine direction: use player's velocity if available, else lastMoveDir
        Vector3 playerPos = playerTransform.position;
        Vector3 moveDir = Vector3.zero;
        if (playerAIPath != null && playerAIPath.velocity.magnitude > 0.01f)
        {
            moveDir = playerAIPath.velocity.normalized;
            lastMoveDir = moveDir; // Update last valid direction
        }
        else
        {
            moveDir = lastMoveDir; // Use last direction if stationary
        }
        // Calculate target point behind player
        targetPoint = playerPos - moveDir * followDistance;
        targetPoint.z = 0; // For 2D

        // Always use manual following unless GoToPoint is called
        isManualFollowing = true;
        if (aiPath != null)
        {
            aiPath.enabled = false;
        }
    }

    void Update()
    {
        if (playerTransform == null)
        {
            // Try to reacquire reference if lost
            FindPlayerReference();
            if (playerTransform == null)
                return; // Still missing, skip update
        }

        timer += Time.deltaTime;
        if (timer >= followUpdateInterval)
        {
            timer = 0f;
            UpdateFollowTarget();
        }

        // Manual movement logic with acceleration/deceleration and stop threshold
        if (isManualFollowing)
        {
            float dist = Vector3.Distance(transform.position, targetPoint);
            if (dist > stopThreshold)
            {
                float desiredSpeed = playerMaxSpeed;
                if (dist > thresholdFar)
                {
                    // Accelerate to player's max speed
                    desiredSpeed = Mathf.Min(currentSpeed + acceleration * Time.deltaTime, playerMaxSpeed);
                }
                else if (dist <= thresholdNear && dist > stopThreshold)
                {
                    // Decelerate as approaching target, but keep moving until stopThreshold
                    desiredSpeed = Mathf.Max(currentSpeed - deceleration * Time.deltaTime, 0.5f);
                }
                else
                {
                    // Maintain player's max speed
                    desiredSpeed = playerMaxSpeed;
                }
                currentSpeed = desiredSpeed;
                Vector3 dir = (targetPoint - transform.position).normalized;
                transform.position += dir * currentSpeed * Time.deltaTime;
            }
            else
            {
                // Stop moving when close enough
                currentSpeed = 0f;
            }
        }
    }

    // Command follower to go to a specific point (pathfinding mode)
    public void GoToPoint(Vector2 worldPosition)
    {
        isManualFollowing = false;
        if (aiPath != null)
        {
            aiPath.enabled = true;
            aiPath.destination = new Vector3(worldPosition.x, worldPosition.y, 0);
        }
    }

    void OnDrawGizmos()
    {
        if (debugDrawTarget && Application.isPlaying)
        {
            Gizmos.color = Color.cyan;
            Gizmos.DrawSphere(targetPoint, 0.2f);
            Gizmos.color = Color.yellow;
            Gizmos.DrawLine(transform.position, targetPoint);
        }
    }
}
