using UnityEngine;
using UnityEngine.AI;

/// <summary>
/// AINavigationHelper — NavMeshAgent wrapper with path caching and mobile optimization.
/// Prevents unnecessary path recalculations and provides clean navigation API.
/// 
/// Only recalculates path when target moves >2m or path becomes invalid.
/// </summary>
public class AINavigationHelper : MonoBehaviour
{
    [Header("Navigation Settings")]
    [SerializeField] private float pathRecalcThreshold = 2f;  // Minimum target movement to recalc
    [SerializeField] private float stoppingDistance = 1.5f;
    [SerializeField] private float reachThreshold = 2f;

    [Header("Avoidance")]
    [SerializeField] private int avoidancePriority = 50;      // 0=highest priority, 99=lowest

    // ─── Components ──────────────────────────────────────────
    private NavMeshAgent _agent;
    private CharacterAIController _aiController;

    // ─── Path Cache ──────────────────────────────────────────
    private Vector3 _lastTargetPosition;
    private bool _hasDestination;

    // ─── Properties ──────────────────────────────────────────
    public bool HasArrived => _hasDestination && _agent != null && _agent.enabled &&
                              !_agent.pathPending &&
                              _agent.remainingDistance <= reachThreshold;

    public bool IsNavigating => _hasDestination && _agent != null && _agent.enabled &&
                                _agent.hasPath && _agent.remainingDistance > reachThreshold;

    public float RemainingDistance => _agent != null && _agent.enabled ? _agent.remainingDistance : float.MaxValue;

    private void Awake()
    {
        _agent = GetComponent<NavMeshAgent>();
        _aiController = GetComponent<CharacterAIController>();
    }

    private void Start()
    {
        if (_agent != null)
        {
            _agent.stoppingDistance = stoppingDistance;
            _agent.avoidancePriority = avoidancePriority;
        }
    }

    /// <summary>
    /// Navigate to a position. Only recalculates path if target moved significantly.
    /// </summary>
    public void SetDestination(Vector3 target)
    {
        // Use CharacterAIController if available (it handles NavMesh warping)
        if (_aiController != null)
        {
            float sqrDist = (target - _lastTargetPosition).sqrMagnitude;
            if (_hasDestination && sqrDist < pathRecalcThreshold * pathRecalcThreshold)
                return; // Target hasn't moved enough, keep current path

            _aiController.NavigateTo(target);
            _lastTargetPosition = target;
            _hasDestination = true;
            return;
        }

        // Direct NavMeshAgent fallback
        if (_agent == null || !_agent.enabled) return;

        float sqrDistDirect = (target - _lastTargetPosition).sqrMagnitude;
        if (_hasDestination && sqrDistDirect < pathRecalcThreshold * pathRecalcThreshold)
            return;

        _agent.SetDestination(target);
        _lastTargetPosition = target;
        _hasDestination = true;
    }

    /// <summary>Stop navigation immediately.</summary>
    public void Stop()
    {
        if (_aiController != null)
        {
            _aiController.Stop();
        }
        else if (_agent != null && _agent.enabled)
        {
            _agent.ResetPath();
        }

        _hasDestination = false;
    }

    /// <summary>Check if destination is approximately reached.</summary>
    public bool HasReachedDestination()
    {
        if (!_hasDestination) return true;

        if (_agent != null && _agent.enabled)
        {
            return !_agent.pathPending && _agent.remainingDistance <= reachThreshold;
        }

        // Fallback distance check
        return Vector3.SqrMagnitude(transform.position - _lastTargetPosition) < reachThreshold * reachThreshold;
    }

    /// <summary>Set avoidance priority (carriers get higher priority = lower number).</summary>
    public void SetAvoidancePriority(int priority)
    {
        avoidancePriority = priority;
        if (_agent != null) _agent.avoidancePriority = priority;
    }

    /// <summary>Set movement speed.</summary>
    public void SetSpeed(float speed)
    {
        if (_agent != null) _agent.speed = speed;
    }

    /// <summary>Warp to a position on the NavMesh.</summary>
    public bool WarpTo(Vector3 position)
    {
        if (_agent == null) return false;

        NavMeshHit hit;
        if (NavMesh.SamplePosition(position, out hit, 5f, NavMesh.AllAreas))
        {
            _agent.Warp(hit.position);
            return true;
        }
        return false;
    }

    /// <summary>Force path recalculation on next SetDestination call.</summary>
    public void InvalidatePath()
    {
        _lastTargetPosition = Vector3.zero;
        _hasDestination = false;
    }
}
