using UnityEngine;
using UnityEngine.AI;
using System.Collections;

/// <summary>
/// Unified AI Controller that handles both enemy and teammate AI.
/// Replaces EnemyScript + EnemyNavigation with NavMeshAgent-based movement.
/// Works with CashSystemAI for Cash System mode decisions.
/// </summary>
[RequireComponent(typeof(Animator))]
public class CharacterAIController : MonoBehaviour
{
    #region Enums
    
    public enum AIState
    {
        Idle,
        Chasing,
        Attacking,
        Retreating,
        Blocking,
        Dead,
        Patrolling    // NEW: wander when no target in range
    }
    
    public enum AIMode
    {
        Practice,    // 1v1 mode - simple attack behavior
        CashSystem   // Team mode - coordinate with CashSystemAI
    }
    
    #endregion
    
    #region Fields
    
    [Header("AI Configuration")]
    [SerializeField] private CharacterStats characterStats;
    [SerializeField] private AIMode currentMode = AIMode.Practice;
    
    [Header("Combat Permission")]
    [Tooltip("Combat permission flag — toggled by RoundsScript/PlayerManagerNew between rounds")]
    public bool attack = true;
    
    [Header("Movement Settings")]
    [Tooltip("Base movement speed (replaces EnemyNavigation.speed)")]
    public float speed = 5f;
    [SerializeField] private float stoppingDistance = 1.5f;
    [SerializeField] private float rotationSpeed = 120f;
    
    [Header("Combat Settings")]
    [SerializeField] private float attackRange = 2f;
    [SerializeField] private float chaseRange = 20f;
    [SerializeField] private float attackCooldown = 1.5f;
    [SerializeField] private float randomAttackVariation = 0.5f;
    
    [Header("Retreat/Block Settings")]
    [SerializeField] private float retreatDistance = 4f;
    [SerializeField] private float retreatDuration = 1.5f;
    [SerializeField] private float blockDuration = 1.0f;
    [SerializeField] private float retreatChance = 0.15f;
    [SerializeField] private float blockChance = 0.20f;
    [SerializeField] private float healthRetreatThreshold = 30f;
    
    [Header("Decision Loop")]
    [SerializeField] private float decisionInterval = 0.3f;
    [SerializeField] private float farDecisionInterval = 0.8f;
    [SerializeField] private float lodDistance = 25f;
    
    [Header("Patrol Settings (Practice Mode)")]
    [SerializeField] private float patrolRadius = 10f;
    [SerializeField] private float patrolPauseMin = 1f;
    [SerializeField] private float patrolPauseMax = 2.5f;
    
    [Header("Grounding")]
    [Tooltip("Layers to raycast against for ground detection. Must exclude character layers to prevent floating.")]
    [SerializeField] private LayerMask groundLayerMask = 0;
    
    [Header("State")]
    [SerializeField] private AIState currentState = AIState.Idle;
    [SerializeField] private GameObject currentTarget;
    
    // Cached components
    private Animator anim;
    private NavMeshAgent navAgent;
    private TeamMember teamMember;
    private AnimationManager animationManager;
    private CharacterAttacks characterAttacks;
    private HealthNew health;
    private CashSystemAI cashSystemAI;
    
    // Cached external references
    private PlayerManagerNew cachedPlayerManager;
    private Camera cachedCamera;
    
    // Internal state
    private float lastAttackTime;
    private float distanceToTarget;
    private bool isAttacking;
    private float retreatEndTime;
    private float blockEndTime;
    private Vector3 retreatDirection;
    private Coroutine decisionCoroutine;
    
    // Patrol state
    private Vector3 patrolTarget;
    private bool hasPatrolTarget;
    private float patrolPauseEndTime;
    
    // Cash System combat — set by CashSystemAI when it wants us to fight
    private bool cashSystemCombatMode;
    
    // Gravity handling
    private float gvelocity;
    [SerializeField] private float gravity = -9.81f;
    [SerializeField] private float gravityScale = 0.75f;
    private bool jump;
    
