using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Rendering.UI;
using UnityEngine.UIElements;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance { get; private set; }
    public List<GameObject> playerCharacters = new List<GameObject>();
    public List<GameObject> enemyCharacters = new List<GameObject>();

    [Header("Decision Controller")]
    public PlayerDecisionController playerDecisionController;

    private Dictionary<GameObject, GameObject> enemySelectedTargets = new Dictionary<GameObject, GameObject>();
    public bool isContinuousRunActive = false; // Indicates if the game is in continuous run mode

    private const string ENEMY_LAYER_NAME = "Enemies";
    private int enemyLayerMask;
    private bool isActionExecutionPhaseActive;
    private bool waitingForAdvanceInput = false;

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);

            // Initialize PlayerDecisionController if not set
            if (playerDecisionController == null)
            {
                playerDecisionController = FindFirstObjectByType<PlayerDecisionController>();
                if (playerDecisionController == null)
                {
                    GameObject pdcGO = new GameObject("PlayerDecisionController");
                    playerDecisionController = pdcGO.AddComponent<PlayerDecisionController>();

                }
            }

            int enemyLayer = LayerMask.NameToLayer(ENEMY_LAYER_NAME);
            if (enemyLayer == -1)
            {
                Debug.LogError($"Layer '{ENEMY_LAYER_NAME}' not found. Please create it in Project Settings > Tags and Layers, and assign your enemy prefabs to it.");
                // Disable functionality or handle error appropriately
            }
            else
            {
                enemyLayerMask = 1 << enemyLayer;
            }
        }
        else
        {
            Destroy(gameObject);
            return; // Avoid further initialization if this is not the singleton instance
        }
    }

    internal void StartBattle(List<GameObject> placedPlayerCharacters, List<GameObject> placedEnemyCharacters)
    {
        playerCharacters = placedPlayerCharacters;
        enemyCharacters = placedEnemyCharacters;

        // Refresh PlayerDecisionController with current player characters
        if (playerDecisionController != null)
        {
            playerDecisionController.RefreshPlayerCharacters();
            playerDecisionController.SetEnabled(false); // Disable initially until decision phase
        }

        // Start the battle logic here


        EnemiesDecideAction();
        StartCoroutine(MainBattleLoopCoroutine());
    }

    private IEnumerator MainBattleLoopCoroutine()
    {
        while (true) // Main battle loop
        {
            // --- Player Decision Phase ---
            Time.timeScale = 1f; // Ensure normal time scale for player decision phase


            // Check for completed movements before turn starts
            CheckAndResetCompletedMovements();

            // Keep existing actions, only allow new decisions for characters with no action
            playerDecisionController.UpdateVisualStates(); // Update colors: pink for no action, green for incomplete
            playerDecisionController.SetEnabled(true);

            // Show lines for any existing incomplete actions
            playerDecisionController.ShowActiveActionLines();

            // Wait for all players to make their initial decisions (only needed at turn start)
            while (!playerDecisionController.AllCharactersHaveActions())
            {
                yield return null; // Wait for player input through PlayerDecisionController
            }

            // Disable input during execution phase and hide action lines
            playerDecisionController.SetEnabled(false);
            playerDecisionController.HideActiveActionLines();


            // --- Pause point after decision (if not in continuous run mode) ---
            if (!isContinuousRunActive)
            {

                PauseGame();
                yield return new WaitUntil(() => Time.timeScale > 0 || isContinuousRunActive);
            }

            if (Time.timeScale == 0 && isContinuousRunActive)
            {
                ResumeGame();
            }

            // --- Action execution phase ---

            // yield return StartCoroutine(ExecutePlayerActionsCoroutine());
            yield return StartCoroutine(ExecuteAllActionsSimultaneously());
            // TODO: add ement action execution here for a full turn


            if (BattleUIManager.Instance != null)
            {
                BattleUIManager.Instance.SetButtonsInteractable(true);
            }

            EnemiesDecideAction(); // Enemies decide their actions after players have executed their actions
            // --- Post-Actions: Loop or Pause ---
            if (isContinuousRunActive)
            {

                if (Time.timeScale > 0)
                {
                    yield return new WaitForSeconds(0.5f); // Brief delay if running
                }
            }
            else
            {

                PauseGame();
            }

            // Check for battle end conditions using proper alive/dead detection
            List<GameObject> alivePlayers = GetAlivePlayers();
            List<GameObject> aliveEnemies = GetAliveEnemies();

            // Debug: Log current battle state
            Debug.Log($"🔍 Battle state check: {alivePlayers.Count} alive players, {aliveEnemies.Count} alive enemies");

            if (alivePlayers.Count == 0 || aliveEnemies.Count == 0)
            {
                Debug.Log("🏁 BATTLE END DETECTED!");
                PauseGame();
                if (BattleUIManager.Instance != null)
                {
                    BattleUIManager.Instance.DisableBattleControls(); // Disable UI controls
                }

                // Handle battle end logic
                if (alivePlayers.Count == 0)
                {
                    Debug.Log("💀 PLAYER DEFEAT");
                    HandlePlayerDefeat(playerCharacters);
                }
                else if (aliveEnemies.Count == 0)
                {
                    Debug.Log("🏆 PLAYER VICTORY");
                    HandlePlayerVictory(enemyCharacters);
                }

                break; // Exit the loop if battle is over
            }
        }
    }

    public List<GameObject> GetAllCharacters()
    {
        return playerCharacters.Concat(enemyCharacters).ToList();
    }

    /// <summary>
    /// Get all alive player characters
    /// </summary>
    public List<GameObject> GetAlivePlayers()
    {
        var alive = playerCharacters
            .Where(p => p != null)
            .Where(p =>
            {
                var character = p.GetComponent<Character>();
                bool isAlive = character != null && !character.IsDead;
                Debug.Log($"🔍 Player {p.name}: Character={character != null}, IsDead={character?.IsDead}, Alive={isAlive}");
                return isAlive;
            })
            .ToList();

        Debug.Log($"🔍 Total alive players: {alive.Count}/{playerCharacters.Count}");
        return alive;
    }

    /// <summary>
    /// Get all alive enemy characters
    /// </summary>
    public List<GameObject> GetAliveEnemies()
    {
        var alive = enemyCharacters
            .Where(e => e != null)
            .Where(e =>
            {
                var character = e.GetComponent<Character>();
                bool isAlive = character != null && !character.IsDead;
                Debug.Log($"🔍 Enemy {e.name}: Character={character != null}, IsDead={character?.IsDead}, Alive={isAlive}");
                return isAlive;
            })
            .ToList();

        Debug.Log($"🔍 Total alive enemies: {alive.Count}/{enemyCharacters.Count}");
        return alive;
    }

    /// <summary>
    /// Handle player victory (all enemies defeated)
    /// </summary>
    private void HandlePlayerVictory(List<GameObject> defeatedEnemies)
    {
        Debug.Log("🏆 Players have won the battle!");

        // Check if there are actually any enemies to loot
        bool hasLootableEnemies = false;
        if (defeatedEnemies != null && defeatedEnemies.Count > 0)
        {
            foreach (var enemy in defeatedEnemies)
            {
                if (enemy != null)
                {
                    var character = enemy.GetComponent<Character>();
                    if (character != null && character.IsDead)
                    {
                        hasLootableEnemies = true;
                        break;
                    }
                }
            }
        }

        if (hasLootableEnemies)
        {
            // Find or create the post-battle loot system
            var lootSystem = FindFirstObjectByType<PostBattleLootSystem>();
            if (lootSystem == null)
            {
                // Create loot system if it doesn't exist
                GameObject lootSystemGO = new GameObject("PostBattleLootSystem");
                lootSystem = lootSystemGO.AddComponent<PostBattleLootSystem>();
            }

            // Initialize and start looting
            lootSystem.InitializeLootSystem(defeatedEnemies);
            lootSystem.OnLootingComplete += OnLootingComplete;
            lootSystem.StartLooting();
        }
        else
        {
            // No loot to collect, show victory screen with return button
            Debug.Log("🏆 No loot to collect, showing victory screen");
            StartCoroutine(ShowVictoryScreenAndReturn());
        }
    }

    /// <summary>
    /// Handle player defeat (all players dead)
    /// </summary>
    private void HandlePlayerDefeat(List<GameObject> defeatedPlayers)
    {
        Debug.Log("💀 All players have been defeated!");

        // Find or create the game over screen
        var gameOverScreen = FindFirstObjectByType<GameOverScreen>();
        if (gameOverScreen == null)
        {
            // Create game over screen if it doesn't exist
            GameObject gameOverGO = new GameObject("GameOverScreen");
            gameOverScreen = gameOverGO.AddComponent<GameOverScreen>();
        }

        // Show game over screen with statistics
        gameOverScreen.ShowGameOver(defeatedPlayers);
    }

    /// <summary>
    /// Show a simple victory screen when there's no loot and allow return to map
    /// </summary>
    private System.Collections.IEnumerator ShowVictoryScreenAndReturn()
    {
        // Create a simple victory overlay using UI Toolkit or IMGUI
        GameObject victoryUIGO = new GameObject("VictoryUI");
        var uiDocument = victoryUIGO.AddComponent<UIDocument>();

        // Create basic victory UI
        var rootElement = uiDocument.rootVisualElement;

        // Create overlay
        var overlay = new VisualElement();
        overlay.style.position = Position.Absolute;
        overlay.style.top = 0;
        overlay.style.left = 0;
        overlay.style.right = 0;
        overlay.style.bottom = 0;
        overlay.style.backgroundColor = new Color(0, 0, 0, 0.8f);
        overlay.style.justifyContent = Justify.Center;
        overlay.style.alignItems = Align.Center;

        // Create victory panel
        var panel = new VisualElement();
        panel.style.backgroundColor = new Color(0.1f, 0.3f, 0.1f, 0.95f);
        panel.style.borderTopWidth = 3;
        panel.style.borderBottomWidth = 3;
        panel.style.borderLeftWidth = 3;
        panel.style.borderRightWidth = 3;
        panel.style.borderTopColor = Color.yellow;
        panel.style.borderBottomColor = Color.yellow;
        panel.style.borderLeftColor = Color.yellow;
        panel.style.borderRightColor = Color.yellow;
        panel.style.borderTopLeftRadius = 15;
        panel.style.borderTopRightRadius = 15;
        panel.style.borderBottomLeftRadius = 15;
        panel.style.borderBottomRightRadius = 15;
        panel.style.paddingTop = 40;
        panel.style.paddingBottom = 40;
        panel.style.paddingLeft = 60;
        panel.style.paddingRight = 60;
        panel.style.width = 500;

        // Victory title
        var title = new Label("🏆 VICTORY! 🏆");
        title.style.fontSize = 36;
        title.style.color = Color.yellow;
        title.style.unityTextAlign = TextAnchor.MiddleCenter;
        title.style.marginBottom = 20;
        title.style.unityFontStyleAndWeight = FontStyle.Bold;

        // Victory message
        var message = new Label("The enemies have been defeated!\nThe battle is won!");
        message.style.fontSize = 18;
        message.style.color = Color.white;
        message.style.unityTextAlign = TextAnchor.MiddleCenter;
        message.style.marginBottom = 30;
        message.style.whiteSpace = WhiteSpace.Normal;

        // Return button
        var returnButton = new Button(() =>
        {
            // Destroy the victory UI
            if (victoryUIGO != null) Destroy(victoryUIGO);

            // Proceed to return to exploration
            OnLootingComplete();
        });
        returnButton.text = "Return to Map";
        returnButton.style.fontSize = 18;
        returnButton.style.paddingTop = 15;
        returnButton.style.paddingBottom = 15;
        returnButton.style.paddingLeft = 30;
        returnButton.style.paddingRight = 30;
        returnButton.style.backgroundColor = new Color(0.2f, 0.7f, 0.2f, 0.9f);
        returnButton.style.color = Color.white;
        returnButton.style.borderTopLeftRadius = 8;
        returnButton.style.borderTopRightRadius = 8;
        returnButton.style.borderBottomLeftRadius = 8;
        returnButton.style.borderBottomRightRadius = 8;
        returnButton.style.marginBottom = 10;

        // Backup return button (fallback)
        var backupButton = new Button(() =>
        {
            // Destroy the victory UI
            if (victoryUIGO != null) Destroy(victoryUIGO);

            // Direct scene load as fallback
            try
            {
                Debug.Log("🗺️ Using backup scene transition to MapScene2");
                UnityEngine.SceneManagement.SceneManager.LoadScene("MapScene2");
            }
            catch (System.Exception e)
            {
                Debug.LogError($"Backup scene transition failed: {e.Message}");
            }
        });
        backupButton.text = "Force Return to Map";
        backupButton.style.fontSize = 14;
        backupButton.style.paddingTop = 10;
        backupButton.style.paddingBottom = 10;
        backupButton.style.paddingLeft = 20;
        backupButton.style.paddingRight = 20;
        backupButton.style.backgroundColor = new Color(0.7f, 0.4f, 0.2f, 0.9f);
        backupButton.style.color = Color.white;
        backupButton.style.borderTopLeftRadius = 5;
        backupButton.style.borderTopRightRadius = 5;
        backupButton.style.borderBottomLeftRadius = 5;
        backupButton.style.borderBottomRightRadius = 5;

        // Space key hint
        var hint = new Label("Press SPACE or click the button to continue");
        hint.style.fontSize = 14;
        hint.style.color = Color.gray;
        hint.style.unityTextAlign = TextAnchor.MiddleCenter;
        hint.style.marginTop = 15;

        // Assemble UI
        panel.Add(title);
        panel.Add(message);
        panel.Add(returnButton);
        panel.Add(backupButton);
        panel.Add(hint);
        overlay.Add(panel);
        rootElement.Add(overlay);

        // Make the UI focusable for keyboard input
        rootElement.focusable = true;
        rootElement.Focus();

        // Handle keyboard input
        bool waitingForInput = true;
        rootElement.RegisterCallback<KeyDownEvent>((evt) =>
        {
            if (evt.keyCode == KeyCode.Space && waitingForInput)
            {
                waitingForInput = false;
                if (victoryUIGO != null) Destroy(victoryUIGO);
                OnLootingComplete();
            }
        });

        // Wait for user input (this coroutine will be stopped when the button is clicked or space is pressed)
        while (waitingForInput && victoryUIGO != null)
        {
            yield return null;
        }
    }

    /// <summary>
    /// Called when looting is complete, proceed to end battle
    /// </summary>
    private void OnLootingComplete()
    {
        Debug.Log("🏆 Battle and looting complete, returning to exploration");
        Debug.Log($"🏆 Called from: {System.Environment.StackTrace}");

        // Save any updated team data back to the game state
        SaveBattleResults();

        // Return to MapScene2 (exploration scene)
        StartCoroutine(ReturnToExplorationScene());
    }

    /// <summary>
    /// Save battle results and return to exploration
    /// </summary>
    private System.Collections.IEnumerator ReturnToExplorationScene()
    {
        Debug.Log("🗺️ Starting return to exploration scene...");

        // Give a brief moment for any final UI updates
        yield return new WaitForSeconds(0.5f);

        // Load the exploration scene
        try
        {
            Debug.Log("🗺️ Loading MapScene2...");
            UnityEngine.SceneManagement.SceneManager.LoadScene("MapScene2");
            Debug.Log("🗺️ Scene load initiated successfully");
        }
        catch (System.Exception e)
        {
            Debug.LogError($"❌ Failed to load MapScene2: {e.Message}");
            Debug.LogError($"Stack trace: {e.StackTrace}");

            // Fallback - try to find and use battle setup
            var battleSetup = FindFirstObjectByType<EnhancedBattleSetup>();
            if (battleSetup != null)
            {
                Debug.Log("🔄 Trying fallback via EnhancedBattleSetup...");
                battleSetup.EndBattleSession(true); // Player victory
            }
            else
            {
                Debug.LogWarning("⚠️ No scene transition method available");

                // Create a simple UI to inform the player
                GameObject errorUIGO = new GameObject("SceneLoadErrorUI");
                var uiDocument = errorUIGO.AddComponent<UIDocument>();
                var rootElement = uiDocument.rootVisualElement;

                var overlay = new VisualElement();
                overlay.style.position = Position.Absolute;
                overlay.style.top = 0;
                overlay.style.left = 0;
                overlay.style.right = 0;
                overlay.style.bottom = 0;
                overlay.style.backgroundColor = new Color(0.5f, 0, 0, 0.8f);
                overlay.style.justifyContent = Justify.Center;
                overlay.style.alignItems = Align.Center;

                var errorLabel = new Label("Scene transition failed. Please restart the game.");
                errorLabel.style.fontSize = 18;
                errorLabel.style.color = Color.white;
                errorLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
                errorLabel.style.backgroundColor = new Color(0.2f, 0.2f, 0.2f, 0.9f);
                errorLabel.style.paddingTop = 20;
                errorLabel.style.paddingBottom = 20;
                errorLabel.style.paddingLeft = 20;
                errorLabel.style.paddingRight = 20;
                errorLabel.style.borderTopLeftRadius = 10;
                errorLabel.style.borderTopRightRadius = 10;
                errorLabel.style.borderBottomLeftRadius = 10;
                errorLabel.style.borderBottomRightRadius = 10;

                overlay.Add(errorLabel);
                rootElement.Add(overlay);
            }
        }
    }

    /// <summary>
    /// Save battle results back to persistent game state
    /// </summary>
    private void SaveBattleResults()
    {
        // Update team data with any changes from battle (health, items, etc.)
        var alivePlayerCharacters = GetAlivePlayers();

        // You could save character states here if needed
        Debug.Log($"💾 Saved battle results for {alivePlayerCharacters.Count} surviving players");
    }

    #region Debug and Testing Methods

    /// <summary>
    /// [DEBUG] Force battle end for testing post-battle systems
    /// </summary>
    [ContextMenu("Test Battle Victory")]
    public void TestBattleVictory()
    {
        Debug.Log("🧪 [TEST] Forcing battle victory to test post-battle loot system");

        // Kill all enemies for testing
        foreach (var enemy in enemyCharacters)
        {
            if (enemy != null)
            {
                var character = enemy.GetComponent<Character>();
                if (character != null && !character.IsDead)
                {
                    // Force enemy death for testing
                    character.TakeDamage(1000);
                }
            }
        }

        // Manually trigger victory
        HandlePlayerVictory(enemyCharacters);
    }

    /// <summary>
    /// [DEBUG] Force battle defeat for testing game over
    /// </summary>
    [ContextMenu("Test Battle Defeat")]
    public void TestBattleDefeat()
    {
        Debug.Log("🧪 [TEST] Forcing battle defeat to test game over screen");

        // Kill all players for testing
        foreach (var player in playerCharacters)
        {
            if (player != null)
            {
                var character = player.GetComponent<Character>();
                if (character != null && !character.IsDead)
                {
                    // Force player death for testing
                    character.TakeDamage(1000);
                }
            }
        }

        // Manually trigger defeat
        HandlePlayerDefeat(playerCharacters);
    }

    /// <summary>
    /// [PUBLIC] Manually trigger return to map - can be called by UI buttons or debug scripts
    /// </summary>
    public void ManualReturnToMap()
    {
        Debug.Log("🗺️ [MANUAL] Manual return to map requested");

        // Save any updated team data back to the game state
        SaveBattleResults();

        // Return to MapScene2 (exploration scene)
        StartCoroutine(ReturnToExplorationScene());
    }

    #endregion

    private IEnumerator ExecuteAllActionsSimultaneously()
    {

        isActionExecutionPhaseActive = true;

        var allActions = new Dictionary<GameObject, GameObject>();
        var movementActions = new Dictionary<GameObject, Vector3>();

        // Collect player actions from Character components
        foreach (GameObject playerGO in playerCharacters)
        {
            Character character = playerGO.GetComponent<Character>();
            if (character != null && character.actionData.hasTarget)
            {
                if (character.actionData.targetEnemy != null)
                {
                    allActions[playerGO] = character.actionData.targetEnemy;
                }
                else if (character.actionData.targetPosition != Vector3.zero)
                {
                    movementActions[playerGO] = character.actionData.targetPosition;
                }
            }
        }

        foreach (var action in enemySelectedTargets)
        {
            allActions[action.Key] = action.Value;
        }

        int playerActionsCount = allActions.Count - enemySelectedTargets.Count + movementActions.Count;


        enemySelectedTargets.Clear(); // Clear enemy targets as well

        if (allActions.Count == 0 && movementActions.Count == 0)
        {

            isActionExecutionPhaseActive = false;
            yield break;
        }

        // Configure All NavMeshAgents before starting movement
        foreach (var action in allActions)
        {
            GameObject actor = action.Key;
            if (actor == null)
            {
                continue;
            }

            Character character = actor.GetComponent<Character>();
            float attackRange = character != null ? character.GetAttackRange() : 2.0f;

            NavMeshAgent agent = actor.GetComponent<NavMeshAgent>();
            if (agent != null)
            {
                // For melee weapons (range <= 2), get much closer. For ranged, stay back more.
                float stoppingDistance = attackRange <= 2 ? 0.2f : Mathf.Max(0.5f, attackRange - 1.0f);
                agent.stoppingDistance = stoppingDistance;

                // Configure movement speed based on character's MovementSpeed stat
                if (character != null)
                {
                    // Convert character movement speed to NavMeshAgent speed (HALVED for better gameplay)
                    // Base conversion: MovementSpeed 10 = 1.75 units/sec, scale from there
                    agent.speed = (character.MovementSpeed / 10f) * 1.75f;

                    // Set high acceleration to reach max speed quickly
                    agent.acceleration = agent.speed * 3.0f; // Reach max speed in ~0.33 seconds
                }
                else
                {
                    agent.speed = 1.75f; // Default speed if no character component (halved)
                    agent.acceleration = 5.25f; // Default acceleration (halved)
                }

                // 
                agent.obstacleAvoidanceType = ObstacleAvoidanceType.HighQualityObstacleAvoidance;
                agent.avoidancePriority = UnityEngine.Random.Range(0, 100);

                // Start movement
                GameObject target = action.Value;
                if (target != null)
                {
                    agent.SetDestination(target.transform.position);
                    agent.isStopped = false;

                }
            }
            else
            {
                Debug.LogWarning($"NavMeshAgent not found or disabled on {actor.name}. Cannot move towards target.");
            }
        }

        // Handle pure movement actions (no enemy target)
        foreach (var movement in movementActions)
        {
            GameObject playerGO = movement.Key;
            Vector3 targetPosition = movement.Value;

            NavMeshAgent agent = playerGO.GetComponent<NavMeshAgent>();
            if (agent != null)
            {
                // Configure movement speed for pure movement actions based on character's MovementSpeed stat
                Character character = playerGO.GetComponent<Character>();
                if (character != null)
                {
                    // Convert character movement speed to NavMeshAgent speed (HALVED for better gameplay)
                    // Base conversion: MovementSpeed 10 = 1.75 units/sec, scale from there
                    agent.speed = (character.MovementSpeed / 10f) * 1.75f;

                    // Set high acceleration to reach max speed quickly
                    agent.acceleration = agent.speed * 3.0f; // Reach max speed in ~0.33 seconds
                    Debug.Log($"🚀 MOVEMENT DEBUG - {character.CharacterName}: MovementSpeed={character.MovementSpeed}, AgentSpeed={agent.speed:F1}, Acceleration={agent.acceleration:F1}, TimeScale={Time.timeScale}");
                }
                else
                {
                    agent.speed = 1.75f; // Default speed if no character component (halved)
                    agent.acceleration = 5.25f; // Default acceleration (halved)
                    Debug.Log($"🚀 MOVEMENT DEBUG - {playerGO.name}: DEFAULT AgentSpeed={agent.speed:F1}, Acceleration={agent.acceleration:F1}, TimeScale={Time.timeScale}");
                }

                agent.SetDestination(targetPosition);
                agent.isStopped = false;

            }
        }

        // handle movement duration based on mode
        // 
        if (allActions.Count > 0 || movementActions.Count > 0)
        {
            yield return StartCoroutine(MovementPhaseWithTargetTracking(allActions, movementActions, 1.0f));
        }
        // else
        // {
        //     // If there are only attacks (no movement), still wait for 1 second
        //     yield return new WaitForSeconds(1.0f);
        // }

        if (!isContinuousRunActive)
        {
            // 
            // 

            // Check for completed movement actions before showing lines
            CheckAndResetCompletedMovements();

            // Enable input and show lines for actions during pause - allow re-picking actions
            playerDecisionController.UpdateVisualStates(); // Update colors
            playerDecisionController.SetEnabled(true); // Allow action changes
            playerDecisionController.ShowActiveActionLines();

            PauseGame();
            waitingForAdvanceInput = true;
            yield return new WaitUntil(() => !waitingForAdvanceInput);

            // Disable input when advancing
            playerDecisionController.SetEnabled(false);
            ResumeGame();
            yield return new WaitForSeconds(1.0f);
        }

        foreach (var action in allActions)
        {
            GameObject actor = action.Key;
            GameObject target = action.Value;

            if (actor == null || target == null) continue;
            Character character = actor.GetComponent<Character>();
            float attackRange = character != null ? character.GetAttackRange() : 2.0f;

            float distance = Vector3.Distance(actor.transform.position, target.transform.position);
            if (distance <= attackRange)
            {


                // Execute the character's attack action
                character.ExecuteAction();
            }
            else
            {

            }
        }

        // Check movement completion and reset action if reached (movement actions are one-time)
        foreach (var movement in movementActions)
        {
            GameObject actor = movement.Key;
            Vector3 targetPosition = movement.Value;

            if (actor == null) continue;

            Character character = actor.GetComponent<Character>();
            if (character != null)
            {
                // Use horizontal distance only, ignore Y differences
                Vector3 actorPos = actor.transform.position;
                Vector2 actorPos2D = new Vector2(actorPos.x, actorPos.z);
                Vector2 targetPos2D = new Vector2(targetPosition.x, targetPosition.z);
                float horizontalDistance = Vector2.Distance(actorPos2D, targetPos2D);

                if (horizontalDistance <= 1.2f) // Movement completion threshold
                {

                    character.actionData.Reset();
                    character.SetVisualState(ActionDecisionState.NoAction);
                }
            }
        }

        isActionExecutionPhaseActive = false;

        BattleUIManager.Instance.SetButtonsInteractable(true);
    }

    private IEnumerator MovementPhaseWithTargetTracking(Dictionary<GameObject, GameObject> allActions, Dictionary<GameObject, Vector3> movementActions, float movementDuration)
    {
        float elapsedTime = 0f;

        // Store witch agents are still moving (not in attack range)
        Dictionary<NavMeshAgent, GameObject> activeMovements = new Dictionary<NavMeshAgent, GameObject>();
        Dictionary<NavMeshAgent, float> agentAttackRanges = new Dictionary<NavMeshAgent, float>();

        // Initialize active movements for attack actions
        foreach (var action in allActions)
        {
            GameObject actor = action.Key;
            GameObject target = action.Value;

            if (actor == null || target == null) continue;

            NavMeshAgent agent = actor.GetComponent<NavMeshAgent>();
            if (agent != null && agent.enabled)
            {
                // Get the character's attack range
                Character character = actor.GetComponent<Character>();
                float attackRange = character != null ? character.GetAttackRange() : 2.0f;

                // Configure movement speed based on character's MovementSpeed stat
                if (character != null)
                {
                    // Convert character movement speed to NavMeshAgent speed (HALVED for better gameplay)
                    // Base conversion: MovementSpeed 10 = 1.75 units/sec, scale from there
                    agent.speed = (character.MovementSpeed / 10f) * 1.75f;

                    // Set high acceleration to reach max speed quickly
                    agent.acceleration = agent.speed * 3.0f; // Reach max speed in ~0.33 seconds
                }
                else
                {
                    agent.speed = 1.75f; // Default speed if no character component (halved)
                    agent.acceleration = 5.25f; // Default acceleration (halved)
                }

                // Configure agent for proper pathfinding around obstacles
                agent.obstacleAvoidanceType = ObstacleAvoidanceType.HighQualityObstacleAvoidance;
                agent.avoidancePriority = UnityEngine.Random.Range(0, 100); // Random priority to avoid clustering

                activeMovements[agent] = target;
                agentAttackRanges[agent] = attackRange;
            }
        }

        // Initialize active movements for pure movement actions
        foreach (var movement in movementActions)
        {
            GameObject actor = movement.Key;
            Vector3 targetPosition = movement.Value;

            if (actor == null) continue;

            NavMeshAgent agent = actor.GetComponent<NavMeshAgent>();
            if (agent != null && agent.enabled)
            {
                // For movement actions, use a small stopping distance to get closer
                float arrivalRange = 1.2f;

                // Configure movement speed based on character's MovementSpeed stat
                Character character = actor.GetComponent<Character>();
                if (character != null)
                {
                    // Convert character movement speed to NavMeshAgent speed (HALVED for better gameplay)
                    // Base conversion: MovementSpeed 10 = 1.75 units/sec, scale from there
                    agent.speed = (character.MovementSpeed / 10f) * 1.75f;

                    // Set high acceleration to reach max speed quickly
                    agent.acceleration = agent.speed * 3.0f; // Reach max speed in ~0.33 seconds
                }
                else
                {
                    agent.speed = 1.75f; // Default speed if no character component (halved)
                    agent.acceleration = 5.25f; // Default acceleration (halved)
                }

                // Configure agent for proper pathfinding around obstacles
                agent.obstacleAvoidanceType = ObstacleAvoidanceType.HighQualityObstacleAvoidance;
                agent.avoidancePriority = UnityEngine.Random.Range(0, 100);
                agent.stoppingDistance = 0.1f; // Get very close to the target

                // Create a dummy target GameObject at the position for consistency with the tracking system
                GameObject dummyTarget = new GameObject("MovementTarget");
                dummyTarget.transform.position = targetPosition;

                activeMovements[agent] = dummyTarget;
                agentAttackRanges[agent] = arrivalRange;
            }
        }

        Debug.Log($"🏃 MOVEMENT PHASE START - TimeScale={Time.timeScale}, ActiveMovements={activeMovements.Count}, Duration={movementDuration}");

        while (elapsedTime < movementDuration && Time.timeScale > 0 && activeMovements.Count > 0)
        {
            var agentsToRemove = new List<NavMeshAgent>();

            foreach (var movement in activeMovements)
            {
                NavMeshAgent agent = movement.Key;
                GameObject target = movement.Value;
                float attackRange = agentAttackRanges[agent];

                if (agent == null || target == null || agent.gameObject == null)
                {
                    agentsToRemove.Add(agent);
                    continue;
                }

                float distanceToTarget = Vector3.Distance(agent.transform.position, target.transform.position);

                // Debug velocity and speed every 10 frames to avoid spam
                if (Time.frameCount % 10 == 0)
                {
                    Character character = agent.GetComponent<Character>();
                    string charName = character != null ? character.CharacterName : agent.gameObject.name;
                    Debug.Log($"🏃‍♂️ VELOCITY - {charName}: Speed={agent.speed:F1}, Velocity={agent.velocity.magnitude:F2}, Distance={distanceToTarget:F1}");
                }

                if (distanceToTarget <= attackRange)
                {
                    agent.isStopped = true;
                    agent.velocity = Vector3.zero;
                    agentsToRemove.Add(agent);


                    // If this is a movement target (dummy), check if we should reset the action
                    if (target.name == "MovementTarget")
                    {
                        Character character = agent.GetComponent<Character>();
                        if (character != null && character.actionData.targetPosition != Vector3.zero)
                        {

                            character.actionData.Reset();
                            character.SetVisualState(ActionDecisionState.NoAction);
                        }
                    }

                }
                else if (!agent.isStopped)
                {
                    // For movement targets, go directly to the position
                    if (target.name == "MovementTarget")
                    {
                        agent.SetDestination(target.transform.position);

                        // Check if agent has reached destination or is very close but stopped moving
                        if (agent.pathStatus == NavMeshPathStatus.PathComplete &&
                            (!agent.hasPath || agent.remainingDistance < 0.1f))
                        {
                            Character character = agent.GetComponent<Character>();
                            if (character != null)
                            {
                                Vector3 actorPos = agent.transform.position;
                                Vector3 targetPos = character.actionData.targetPosition;
                                Vector2 actorPos2D = new Vector2(actorPos.x, actorPos.z);
                                Vector2 targetPos2D = new Vector2(targetPos.x, targetPos.z);
                                float horizontalDistance = Vector2.Distance(actorPos2D, targetPos2D);

                                if (horizontalDistance <= 1.2f)
                                {
                                    agent.isStopped = true;
                                    agentsToRemove.Add(agent);

                                    character.actionData.Reset();
                                    character.SetVisualState(ActionDecisionState.NoAction);
                                }
                            }
                        }
                    }
                    else
                    {
                        // Update destination to track moving target, but stop just outside attack range
                        Vector3 directionToTarget = (target.transform.position - agent.transform.position).normalized;
                        Vector3 stoppingPosition = target.transform.position - directionToTarget * (attackRange * 0.9f);
                        agent.SetDestination(stoppingPosition);
                    }

                    // Check if agent is stuck or can't reach destination
                    if (agent.pathStatus == NavMeshPathStatus.PathInvalid)
                    {
                        Debug.LogWarning($"{agent.gameObject.name} cannot find path to {target.name}");
                        agent.SetDestination(target.transform.position);
                    }
                }
            }

            foreach (var agent in agentsToRemove)
            {
                activeMovements.Remove(agent);
                agentAttackRanges.Remove(agent);
            }

            yield return null; // wait one frame
            elapsedTime += Time.deltaTime;
        }
        // Stop any remaining moving agents and clean up dummy targets
        foreach (var movement in activeMovements)
        {
            if (movement.Key != null && movement.Key.enabled)
            {
                movement.Key.isStopped = true;
                movement.Key.velocity = Vector3.zero;
            }

            // Clean up dummy movement targets
            if (movement.Value != null && movement.Value.name == "MovementTarget")
            {
                Destroy(movement.Value);
            }
        }


    }



    public void AdvanceAction()
    {


        // Hide action lines when advancing
        if (playerDecisionController != null)
        {
            playerDecisionController.HideActiveActionLines();
        }

        if (waitingForAdvanceInput)
        {

            waitingForAdvanceInput = false;
        }
        else if (Time.timeScale == 0 && !isActionExecutionPhaseActive)
        {

            ResumeGame();
        }
        else
        {


        }
    }

    public void PauseGame()
    {
        Time.timeScale = 0f; // Pause the game

        BattleUIManager.Instance.SetButtonsInteractable(true);
    }

    public void ResumeGame()
    {
        Time.timeScale = 1f; // Resume the game

    }

    private void EnemiesDecideAction()
    {


        enemySelectedTargets.Clear();

        foreach (var enemy in enemyCharacters)
        {
            if (enemy == null)
            {
                Debug.LogWarning("Found null enemy in enemyCharacters list");
                continue;
            }
            if (playerCharacters.Count == 0)
            {
                Debug.LogWarning("No player characters available for enemies to target");
                continue;
            }
            // Logic for enemy action decision


            GameObject closestPlayer = null;
            float minDistance = float.MaxValue;
            List<GameObject> alivePlayers = playerCharacters.Where(player => !player.GetComponent<Character>().IsDead).ToList();
            foreach (var player in alivePlayers)
            {
                if (player == null) continue; // Safety check
                float distance = Vector3.Distance(enemy.transform.position, player.transform.position);
                if (distance < minDistance)
                {
                    minDistance = distance;
                    closestPlayer = player;
                }
            }
            if (closestPlayer != null)
            {


                // Set the enemy's action data to attack the target
                Character enemyCharacter = enemy.GetComponent<Character>();
                if (enemyCharacter != null)
                {
                    enemyCharacter.actionData.SetAttackTarget(closestPlayer);

                }

                enemySelectedTargets[enemy] = closestPlayer; // Assign the closest player as the target
            }
            else
            {
                Debug.LogWarning($"{enemy.name} could not find a valid target");
            }

            enemy.GetComponent<Character>().SetVisualState(ActionDecisionState.EnemyAction);
        }


    }

    private void CheckAndResetCompletedMovements()
    {
        foreach (GameObject playerGO in playerCharacters)
        {
            Character character = playerGO.GetComponent<Character>();
            if (character != null && character.actionData.targetPosition != Vector3.zero && character.actionData.targetEnemy == null)
            {
                // This is a movement action, check if completed using horizontal distance only
                Vector3 playerPos = playerGO.transform.position;
                Vector3 targetPos = character.actionData.targetPosition;

                // Use only X and Z coordinates (ignore Y differences)
                Vector2 playerPos2D = new Vector2(playerPos.x, playerPos.z);
                Vector2 targetPos2D = new Vector2(targetPos.x, targetPos.z);
                float horizontalDistance = Vector2.Distance(playerPos2D, targetPos2D);



                if (horizontalDistance <= 1.2f) // Threshold for "close enough"
                {

                    character.actionData.Reset();
                    character.SetVisualState(ActionDecisionState.NoAction);
                }
            }
        }
    }


}