    // Scale protection: animation clips with baked scale curves from FBX import
    // can shrink the character model. Save and restore original scale each frame.
    private Vector3 originalScale;
    
    #endregion
    
    #region Unity Lifecycle
    
    private void Awake()
    {
        originalScale = transform.localScale;
        CacheComponents();
    }
    
    private void Start()
    {
        InitializeAI();
        DetermineMode();
    }
    
    private void OnEnable()
    {
        // Reset state when AI is enabled
        currentState = AIState.Idle;
        isAttacking = false;
        
        // Re-warp to NavMesh when re-enabled (e.g., after control switch)
        if (navAgent != null && navAgent.isActiveAndEnabled)
        {
            WarpToNavMesh();
        }
        
        // Start the coroutine-based decision loop
        if (decisionCoroutine != null) StopCoroutine(decisionCoroutine);
        decisionCoroutine = StartCoroutine(AIDecisionLoop());
    }
    
    private void OnDisable()
    {
        if (decisionCoroutine != null)
        {
            StopCoroutine(decisionCoroutine);
            decisionCoroutine = null;
        }
    }
    
    /// <summary>
    /// FixedUpdate handles gravity and grounding every physics tick.
    /// This MUST run independently of the AI decision loop so characters
    /// stay grounded even before combat starts (attack == false).
    /// </summary>
    private void FixedUpdate()
    {
        ApplyGravity();
        EnsureUprightCharacter();
        
        // Protect against animation clips overwriting scale
        if (transform.localScale != originalScale)
        {
            transform.localScale = originalScale;
        }
    }
    
    private void CacheComponents()
    {
        anim = GetComponent<Animator>();
        navAgent = GetComponent<NavMeshAgent>();
        teamMember = GetComponent<TeamMember>();
        animationManager = GetComponent<AnimationManager>();
        characterAttacks = GetComponent<CharacterAttacks>();
        health = GetComponent<HealthNew>();
        cashSystemAI = GetComponent<CashSystemAI>();
        
        // Cache external singletons (lazy — may be null at Awake)
        cachedCamera = Camera.main;
    }
    
    private void InitializeAI()
    {
        // Apply stats if available
        if (characterStats != null)
        {
            attackRange = characterStats.preferredCombatRange;
            attackCooldown = 1f / characterStats.attackFrequency;
        }
        
        // Apply speed to NavMeshAgent
        if (navAgent != null)
        {
            navAgent.speed = speed;
            navAgent.stoppingDistance = stoppingDistance;
            
            // CRITICAL: Warp agent onto NavMesh surface to prevent floating.
            // NavMeshAgent can only manage grounding when it is ON the NavMesh.
            // If the agent was spawned slightly off the baked mesh, it floats.
            WarpToNavMesh();
        }
        
        lastAttackTime = -attackCooldown; // Allow immediate first attack
    }
    
    /// <summary>
    /// Warp the NavMeshAgent to the nearest valid NavMesh point.
    /// Prevents floating caused by spawning off-NavMesh.
    /// </summary>
    private void WarpToNavMesh()
    {
        if (navAgent == null) return;
        
        NavMeshHit navHit;
        if (NavMesh.SamplePosition(transform.position, out navHit, 20f, NavMesh.AllAreas))
        {
            navAgent.Warp(navHit.position);
            DevLog.Log($"[CharacterAIController] {gameObject.name}: Warped to NavMesh at Y={navHit.position.y} (was Y={transform.position.y})");
        }
        else
        {
            DevLog.LogWarning($"[CharacterAIController] {gameObject.name}: NO NavMesh found within 20m! Character will float. " +
                "Ensure NavMesh is baked for this scene.");
        }
    }
    
    private void DetermineMode()
    {
        // Check if we're in Cash System mode
        if (SelectionOptions.Instance != null && SelectionOptions.Instance.isCashSystemSelected)
        {
            currentMode = AIMode.CashSystem;
            DevLog.Log($"[CharacterAIController] {gameObject.name} set to CashSystem mode");
        }
        else
        {
            currentMode = AIMode.Practice;
            DevLog.Log($"[CharacterAIController] {gameObject.name} set to Practice mode");
        }
    }
    
    #endregion
    
    #region Coroutine Decision Loop
    
    /// <summary>
    /// Coroutine-based decision loop. Runs at variable intervals based on
    /// distance from camera (AI LOD). Much cheaper than Update() polling.
    /// </summary>
    private IEnumerator AIDecisionLoop()
    {
        yield return new WaitForSeconds(Random.Range(0.1f, 0.5f)); // Stagger AI startup
        
        while (enabled)
        {
            if (!IsGamePaused() && attack)
            {
                // Choose interval based on distance from camera (AI LOD)
                float interval = GetDecisionInterval();
                
                if (currentMode == AIMode.CashSystem)
                {
                    // CashSystem mode: CashSystemAI is the SOLE authority.
                    // We only sync animation — no state machine, no movement commands.
                    // CashSystemAI drives NavMeshAgent directly.
                    
                    // (Nothing to do here — animation sync is in UpdateCashSystemBehavior
                    //  which is now ONLY called for combat that CashSystemAI delegates)
                }
                else
                {
                    UpdatePracticeBehavior();
                }
                
                yield return new WaitForSeconds(interval);
            }
            else if (currentMode == AIMode.CashSystem)
            {
                // CRITICAL: In CashSystem mode, do NOT call StopMovement() when attack=false.
                // CashSystemAI manages NavMeshAgent independently of the attack flag.
                // The attack flag only gates combat actions inside CashSystemAI.IsCombatEnabled().
                // Collection, deposit, and patrol run regardless of the attack flag.
                yield return new WaitForSeconds(0.2f);
            }
            else
            {
                // Practice mode: Paused or attack disabled — stop moving, check again soon
                StopMovement();
                anim?.SetFloat("Speed", 0f);
                yield return new WaitForSeconds(0.2f);
            }
        }
    }
    
    /// <summary>
    /// AI LOD: slower decisions when far from camera
    /// </summary>
    private float GetDecisionInterval()
    {
        if (cachedCamera == null)
        {
            cachedCamera = Camera.main;
            if (cachedCamera == null) return decisionInterval;
        }
        
        float distFromCamera = Vector3.Distance(transform.position, cachedCamera.transform.position);
        return distFromCamera > lodDistance ? farDecisionInterval : decisionInterval;
    }
    
    #endregion
    
    #region Practice Mode Behavior
    
    private void UpdatePracticeBehavior()
    {
        // Find target if none
        if (currentTarget == null)
        {
            FindTarget();
            if (currentTarget == null) return;
        }
        
        // Check if target is still valid
        HealthNew targetHealth = currentTarget.GetComponent<HealthNew>();
        if (targetHealth != null && targetHealth.currentHealth <= 0)
        {
            currentTarget = null;
            SetState(AIState.Idle);
            StopMovement();
            return;
        }
        
        // Calculate distance
        distanceToTarget = CalculateDistanceToTarget();
        

        
        // State machine
        switch (currentState)
        {
            case AIState.Idle:
                HandleIdleState();
                break;
            case AIState.Chasing:
                HandleChasingState();
                break;
            case AIState.Attacking:
                HandleAttackingState();
                break;
            case AIState.Retreating:
                HandleRetreatingState();
                break;
            case AIState.Blocking:
                HandleBlockingState();
                break;
            case AIState.Patrolling:
                HandlePatrollingState();
                break;
        }
        
        // Always face target when in range
        if (distanceToTarget <= attackRange * 1.5f)
        {
            FaceTarget();
        }
    }
    
    private void HandleIdleState()
    {
        if (currentTarget != null && distanceToTarget <= chaseRange)
        {
            SetState(AIState.Chasing);
        }
        else
        {
            // No target in range — patrol instead of standing still
            SetState(AIState.Patrolling);
        }
    }
    
    /// <summary>
    /// GTA-style patrol: pick random nearby NavMesh points and walk between them.
    /// Immediately interrupts when a target enters chase range.
    /// </summary>
    private void HandlePatrollingState()
    {
        // Priority: if a target is in chase range, switch to chasing
        if (currentTarget != null && distanceToTarget <= chaseRange)
        {
            SetState(AIState.Chasing);
            hasPatrolTarget = false;
            return;
        }
        
        // Try to find a target periodically
        if (currentTarget == null)
        {
            FindTarget();
            if (currentTarget != null && CalculateDistanceToTarget() <= chaseRange)
            {
                SetState(AIState.Chasing);
                hasPatrolTarget = false;
                return;
            }
        }
        
        // Wait if pausing at patrol point
        if (Time.time < patrolPauseEndTime)
        {
            StopMovement();
            anim?.SetFloat("Speed", 0f);
            return;
        }
        
        // Check if reached current patrol point
        if (hasPatrolTarget)
        {
            float distToPatrol = Vector3.Distance(transform.position, patrolTarget);
            if (distToPatrol < 2f)
            {
                // Arrived — pause briefly, then pick new point
                patrolPauseEndTime = Time.time + Random.Range(patrolPauseMin, patrolPauseMax);
                hasPatrolTarget = false;
                StopMovement();
                anim?.SetFloat("Speed", 0f);
                return;
            }
            else
            {
                // Keep moving toward patrol point
                MoveToTarget(patrolTarget);
                anim?.SetFloat("Speed", 1f);
                return;
            }
        }
        
        // Pick a new random NavMesh point
        Vector3 randomDir = Random.insideUnitSphere * patrolRadius;
        randomDir.y = 0;
        Vector3 randomPoint = transform.position + randomDir;
        
        NavMeshHit hit;
        if (NavMesh.SamplePosition(randomPoint, out hit, patrolRadius, NavMesh.AllAreas))
        {
            patrolTarget = hit.position;
            hasPatrolTarget = true;
            MoveToTarget(patrolTarget);
            anim?.SetFloat("Speed", 1f);
        }
    }
    
    private void HandleChasingState()
    {
        if (currentTarget == null) { SetState(AIState.Idle); return; }
        
        MoveToTarget(currentTarget.transform.position);
        
        if (distanceToTarget <= attackRange && CanAttack())
        {
            SetState(AIState.Attacking);
        }
    }
    
    private void HandleAttackingState()
    {
        // Stop moving when attacking
        StopMovement();
        
        if (!isAttacking && CanAttack())
        {
            // Chance to retreat or block instead of attacking
            if (ShouldRetreat())
            {
                StartRetreat();
                return;
            }
            if (ShouldBlock())
            {
                StartBlock();
                return;
            }
            
            PerformAttack();
        }
        
        // Return to chasing if out of range
        if (distanceToTarget > attackRange * 1.2f)
        {
            SetState(AIState.Chasing);
        }
    }
    
    private void HandleRetreatingState()
    {
        if (Time.time >= retreatEndTime)
        {
            // Retreat done — go back to chasing
            SetState(AIState.Chasing);
            return;
        }
        
        // Move away from target
        if (navAgent != null && navAgent.isActiveAndEnabled && navAgent.isOnNavMesh)
        {
            Vector3 retreatPos = transform.position + retreatDirection * retreatDistance;
            navAgent.isStopped = false;
            navAgent.SetDestination(retreatPos);
            
            if (anim != null)
            {
                float spd = navAgent.velocity.magnitude / Mathf.Max(navAgent.speed, 0.01f);
                anim.SetFloat("Speed", spd);
            }
        }
    }
    
    private void HandleBlockingState()
    {
        StopMovement();
        
        if (Time.time >= blockEndTime)
        {
            // Block done — counterattack or chase
            if (anim != null) anim.SetBool("isBlocking", false);
            SetState(distanceToTarget <= attackRange ? AIState.Attacking : AIState.Chasing);
        }
    }
    
    private bool ShouldRetreat()
    {
        if (health == null) return false;
        
        // Higher chance to retreat when low health
        float healthPercent = (float)health.currentHealth / 100f;
        float adjustedChance = retreatChance;
        if (healthPercent * 100f < healthRetreatThreshold)
        {
            adjustedChance = retreatChance * 2.5f;
        }
        
        return Random.value < adjustedChance;
    }
    
    private bool ShouldBlock()
    {
        return Random.value < blockChance;
    }
    
    private void StartRetreat()
    {
        SetState(AIState.Retreating);
        retreatEndTime = Time.time + retreatDuration;
        
        // Calculate direction away from target
        if (currentTarget != null)
        {
            retreatDirection = (transform.position - currentTarget.transform.position).normalized;
            retreatDirection.y = 0;
        }
        else
        {
            retreatDirection = -transform.forward;
        }
        
        // Play retreat animation
        PlayAnimation(AnimationNames.JumpBack);
    }
    
    private void StartBlock()
    {
        SetState(AIState.Blocking);
        blockEndTime = Time.time + blockDuration;
        
        if (anim != null) anim.SetBool("isBlocking", true);
    }
    
    #endregion
    
    #region Cash System Mode Behavior
    
    /// <summary>
    /// CashSystem behavior: FULLY PASSIVE.
    /// CashSystemAI is the single authority — it drives NavMeshAgent directly,
    /// handles combat directly, and manages all decision-making.
    /// CharacterAIController does NOT touch NavMeshAgent in CashSystem mode.
    /// Animation is synced by CashSystemAI.SyncAnimation() directly.
    /// This method is kept as a no-op for backward compatibility.
    /// </summary>
    private void UpdateCashSystemBehavior()
    {
        // Intentionally empty — CashSystemAI owns everything in Cash System mode.
        // Animation sync is handled by CashSystemAI.SyncAnimation().
        // Combat is handled by CashSystemAI.PerformDirectAttack().
        // Navigation is handled by CashSystemAI.MoveToward().
    }
    
    #endregion
    
    #region Combat
    
    private void FindTarget()
    {
        // Use static TeamMember registry if available (zero-allocation)
        if (teamMember != null)
        {
            float nearestDistance = float.MaxValue;
            
            foreach (TeamMember other in TeamMember.AllMembers)
            {
                if (other == null || other == teamMember) continue;
                if (other.GetTeam() == teamMember.GetTeam()) continue;
                
                float distance = Vector3.Distance(transform.position, other.transform.position);
                if (distance < nearestDistance)
                {
                    nearestDistance = distance;
                    currentTarget = other.gameObject;
                }
            }
        }
        
        // Fallback: find player by tag
        if (currentTarget == null)
        {
            GameObject player = GameObject.FindGameObjectWithTag("Player");
            if (player != null && player != gameObject)
            {
                currentTarget = player;
            }
        }
    }
    
    private float CalculateDistanceToTarget()
    {
        if (currentTarget == null) return float.MaxValue;
        return Vector3.Distance(transform.position, currentTarget.transform.position);
    }
    
    private bool CanAttack()
    {
        return Time.time >= lastAttackTime + attackCooldown + Random.Range(-randomAttackVariation, randomAttackVariation);
    }
    
    private void PerformAttack()
    {
        if (isAttacking) return;
        
        isAttacking = true;
        lastAttackTime = Time.time;
        
        // Choose random attack type
        int attackType = Random.Range(0, 4);
        string animationName = "";
        
        switch (attackType)
        {
            case 0:
                animationName = AnimationNames.Jab;
                break;
            case 1:
                animationName = AnimationNames.Right;
                break;
            case 2:
                animationName = AnimationNames.LowKick;
                break;
            case 3:
                animationName = AnimationNames.Haymaker;
                break;
        }
        
        // Play animation
        PlayAnimation(animationName);
        
        // Reset attack flag after animation
        StartCoroutine(ResetAttackFlag(0.8f));
    }
    
    private IEnumerator ResetAttackFlag(float delay)
    {
        yield return new WaitForSeconds(delay);
        isAttacking = false;
    }
    
    private void PlayAnimation(string animationName)
    {
        if (animationManager != null)
        {
            animationManager.PlayAnimation(animationName);
        }
        else if (anim != null)
        {
            anim.Play(animationName);
        }
    }
    
    private void FaceTarget()
    {
        if (currentTarget == null) return;
        
        Vector3 direction = (currentTarget.transform.position - transform.position).normalized;
        direction.y = 0;
        
        if (direction != Vector3.zero)
        {
            Quaternion targetRotation = Quaternion.LookRotation(direction);
            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
        }
    }
    
    #endregion
    
    #region Movement Helpers
    
    private void MoveToTarget(Vector3 position)
    {
        if (navAgent == null || !navAgent.isActiveAndEnabled)
        {
            DevLog.LogWarning($"[CharacterAIController] {gameObject.name}: NavMeshAgent null or disabled, cannot move!");
            return;
        }
        
        // If agent fell off NavMesh, try to re-warp it
        if (!navAgent.isOnNavMesh)
        {
            DevLog.LogWarning($"[CharacterAIController] {gameObject.name}: Agent is OFF NavMesh! Attempting re-warp...");
            WarpToNavMesh();
            
            // If still not on NavMesh after warp, give up this frame
            if (!navAgent.isOnNavMesh)
            {
                Debug.LogError($"[CharacterAIController] {gameObject.name}: Re-warp FAILED. No NavMesh at position {transform.position}");
                return;
            }
        }
        
        navAgent.isStopped = false;
        navAgent.SetDestination(position);
        
        if (anim != null)
        {
            float spd = navAgent.velocity.magnitude / Mathf.Max(navAgent.speed, 0.01f);
            anim.SetFloat("Speed", spd);
        }
    }
    
    private void StopMovement()
    {
        if (navAgent != null && navAgent.isActiveAndEnabled && navAgent.isOnNavMesh)
        {
            navAgent.isStopped = true;
            navAgent.velocity = Vector3.zero;
        }
        
        if (anim != null)
        {
            anim.SetFloat("Speed", 0f);
        }
    }
    
    #endregion
    
    #region Character Stability
    
    private bool IsGamePaused()
    {
        // Lazy-cache PlayerManagerNew
        if (cachedPlayerManager == null)
        {
            cachedPlayerManager = FindFirstObjectByType<PlayerManagerNew>();
        }
        return cachedPlayerManager != null && cachedPlayerManager.pause;
    }
    
    private void EnsureUprightCharacter()
    {
        if (IsCharacterTilted())
        {
            Quaternion targetRotation = Quaternion.Euler(0, transform.rotation.eulerAngles.y, 0);
            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 5f);
        }
    }
    
    private bool IsCharacterTilted()
    {
        return Mathf.Abs(transform.rotation.eulerAngles.x) > 5f || 
               Mathf.Abs(transform.rotation.eulerAngles.z) > 5f;
    }
    
    private void ApplyGravity()
    {
        if (jump) return;
        
        // CRITICAL FIX: When NavMeshAgent is active and ON the NavMesh,
        // it handles Y-positioning automatically. Applying manual gravity
        // CONFLICTS with NavMeshAgent and causes jittering/floating.
        // Only apply manual gravity as a FALLBACK when the agent is off-mesh.
        if (navAgent != null && navAgent.isActiveAndEnabled && navAgent.isOnNavMesh)
        {
            // NavMeshAgent handles grounding — reset velocity and skip manual gravity
            gvelocity = 0;
            return;
        }
        
        gvelocity += gravity * gravityScale * Time.deltaTime;
        
        // Auto-configure ground layer mask if not set (exclude character layers)
        if (groundLayerMask.value == 0)
        {
            groundLayerMask = ~0; // Start with everything
            int playerLayer = LayerMask.NameToLayer("Player");
            int enemyLayer = LayerMask.NameToLayer("Enemy");
            int characterLayer = LayerMask.NameToLayer("Character");
            int ignoreRaycast = LayerMask.NameToLayer("Ignore Raycast");
            if (playerLayer >= 0) groundLayerMask &= ~(1 << playerLayer);
            if (enemyLayer >= 0) groundLayerMask &= ~(1 << enemyLayer);
            if (characterLayer >= 0) groundLayerMask &= ~(1 << characterLayer);
            if (ignoreRaycast >= 0) groundLayerMask &= ~(1 << ignoreRaycast);
        }
        
        // Fallback gravity: only runs when NavMeshAgent is NOT handling grounding
        float groundY = 0f;
        RaycastHit hit;
        if (Physics.Raycast(transform.position + Vector3.up * 0.5f, Vector3.down, out hit, 50f, groundLayerMask))
        {
            groundY = hit.point.y;
        }
        
        if (transform.position.y > groundY + 0.1f && !jump)
        {
            transform.position = new Vector3(
                transform.position.x,
                Mathf.Max(groundY + 0.05f, transform.position.y + gvelocity * Time.deltaTime),
                transform.position.z
            );
        }
        else
        {
            gvelocity = 0;
        }
    }
    
    #endregion
    
    #region Public API
    
    /// <summary>
    /// Set the current target for this AI
    /// </summary>
    public void SetTarget(GameObject target)
    {
        currentTarget = target;
    }
    
    /// <summary>
    /// Get the current AI state
    /// </summary>
    public AIState GetState()
    {
        return currentState;
    }
    
    /// <summary>
    /// Force the AI into a specific state
    /// </summary>
    public void SetState(AIState state)
    {
        if (currentState != state)
        {
            currentState = state;
        }
    }
    
    /// <summary>
    /// Set the AI mode
    /// </summary>
    public void SetMode(AIMode mode)
    {
        currentMode = mode;
    }
    
    /// <summary>
    /// Trigger an attack (can be called by CashSystemAI)
    /// </summary>
    public void TriggerAttack()
    {
        if (CanAttack())
        {
            PerformAttack();
        }
    }
    
    /// <summary>
    /// Update NavMeshAgent speed at runtime (replaces EnemyNavigation.speed setter)
    /// </summary>
    public void SetSpeed(float newSpeed)
    {
        speed = newSpeed;
        if (navAgent != null)
        {
            navAgent.speed = speed;
        }
    }
    
    /// <summary>
    /// Get current movement speed
    /// </summary>
    public float GetSpeed()
    {
        return speed;
    }
    
    /// <summary>
    /// Navigate to a world position (for CashSystemAI integration).
    /// Used for non-combat movement (collect, deposit, patrol).
    /// </summary>
    public void NavigateTo(Vector3 position)
    {
        cashSystemCombatMode = false; // Clear combat mode when navigating
        MoveToTarget(position);
    }
    
    /// <summary>
    /// Stop all movement (for CashSystemAI integration)
    /// </summary>
    public void Stop()
    {
        StopMovement();
    }
    
    /// <summary>
    /// Enter combat mode for Cash System — enables the chase→attack→retreat→block
    /// state machine against the current target. Called by CashSystemAI.ExecuteAttack()
    /// and CashSystemAI.ExecuteDefend().
    /// </summary>
    public void SetCashSystemCombatTarget(Vector3 targetPosition)
    {
        cashSystemCombatMode = true;
        
        // Ensure we start chasing if currently idle or patrolling
        if (currentState == AIState.Idle || currentState == AIState.Patrolling)
            SetState(AIState.Chasing);
    }
    
    /// <summary>
    /// Exit combat mode (called when CashSystemAI switches to non-combat state).
    /// </summary>
    public void ClearCashSystemCombat()
    {
        cashSystemCombatMode = false;
    }
    
    #endregion
}
