using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.InputSystem;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// CashSystemManager - Main controller for Cash System game mode.
/// Handles team spawning, win conditions, and game flow.
/// </summary>
public class CashSystemManager : MonoBehaviour
{
    [Header("Match Settings")]
    [SerializeField] private float matchDuration = 300f; // 5 minutes
    [SerializeField] private float targetCashToWin = 2000f;
    [SerializeField] private bool endOnThreshold = true;
    
    [Header("Team Spawn Points")]
    [SerializeField] private Transform[] playerTeamSpawnPoints;
    [SerializeField] private Transform[] enemyTeamSpawnPoints;
    
    [Header("Vault References")]
    [SerializeField] private TeamVault playerVault;
    [SerializeField] private TeamVault enemyVault;
    
    [Header("Cashout Stations (Extraction Mode)")]
    [SerializeField] private CashoutStation playerStation;
    [SerializeField] private CashoutStation enemyStation;
    
    [Header("Extraction Mode Settings")]
    [SerializeField] private float killReward = 200f;             // $200 per kill
    [SerializeField] private float teamWipePenaltyPercent = 0.30f; // -30% cash on team wipe
    [SerializeField] private float respawnTime = 10f;              // 10s respawn timer
    [SerializeField] private GameObject vaultSpawnerPrefab;        // Optional prefab for vault spawner
    
    [Header("Character Switching")]
    [SerializeField] private KeyCode switchCharacterKey = KeyCode.Tab;
    [SerializeField] private float switchCooldown = 1f;
    
    [Header("UI")]
    [SerializeField] private GameObject victoryScreen;
    [SerializeField] private GameObject defeatScreen;
    
    [Header("Buzzer Beater")]
    [SerializeField] private float buzzerBeaterWindow = 15f;
    [SerializeField] private float buzzerSlowMotion = 0.6f;
    
    // Runtime state
    private List<GameObject> playerTeamCharacters = new List<GameObject>();
    private List<GameObject> enemyTeamCharacters = new List<GameObject>();
    private int currentControlledIndex = 0;
    private float matchTimer;
    private bool matchEnded = false;
    private float lastSwitchTime = 0f;
    private bool _buzzerActive;
    
    public float MatchTimer => matchTimer;
    public float MatchDuration => matchDuration;
    public bool MatchEnded => matchEnded;
    public GameObject CurrentControlledCharacter => 
        currentControlledIndex < playerTeamCharacters.Count ? playerTeamCharacters[currentControlledIndex] : null;
    
    private static CashSystemManager instance;
    public static CashSystemManager Instance => instance;
    
    private void Awake()
    {
        if (instance != null && instance != this)
        {
            Destroy(gameObject);
            return;
        }
        instance = this;
    }
    
    private void OnEnable()
    {
        GameEvents.OnCashDeposited += OnCashDepositedEvent;
        GameEvents.OnVaultStolen += OnVaultStolenEvent;
        GameEvents.OnKill += OnKillEvent;
        GameEvents.OnCharacterDied += OnCharacterDiedEvent;
    }
    
    private void OnDisable()
    {
        GameEvents.OnCashDeposited -= OnCashDepositedEvent;
        GameEvents.OnVaultStolen -= OnVaultStolenEvent;
        GameEvents.OnKill -= OnKillEvent;
        GameEvents.OnCharacterDied -= OnCharacterDiedEvent;
    }
    
    private void Start()
    {
        // Only activate in Cash System mode
        if (SelectionOptions.Instance == null || !SelectionOptions.Instance.isCashSystemSelected)
        {
            DevLog.Log("[CashSystemManager] Not in Cash System mode, disabling.");
            enabled = false;
            return;
        }
        
        DevLog.Log("[CashSystemManager] Cash System mode active, initializing...");
        
        // Ensure TeamControlManager exists
        if (TeamControlManager.Instance == null)
        {
            GameObject tcmObj = new GameObject("TeamControlManager");
            tcmObj.AddComponent<TeamControlManager>();
            DevLog.Log("[CashSystemManager] Created TeamControlManager");
        }
        
        // Ensure AudioListenerManager exists for sound to work
        if (AudioListenerManager.Instance == null)
        {
            GameObject almObj = new GameObject("AudioListenerManager");
            almObj.AddComponent<AudioListenerManager>();
            DevLog.Log("[CashSystemManager] Created AudioListenerManager");
        }
        
        // Ensure TeamIndicatorManager exists for visual team differentiation
        if (TeamIndicatorManager.Instance == null)
        {
            GameObject timObj = new GameObject("TeamIndicatorManager");
            timObj.AddComponent<TeamIndicatorManager>();
            DevLog.Log("[CashSystemManager] Created TeamIndicatorManager");
        }
        
        // Ensure MinimapMarkerManager exists for minimap team markers
        if (MinimapMarkerManager.Instance == null)
        {
            GameObject mmmObj = new GameObject("MinimapMarkerManager");
            mmmObj.AddComponent<MinimapMarkerManager>();
            DevLog.Log("[CashSystemManager] Created MinimapMarkerManager");
        }
        
        // Find vaults if not assigned
        if (playerVault == null || enemyVault == null)
        {
            TeamVault[] vaults = FindObjectsOfType<TeamVault>();
            foreach (TeamVault vault in vaults)
            {
                if (vault.TeamTag == "Player") playerVault = vault;
                else if (vault.TeamTag == "Enemy") enemyVault = vault;
            }
        }
        
        // Find CashoutStations if not assigned (extraction mode)
        if (playerStation == null || enemyStation == null)
        {
            CashoutStation[] stations = FindObjectsOfType<CashoutStation>();
            foreach (CashoutStation station in stations)
            {
                if (station.TeamTag == "Player") playerStation = station;
                else if (station.TeamTag == "Enemy") enemyStation = station;
            }
        }
        
        // Ensure VaultSpawner exists for extraction mode
        if (FindObjectOfType<VaultSpawner>() == null)
        {
            GameObject spawnerObj = new GameObject("VaultSpawner");
            spawnerObj.AddComponent<VaultSpawner>();
            DevLog.Log("[CashSystemManager] Created VaultSpawner");
        }
        
        matchTimer = matchDuration;
        
        // Initialize UI with vault values
        StartCoroutine(InitializeUIDelayed());
        
        // Ensure UI panels exist (activates inactive instances or auto-creates minimal ones)
        PreMatchIntroUI.EnsureExists();
        MatchResultUI.EnsureExists();
        
        // Show pre-match intro before spawning
        if (PreMatchIntroUI.Instance != null)
        {
            PreMatchIntroUI.Instance.Show();
            DevLog.Log("[CashSystemManager] PreMatchIntroUI.Show() called");
        }
        else
        {
            DevLog.LogWarning("[CashSystemManager] PreMatchIntroUI.Instance is STILL null after EnsureExists!");
        }
        
        if (MatchResultUI.Instance != null)
            DevLog.Log("[CashSystemManager] MatchResultUI ready for end-of-match");
        else
            DevLog.LogWarning("[CashSystemManager] MatchResultUI.Instance is STILL null after EnsureExists!");
        
        StartCoroutine(SpawnTeams());
    }
    
    private IEnumerator InitializeUIDelayed()
    {
        yield return null;
        yield return new WaitForSeconds(0.2f);
        
        // Fire events instead of FindObjectOfType — UI subscribes to these
        GameEvents.FireTimerUpdated(matchTimer);
        if (playerStation != null) GameEvents.FireScoreChanged("Player", playerStation.StoredCash);
        else if (playerVault != null) GameEvents.FireScoreChanged("Player", playerVault.StoredCash);
        if (enemyStation != null) GameEvents.FireScoreChanged("Enemy", enemyStation.StoredCash);
        else if (enemyVault != null) GameEvents.FireScoreChanged("Enemy", enemyVault.StoredCash);
    }
    
    // Throttle timer UI updates to once per displayed second (was 60Hz)
    private int _lastDisplayedSecond = -1;
    
    private void Update()
    {
        if (matchEnded) return;
        
        // Timer tick
        matchTimer -= Time.deltaTime;
        
        // Only fire timer event when the displayed second changes (60Hz → 1Hz)
        int displayedSecond = Mathf.CeilToInt(matchTimer);
        if (displayedSecond != _lastDisplayedSecond)
        {
            _lastDisplayedSecond = displayedSecond;
            GameEvents.FireTimerUpdated(matchTimer);
        }
        
        if (matchTimer <= 0)
        {
            matchTimer = 0;
            EndMatch();
            return;
        }
        
        // Buzzer beater slow-motion
        if (!_buzzerActive && matchTimer <= buzzerBeaterWindow)
        {
            float playerScore = GetTeamTotalCash("Player");
            float enemyScore = GetTeamTotalCash("Enemy");
            float scoreDiff = Mathf.Abs(playerScore - enemyScore);
            if (scoreDiff < 500f) // Close game
            {
                _buzzerActive = true;
                Time.timeScale = buzzerSlowMotion;
                Time.fixedDeltaTime = 0.02f * buzzerSlowMotion;
                GameEvents.FirePopupMessage("BUZZER BEATER!", 2f);
            }
        }
        
        // Threshold win — check both TeamVaults and CashoutStations
        if (endOnThreshold)
        {
            float playerScore = GetTeamTotalCash("Player");
            float enemyScore = GetTeamTotalCash("Enemy");
            
            if (playerScore >= targetCashToWin)
            { EndMatch(true); return; }
            if (enemyScore >= targetCashToWin)
            { EndMatch(false); return; }
        }
        
        // Character switching
        if (Input.GetKeyDown(switchCharacterKey) && Time.time - lastSwitchTime > switchCooldown)
        {
            SwitchControlledCharacter();
            lastSwitchTime = Time.time;
        }
    }
    
    private IEnumerator SpawnTeams()
    {
        yield return new WaitForSeconds(0.5f); // Wait for scene to settle
        
        // Get team data from SelectionOptions
        string[] playerTeam = SelectionOptions.Instance.playerTeam;
        string[] enemyTeam = SelectionOptions.Instance.enemyTeam;
        int captainIndex = SelectionOptions.Instance.captainIndex;
        
        DevLog.Log($"[CashSystemManager] Spawning teams - Captain index: {captainIndex}");
        DevLog.Log($"[CashSystemManager] Player team: {string.Join(", ", playerTeam ?? new string[0])}");
        DevLog.Log($"[CashSystemManager] Enemy team: {string.Join(", ", enemyTeam ?? new string[0])}");
        
        // If teams not set, generate them
        if (playerTeam == null || playerTeam.Length == 0 || string.IsNullOrEmpty(playerTeam[0]))
        {
            DevLog.Log("[CashSystemManager] Generating default teams...");
            GenerateDefaultTeams();
            playerTeam = SelectionOptions.Instance.playerTeam;
            enemyTeam = SelectionOptions.Instance.enemyTeam;
        }
        
        // Get spawn positions from vaults if spawn points not assigned
        Vector3 playerVaultPos = playerVault != null ? playerVault.transform.position : new Vector3(-10f, 0f, 0f);
        Vector3 enemyVaultPos = enemyVault != null ? enemyVault.transform.position : new Vector3(10f, 0f, 0f);
        
        DevLog.Log($"[CashSystemManager] Player vault position: {playerVaultPos}");
        DevLog.Log($"[CashSystemManager] Enemy vault position: {enemyVaultPos}");
        DevLog.Log($"[CashSystemManager] Player spawn points assigned: {playerTeamSpawnPoints != null && playerTeamSpawnPoints.Length > 0}");
        DevLog.Log($"[CashSystemManager] Enemy spawn points assigned: {enemyTeamSpawnPoints != null && enemyTeamSpawnPoints.Length > 0}");
        
        // Spawn player team - use assigned spawn points if available, otherwise vault positions
        for (int i = 0; i < playerTeam.Length; i++)
        {
            if (string.IsNullOrEmpty(playerTeam[i])) continue;
            
            // First try to use assigned spawn points
            Vector3 spawnPos;
            if (playerTeamSpawnPoints != null && i < playerTeamSpawnPoints.Length && playerTeamSpawnPoints[i] != null)
            {
                spawnPos = playerTeamSpawnPoints[i].position;
                DevLog.Log($"[CashSystemManager] Using assigned spawn point for player {i}: {spawnPos}");
            }
            else
            {
                spawnPos = GetSpawnPositionNearVault(playerVaultPos, i, true);
                DevLog.Log($"[CashSystemManager] Using vault-based spawn for player {i}: {spawnPos}");
            }
            
            bool isPlayerControlled = (i == captainIndex);
            
            DevLog.Log($"[CashSystemManager] Spawning player {playerTeam[i]} at {spawnPos}, isPlayerControlled: {isPlayerControlled}");
            
            GameObject character = SpawnCharacter(playerTeam[i], spawnPos, "Player", isPlayerControlled);
            if (character != null)
            {
                playerTeamCharacters.Add(character);
                // CashCarrier and AI components are now added in SpawnCharacter/ConfigureCharacterControllers
                DevLog.Log($"[CashSystemManager] Player {character.name} spawned successfully at {character.transform.position}");
            }
        }
        
        // Spawn enemy team - use assigned spawn points if available, otherwise vault positions
        for (int i = 0; i < enemyTeam.Length; i++)
        {
            if (string.IsNullOrEmpty(enemyTeam[i])) continue;
            
            // First try to use assigned spawn points
            Vector3 spawnPos;
            if (enemyTeamSpawnPoints != null && i < enemyTeamSpawnPoints.Length && enemyTeamSpawnPoints[i] != null)
            {
                spawnPos = enemyTeamSpawnPoints[i].position;
                DevLog.Log($"[CashSystemManager] Using assigned spawn point for enemy {i}: {spawnPos}");
            }
            else
            {
                spawnPos = GetSpawnPositionNearVault(enemyVaultPos, i, false);
                DevLog.Log($"[CashSystemManager] Using vault-based spawn for enemy {i}: {spawnPos}");
            }
            
            DevLog.Log($"[CashSystemManager] Spawning enemy {enemyTeam[i]} at {spawnPos}");
            
            GameObject character = SpawnCharacter(enemyTeam[i], spawnPos, "Enemy", false);
            if (character != null)
            {
                enemyTeamCharacters.Add(character);
                // CashCarrier, CashSystemAI, and EnemyAIController are now added in SpawnCharacter/ConfigureCharacterControllers
                DevLog.Log($"[CashSystemManager] Enemy {character.name} spawned successfully at {character.transform.position}");
            }
        }
        
        // Note: CashSystemAI is now added in ConfigureCharacterControllers, no need to add again
        
        currentControlledIndex = captainIndex;
        
        DevLog.Log($"[CashSystemManager] Teams spawned: {playerTeamCharacters.Count} players, {enemyTeamCharacters.Count} enemies");
        
        // Assign deterministic AI roles: 1 Defender + 2 Collectors per team
        // Must happen AFTER all CashSystemAI components are fully initialized
        yield return null; // Give CashSystemAI.Start() a frame to run
        CashSystemAI.AssignTeamRoles();
        
        // Initialize team HUD with player team characters (HUD is CanvasGroup-hidden, Initialize shows it)
        if (TeamHUDPanel.Instance != null)
            TeamHUDPanel.Instance.Initialize(playerTeamCharacters, currentControlledIndex);
        
        // Wait for intro panel to finish (including its countdown: 3-2-1-FIGHT!)
        // instead of hiding it early. The intro sets IsComplete when done.
        if (PreMatchIntroUI.Instance != null)
        {
            DevLog.Log("[CashSystemManager] Waiting for intro to complete...");
            while (!PreMatchIntroUI.Instance.IsComplete)
                yield return null;
            DevLog.Log("[CashSystemManager] Intro complete, enabling combat");
        }
        
        // Show the Cash System HUD now that intro is done
        CashSystemUI cashUI = FindObjectOfType<CashSystemUI>();
        if (cashUI != null)
            cashUI.ShowHUD();

        // Enable combat — either intro did the countdown, or we do it ourselves
        if (PreMatchIntroUI.Instance != null && PreMatchIntroUI.Instance.IsComplete)
        {
            // Intro already fired countdown ticks; just enable combat now
            GameEvents.FireCombatEnabled(true);
            foreach (var c in playerTeamCharacters)
                if (c != null) EnableCharacterCombat(c);
            foreach (var c in enemyTeamCharacters)
                if (c != null) EnableCharacterCombat(c);
        }
        else
        {
            // No intro panel present — use standalone countdown fallback
            StartCoroutine(MatchCountdown());
        }
    }
    
    private void GenerateDefaultTeams()
    {
        // Use all 6 characters, split between teams
        string[] allCharacters = { "Windham", "Amira", "Bahman", "Ziggy", "Amon", "Imani" };
        
        // Shuffle
        for (int i = allCharacters.Length - 1; i > 0; i--)
        {
            int j = Random.Range(0, i + 1);
            string temp = allCharacters[i];
            allCharacters[i] = allCharacters[j];
            allCharacters[j] = temp;
        }
        
        // Assign to teams
        SelectionOptions.Instance.playerTeam = new string[] { allCharacters[0], allCharacters[1], allCharacters[2] };
        SelectionOptions.Instance.enemyTeam = new string[] { allCharacters[3], allCharacters[4], allCharacters[5] };
        SelectionOptions.Instance.captainIndex = 0;
        
        DevLog.Log($"[CashSystemManager] Generated teams - Player: {string.Join(", ", SelectionOptions.Instance.playerTeam)}, Enemy: {string.Join(", ", SelectionOptions.Instance.enemyTeam)}");
    }
    
    /// <summary>
    /// Get spawn position near a vault - spreads characters in a line
    /// </summary>
    private Vector3 GetSpawnPositionNearVault(Vector3 vaultPosition, int index, bool isPlayerTeam)
    {
        // Offset from vault position (spawn a bit away from vault)
        float spawnDistance = 3f; // Distance from vault center
        float spacing = 2f; // Horizontal spacing between characters
        
        // Center the team spawn with offset from vault
        float xOffset = (index - 1) * spacing; // -2, 0, +2 for 3 characters
        
        // Different direction for player vs enemy
        if (isPlayerTeam)
        {
            // Player spawns "forward" from vault (opposite to enemy)
            return new Vector3(vaultPosition.x + xOffset, vaultPosition.y, vaultPosition.z + spawnDistance);
        }
        else
        {
            // Enemy spawns "forward" from their vault (opposite to player)
            return new Vector3(vaultPosition.x + xOffset, vaultPosition.y, vaultPosition.z - spawnDistance);
        }
    }
    
    private Vector3 GetSpawnPosition(Transform[] spawnPoints, int index)
    {
        if (spawnPoints != null && index < spawnPoints.Length && spawnPoints[index] != null)
        {
            return spawnPoints[index].position;
        }
        
        // Default positions
        float xOffset = 3f * index;
        return new Vector3(xOffset, 0f, (spawnPoints == playerTeamSpawnPoints) ? 10f : -10f);
    }
    
    private GameObject SpawnCharacter(string characterName, Vector3 position, string teamTag, bool isPlayerControlled)
    {
        // IMPORTANT: Always load the PLAYER prefab - NOT the Enemy variant!
        // The old code loaded "Enemy" prefabs which caused confusion
        // Now we use ONE prefab per character and configure it based on team
        GameObject prefab = CharacterPrefabManager.Instance.GetCharacterPrefab(characterName, isAI: false);
        
        if (prefab == null)
        {
            Debug.LogError($"[CashSystemManager] Failed to load prefab for {characterName}");
            return null;
        }
        
        DevLog.Log($"[CashSystemManager] Loading prefab: {prefab.name} for {characterName}");
        
        GameObject character = Instantiate(prefab, position, Quaternion.identity);
    
    // Snap to NavMesh surface so characters don't spawn underground with new environments
    UnityEngine.AI.NavMeshHit navHit;
    if (UnityEngine.AI.NavMesh.SamplePosition(position, out navHit, 10f, UnityEngine.AI.NavMesh.AllAreas))
    {
        character.transform.position = navHit.position;
        
        // Warp NavMeshAgent to the snapped position so it doesn't fight physics
        var agent = character.GetComponent<UnityEngine.AI.NavMeshAgent>();
        if (agent != null)
        {
            agent.enabled = false;
            character.transform.position = navHit.position;
            agent.enabled = true;
            agent.Warp(navHit.position);
        }
        
        // For AI characters: make Rigidbody kinematic so NavMeshAgent controls position
        // For player-controlled: leave Rigidbody non-kinematic (PlayerMovementBehaviour uses MovePosition)
        if (!isPlayerControlled)
        {
            var rb = character.GetComponent<Rigidbody>();
            if (rb != null && agent != null)
            {
                rb.isKinematic = true;
            }
        }
        else
        {
            // Player-controlled: DISABLE NavMeshAgent entirely after snapping.
            // PlayerMovementBehaviour uses Rigidbody.MovePosition — an enabled NavMeshAgent
            // creates internal velocity corrections that fight the Rigidbody and cause drag.
            var agent2 = character.GetComponent<UnityEngine.AI.NavMeshAgent>();
            if (agent2 != null)
            {
                agent2.enabled = false;
            }
        }
        
        DevLog.Log($"[CashSystemManager] Snapped {characterName} to NavMesh at Y={navHit.position.y} (was Y={position.y})");
    }
    else
    {
        DevLog.LogWarning($"[CashSystemManager] No NavMesh found near {position} for {characterName} — character may be underground!");
    }
        
        // Add TeamMember component if not present
        TeamMember teamMember = character.GetComponent<TeamMember>();
        if (teamMember == null)
        {
            teamMember = character.AddComponent<TeamMember>();
        }
        
        // Set team based on tag
        bool isPlayerTeam = (teamTag == "Player");
        teamMember.CurrentTeam = isPlayerTeam ? TeamMember.Team.PlayerTeam : TeamMember.Team.EnemyTeam;
        
        // Set proper tag (TeamMember.UpdateLayerAndTag will handle this but we set it here too)
        character.tag = teamTag;
        
        // Use the new ControlType system - this handles ALL component configuration!
        TeamMember.ControlType controlType;
        if (isPlayerControlled)
        {
            controlType = TeamMember.ControlType.HumanControlled;
        }
        else if (isPlayerTeam)
        {
            controlType = TeamMember.ControlType.PlayerAI;
        }
        else
        {
            controlType = TeamMember.ControlType.EnemyAI;
        }
        teamMember.SetControlType(controlType);
        
        // CRITICAL: For player-controlled characters, bind input action callbacks
        // This is what Practice mode does in SelectionOptions.SetUpPlayerInputAI
        if (isPlayerControlled)
        {
            BindPlayerInputActions(character);
        }
        
        // Add CashCarrier for carrying cash
        if (character.GetComponent<CashCarrier>() == null)
        {
            character.AddComponent<CashCarrier>();
        }
        
        // Register with TeamControlManager for switching
        if (TeamControlManager.Instance != null && isPlayerTeam)
        {
            TeamControlManager.Instance.RegisterPlayerTeamCharacter(character, isPlayerControlled);
        }
        
        // Register with CameraManager AND directly set target if player-controlled
        if (CameraManager.Instance != null)
        {
            CameraManager.Instance.RegisterTeamMember(teamMember);
            
            // DIRECTLY set camera target for the captain
            if (isPlayerControlled)
            {
                CameraManager.Instance.SetTarget(teamMember);
                DevLog.Log($"[CashSystemManager] Set CameraManager target to captain: {character.name}");
            }
        }
        
        // Disable attack until countdown finishes (combat control is independent of ControlType)
        DisableCharacterCombat(character);
        
        // Configure AI controller scripts (CashSystemAI, TeamAIController, etc.)
        if (!isPlayerControlled)
        {
            ConfigureCharacterControllers(character, isPlayerTeam, isPlayerControlled);
        }
        
        DevLog.Log($"[CashSystemManager] Spawned {characterName} as {controlType}, Team: {(isPlayerTeam ? "PLAYER" : "ENEMY")}");
        
        return character;
    }
    
    /// <summary>
    /// Configure the appropriate controller scripts based on team and control mode
    /// </summary>
    private void ConfigureCharacterControllers(GameObject character, bool isPlayerTeam, bool isPlayerControlled)
    {
        // Get existing components
        PlayerScript playerScript = character.GetComponent<PlayerScript>();
        CharacterAIController aiController = character.GetComponent<CharacterAIController>();
        
        if (isPlayerControlled)
        {
            // PLAYER CONTROLLED: Enable player input scripts, disable AI scripts
            if (playerScript != null) playerScript.enabled = true;
            if (aiController != null) aiController.enabled = false;
            
            // Enable new modular input handler if present
            CharacterInputHandler inputHandler = character.GetComponent<CharacterInputHandler>();
            if (inputHandler != null) inputHandler.enabled = true;
            
            // Disable CharacterAIController for player-controlled
            if (aiController != null) aiController.enabled = false;
            
            // Don't add AI controllers to player-controlled character
        }
        else if (isPlayerTeam)
        {
            // PLAYER TEAM AI: Enable navigation, use TeamAIController + CharacterAIController
            if (playerScript != null) playerScript.enabled = false;
            
            // Disable CharacterInputHandler on AI characters
            CharacterInputHandler inputHandler = character.GetComponent<CharacterInputHandler>();
            if (inputHandler != null) inputHandler.enabled = false;
            
            // Enable CharacterAIController if present, or add it
            if (aiController == null)
            {
                aiController = character.AddComponent<CharacterAIController>();
            }
            aiController.enabled = true;
            
            // CRITICAL: Disable PlayerInput on AI characters to prevent duplicate input
            PlayerInput playerInput = character.GetComponent<PlayerInput>();
            if (playerInput != null)
            {
                playerInput.enabled = false;
                DevLog.Log($"[CashSystemManager] Disabled PlayerInput on AI teammate {character.name}");
            }
            
            // Disable AudioListener on AI characters (only player should have one)
            AudioListener audioListener = character.GetComponent<AudioListener>();
            if (audioListener != null)
            {
                audioListener.enabled = false;
            }
            
            // CRITICAL: Disable ALL embedded cameras on AI characters
            // This prevents multiple cameras from being active in the scene
            Camera[] cameras = character.GetComponentsInChildren<Camera>(true);
            foreach (Camera cam in cameras)
            {
                cam.enabled = false;
                DevLog.Log($"[CashSystemManager] Disabled embedded camera {cam.name} on AI teammate {character.name}");
            }
            
            // Also disable any Cinemachine cameras on AI characters
            Cinemachine.CinemachineBrain[] brains = character.GetComponentsInChildren<Cinemachine.CinemachineBrain>(true);
            foreach (var brain in brains)
            {
                brain.enabled = false;
            }
            
            // Add TeamAIController if not present
            TeamAIController teamAI = character.GetComponent<TeamAIController>();
            if (teamAI == null)
            {
                teamAI = character.AddComponent<TeamAIController>();
            }
            teamAI.enabled = true;
            
            // Add CashSystemAI for cash-related decisions
            CashSystemAI cashAI = character.GetComponent<CashSystemAI>();
            if (cashAI == null)
            {
                cashAI = character.AddComponent<CashSystemAI>();
            }
            cashAI.enabled = true;
            
            // Keep NavMeshAgent for movement
            UnityEngine.AI.NavMeshAgent navAgent = character.GetComponent<UnityEngine.AI.NavMeshAgent>();
            if (navAgent != null) navAgent.enabled = true;
            
            // Disable CharacterMovement - AI uses NavMeshAgent, not joystick-based movement
            CharacterMovement charMovement = character.GetComponent<CharacterMovement>();
            if (charMovement != null) charMovement.enabled = false;
            
            DevLog.Log($"[CashSystemManager] Configured {character.name} as PLAYER TEAM AI");
        }
        else
        {
            // ENEMY TEAM AI: Use EnemyAIController + CharacterAIController
            if (playerScript != null) playerScript.enabled = false;
            
            // Disable CharacterInputHandler on AI characters
            CharacterInputHandler inputHandler = character.GetComponent<CharacterInputHandler>();
            if (inputHandler != null) inputHandler.enabled = false;
            
            // Enable CharacterAIController if present, or add it
            if (aiController == null)
            {
                aiController = character.AddComponent<CharacterAIController>();
            }
            aiController.enabled = true;
            
            // CRITICAL: Disable PlayerInput on AI characters to prevent duplicate input
            PlayerInput playerInput = character.GetComponent<PlayerInput>();
            if (playerInput != null)
            {
                playerInput.enabled = false;
                DevLog.Log($"[CashSystemManager] Disabled PlayerInput on enemy AI {character.name}");
            }
            
            // Disable AudioListener on AI characters (only player should have one)
            AudioListener audioListener = character.GetComponent<AudioListener>();
            if (audioListener != null)
            {
                audioListener.enabled = false;
            }
            
            // CRITICAL: Disable ALL embedded cameras on AI characters
            // This prevents multiple cameras from being active in the scene
            Camera[] cameras = character.GetComponentsInChildren<Camera>(true);
            foreach (Camera cam in cameras)
            {
                cam.enabled = false;
                DevLog.Log($"[CashSystemManager] Disabled embedded camera {cam.name} on enemy AI {character.name}");
            }
            
            // Also disable any Cinemachine cameras on AI characters
            Cinemachine.CinemachineBrain[] brains = character.GetComponentsInChildren<Cinemachine.CinemachineBrain>(true);
            foreach (var brain in brains)
            {
                brain.enabled = false;
            }
            
            // Add EnemyAIController if not present
            EnemyAIController enemyAI = character.GetComponent<EnemyAIController>();
            if (enemyAI == null)
            {
                enemyAI = character.AddComponent<EnemyAIController>();
            }
            enemyAI.enabled = true;
            
            // Add CashSystemAI for cash-related decisions
            CashSystemAI cashAI = character.GetComponent<CashSystemAI>();
            if (cashAI == null)
            {
                cashAI = character.AddComponent<CashSystemAI>();
            }
            cashAI.enabled = true;
            
            // Keep NavMeshAgent for movement
            UnityEngine.AI.NavMeshAgent navAgent = character.GetComponent<UnityEngine.AI.NavMeshAgent>();
            if (navAgent != null) navAgent.enabled = true;
            
            // Disable CharacterMovement - AI uses NavMeshAgent, not joystick-based movement
            CharacterMovement charMovement = character.GetComponent<CharacterMovement>();
            if (charMovement != null) charMovement.enabled = false;
            
            DevLog.Log($"[CashSystemManager] Configured {character.name} as ENEMY TEAM AI");
        }
    }
    
    /// <summary>
    /// Set up player control on the captain character
    /// </summary>
    private void SetupPlayerControl(GameObject character)
    {
        DevLog.Log($"[CashSystemManager] Setting up player control for {character.name}");
        
        // Find head transform for camera tracking (like Practice mode)
        Transform targetTransform = FindCharacterHead(character);
        DevLog.Log($"[CashSystemManager] Camera target: {targetTransform?.name ?? "character root"}");
        
        // Set up camera to follow this character via CameraManager (single authority)
        if (CameraManager.Instance != null)
        {
            TeamMember teamMember = character.GetComponent<TeamMember>();
            if (teamMember != null)
            {
                CameraManager.Instance.SetTarget(teamMember);
            }
            else
            {
                CameraManager.Instance.SetTarget(character);
            }
            DevLog.Log($"[CashSystemManager] Camera target set via CameraManager for {character.name}");
        }
        else
        {
            // Fallback: set Cinemachine targets directly with correct Follow/LookAt separation
            Transform followTarget = character.transform; // Root = orbit center
            Transform lookAtTarget = FindCharacterHead(character); // Head = aim point
            
            Cinemachine.CinemachineFreeLook[] freeLookCameras = FindObjectsOfType<Cinemachine.CinemachineFreeLook>();
            foreach (var freeLookCam in freeLookCameras)
            {
                if (freeLookCam.gameObject.activeInHierarchy)
                {
                    freeLookCam.Follow = followTarget;
                    freeLookCam.LookAt = lookAtTarget;
                }
            }
            DevLog.Log($"[CashSystemManager] Camera targets set directly (fallback) for {character.name}");
        }
        
        // Enable player input components
        PlayerScript playerScript = character.GetComponent<PlayerScript>();
        if (playerScript != null)
        {
            playerScript.enabled = true;
            // NOTE: attack is left false here - EnableCharacterCombat will set it to true after countdown
            DevLog.Log("[CashSystemManager] Enabled PlayerScript (attack will be enabled after countdown)");
        }
        
        // Enable and configure PlayerInput component (critical for receiving input!)
        UnityEngine.InputSystem.PlayerInput playerInput = character.GetComponent<UnityEngine.InputSystem.PlayerInput>();
        if (playerInput != null)
        {
            playerInput.enabled = true;
            
            // Switch to Player Controls action map
            try
            {
                playerInput.SwitchCurrentActionMap("Player Controls");
                DevLog.Log("[CashSystemManager] Switched to Player Controls action map");
            }
            catch (System.Exception e)
            {
                DevLog.LogWarning($"[CashSystemManager] Could not switch action map: {e.Message}");
            }
            
            DevLog.Log($"[CashSystemManager] PlayerInput enabled, current map: {playerInput.currentActionMap?.name ?? "null"}");
        }
        else
        {
            DevLog.LogWarning("[CashSystemManager] No PlayerInput component found on player character!");
        }
        
        // Disable AI components if present
        CharacterAIController aiController = character.GetComponent<CharacterAIController>();
        if (aiController != null)
        {
            aiController.enabled = false;
            DevLog.Log("[CashSystemManager] Disabled CharacterAIController");
        }
        
        // Disable any AI brain
        UnityEngine.AI.NavMeshAgent navMeshAgent = character.GetComponent<UnityEngine.AI.NavMeshAgent>();
        if (navMeshAgent != null && navMeshAgent.enabled)
        {
            // NavMeshAgent should stay enabled for movement, but we'll let PlayerScript control it
            DevLog.Log("[CashSystemManager] NavMeshAgent present");
        }
        
        // Disable CashSystemAI if added
        CashSystemAI cashAI = character.GetComponent<CashSystemAI>();
        if (cashAI != null)
        {
            Destroy(cashAI);
            DevLog.Log("[CashSystemManager] Removed CashSystemAI from player");
        }
    }
    
    /// <summary>
    /// Bind input action callbacks to PlayerScript methods.
    /// This mirrors what Practice mode does in SelectionOptions.SetUpPlayerInputAI.
    /// Without this explicit binding, the PlayerInput component won't route actions to PlayerScript.
    /// </summary>
    private void BindPlayerInputActions(GameObject character)
    {
        PlayerInput playerInput = character.GetComponent<PlayerInput>();
        PlayerScript playerScript = character.GetComponent<PlayerScript>();
        
        if (playerInput == null || playerScript == null)
        {
            DevLog.LogWarning($"[CashSystemManager] Cannot bind input actions - PlayerInput: {playerInput != null}, PlayerScript: {playerScript != null}");
            return;
        }
        
        // Ensure PlayerInput is enabled with the right action map
        playerInput.enabled = true;
        try 
        { 
            playerInput.SwitchCurrentActionMap("Player Controls"); 
        } 
        catch (System.Exception e) 
        { 
            DevLog.LogWarning($"[CashSystemManager] Could not switch action map: {e.Message}"); 
        }
        
        var actionMap = playerInput.currentActionMap;
        if (actionMap == null)
        {
            Debug.LogError("[CashSystemManager] No current action map found!");
            return;
        }
        
        DevLog.Log($"[CashSystemManager] Binding input actions on action map: {actionMap.name}");
        
        // CRITICAL: Bind the Move action - this is what Practice mode does!
        TryBindActionPerformed(actionMap, "Move", playerScript.OnMove);  // performed
        TryBindActionCanceled(actionMap, "Move", playerScript.OnMove);   // canceled
        
        // Bind attack actions
        TryBindActionPerformed(actionMap, "Jab", playerScript.OnJab);
        TryBindActionPerformed(actionMap, "Right", playerScript.OnRight);
        TryBindActionPerformed(actionMap, "LeftHook", playerScript.OnLeftHook);
        TryBindActionPerformed(actionMap, "RightHook", playerScript.OnRightHook);
        TryBindActionPerformed(actionMap, "LeftElbow", playerScript.OnLeftElbow);
        TryBindActionPerformed(actionMap, "RightElbow", playerScript.OnRightElbow);
        TryBindActionPerformed(actionMap, "RightBody", playerScript.OnRightBody);
        TryBindActionPerformed(actionMap, "PowerPunchLeft", playerScript.OnPowerPunchLeft);
        TryBindActionPerformed(actionMap, "SupermanPunch", playerScript.OnSupermanPunch);
        
        // Kick actions
        TryBindActionPerformed(actionMap, "LegKickRight", playerScript.OnLegKickRight);
        TryBindActionPerformed(actionMap, "BodyKickRight", playerScript.OnBodyKickRight);
        TryBindActionPerformed(actionMap, "KneeRight", playerScript.OnKneeRight);
        TryBindActionPerformed(actionMap, "BackSideKick", playerScript.OnBackSideKick);
        TryBindActionPerformed(actionMap, "FrontKickRight", playerScript.OnFrontKickRight);
        TryBindActionPerformed(actionMap, "LegPowerKickRight", playerScript.OnLegPowerKickRight);
        
        // Dodge actions
        TryBindActionPerformed(actionMap, "JumpBack", playerScript.OnJumpBack);
        TryBindActionPerformed(actionMap, "JumpLeft", playerScript.OnJumpLeft);
        TryBindActionPerformed(actionMap, "JumpRight", playerScript.OnJumpRight);
        
        // Block actions
        TryBindActionPerformed(actionMap, "BlockStepBack", playerScript.OnBlockStepBack);
        TryBindActionPerformed(actionMap, "BlockBodyLeft", playerScript.OnBlockBodyLeft);
        TryBindActionPerformed(actionMap, "BlockLeg", playerScript.OnBlockLeg);
        
        // Special/Vicious attacks
        TryBindActionPerformed(actionMap, "Chokeslam", playerScript.OnChokeslam);
        TryBindActionPerformed(actionMap, "Suplex", playerScript.OnSuplex);
        TryBindActionPerformed(actionMap, "GiantSwing", playerScript.OnGiantSwing);
        TryBindActionPerformed(actionMap, "DiamondCrusher", playerScript.OnDiamondCrusher);
        TryBindActionPerformed(actionMap, "SumoSlap", playerScript.OnSumoSlap);
        TryBindActionPerformed(actionMap, "JavelinTackle", playerScript.OnJavelinTackle);
        TryBindActionPerformed(actionMap, "RKO", playerScript.OnRKO);
        TryBindActionPerformed(actionMap, "Spear", playerScript.OnSpear);
        TryBindActionPerformed(actionMap, "RockBottom", playerScript.OnRockBottom);
        TryBindActionPerformed(actionMap, "F5", playerScript.OnF5);
        
        DevLog.Log($"[CashSystemManager] Input actions bound successfully for {character.name}");
    }
    
    /// <summary>
    /// Helper to safely bind an action's performed callback
    /// </summary>
    private void TryBindActionPerformed(InputActionMap actionMap, string actionName, System.Action<InputAction.CallbackContext> callback)
    {
        InputAction action = actionMap.FindAction(actionName);
        if (action != null)
        {
            action.performed += callback;
        }
    }
    
    /// <summary>
    /// Helper to safely bind an action's canceled callback
    /// </summary>
    private void TryBindActionCanceled(InputActionMap actionMap, string actionName, System.Action<InputAction.CallbackContext> callback)
    {
        InputAction action = actionMap.FindAction(actionName);
        if (action != null)
        {
            action.canceled += callback;
        }
    }
    
    /// <summary>
    /// Helper to safely bind an action (both performed and started)
    /// </summary>
    private void TryBindAction(InputActionMap actionMap, string actionName, System.Action<InputAction.CallbackContext> startedCallback, System.Action<InputAction.CallbackContext> performedCallback)
    {
        InputAction action = actionMap.FindAction(actionName);
        if (action != null)
        {
            if (startedCallback != null) action.started += startedCallback;
            if (performedCallback != null) action.performed += performedCallback;
        }
    }
    
    /// <summary>
    /// Find the character's head transform for camera targeting (matches Practice mode)
    /// </summary>
    private Transform FindCharacterHead(GameObject character)
    {
        Transform headTransform = null;
        
        try
        {
            // Common head bone names in character rigs
            string[] headNames = { "Head", "head", "Bip001 Head", "mixamorig:Head", "Bip01 Head" };
            
            foreach (string headName in headNames)
            {
                headTransform = character.transform.Find(headName);
                if (headTransform != null) break;
                
                // Also search recursively
                headTransform = FindChildRecursive(character.transform, headName);
                if (headTransform != null) break;
            }
            
            // If no head found, try to find any transform with "head" in name
            if (headTransform == null)
            {
                headTransform = FindChildWithPartialName(character.transform, "head");
            }
        }
        catch (System.Exception e)
        {
            DevLog.LogWarning($"[CashSystemManager] Error finding head for {character.name}: {e.Message}");
        }
        
        return headTransform ?? character.transform;
    }
    
    private Transform FindChildRecursive(Transform parent, string name)
    {
        foreach (Transform child in parent)
        {
            if (child.name == name) return child;
            Transform found = FindChildRecursive(child, name);
            if (found != null) return found;
        }
        return null;
    }
    
    private Transform FindChildWithPartialName(Transform parent, string partialName)
    {
        foreach (Transform child in parent)
        {
            if (child.name.ToLower().Contains(partialName.ToLower())) return child;
            Transform found = FindChildWithPartialName(child, partialName);
            if (found != null) return found;
        }
        return null;
    }
    
    /// <summary>
    /// Disable combat for a character (used before countdown)
    /// </summary>
    private void DisableCharacterCombat(GameObject character)
    {
        PlayerScript playerScript = character.GetComponent<PlayerScript>();
        if (playerScript != null)
        {
            playerScript.attack = false;
        }
        
        CharacterAIController aiController = character.GetComponent<CharacterAIController>();
        if (aiController != null)
        {
            aiController.attack = false;
        }
    }
    
    private IEnumerator MatchCountdown()
    {
        DevLog.Log("[CashSystemManager] Starting match countdown...");
        
        // Try to find existing countdown UI
        TMPro.TextMeshProUGUI countdownText = null;
        GameObject uiObject = GameObject.Find("UI");
        if (uiObject != null)
        {
            Transform roundInfo = uiObject.transform.Find("Canvas/rounds info (TMP)");
            if (roundInfo != null)
                countdownText = roundInfo.GetComponent<TMPro.TextMeshProUGUI>();
        }
        
        yield return new WaitForSecondsRealtime(1f);
        
        string[] steps = { "3", "2", "1", "FIGHT!" };
        foreach (string step in steps)
        {
            if (countdownText != null) countdownText.text = step;
            GameEvents.FireCountdownTick(step);
            yield return new WaitForSecondsRealtime(1f);
        }
        
        // Clear
        if (countdownText != null) countdownText.text = "";
        GameEvents.FireCountdownTick("");
        
        // Enable combat
        GameEvents.FireCombatEnabled(true);
        foreach (var c in playerTeamCharacters)
            if (c != null) EnableCharacterCombat(c);
        foreach (var c in enemyTeamCharacters)
            if (c != null) EnableCharacterCombat(c);
    }
    
    private void EnableCharacterCombat(GameObject character)
    {
        // Enable attack for player characters
        PlayerScript playerScript = character.GetComponent<PlayerScript>();
        if (playerScript != null)
        {
            playerScript.attack = true;
        }
        
        // Enable attack for AI characters
        CharacterAIController aiController = character.GetComponent<CharacterAIController>();
        if (aiController != null)
        {
            aiController.attack = true;
        }
    }
    
    private void SwitchControlledCharacter()
    {
        if (playerTeamCharacters.Count <= 1) return;
        
        // Use TeamControlManager if available
        if (TeamControlManager.Instance != null)
        {
            TeamControlManager.Instance.SwitchToNextCharacter();
            
            // Update local tracking
            GameObject newControlled = TeamControlManager.Instance.GetCurrentControlledCharacter();
            if (newControlled != null)
            {
                GameObject oldControlled = currentControlledIndex < playerTeamCharacters.Count 
                    ? playerTeamCharacters[currentControlledIndex] : null;
                currentControlledIndex = playerTeamCharacters.IndexOf(newControlled);
                SelectionOptions.Instance.currentControlledIndex = currentControlledIndex;
                GameEvents.FireCharacterSwitched(oldControlled, newControlled);
            }
            return;
        }
        
        // Fallback: Manual switching
        int previousIndex = currentControlledIndex;
        
        // Find next alive character
        for (int i = 1; i <= playerTeamCharacters.Count; i++)
        {
            int nextIndex = (currentControlledIndex + i) % playerTeamCharacters.Count;
            GameObject character = playerTeamCharacters[nextIndex];
            
            if (character != null)
            {
                HealthNew health = character.GetComponent<HealthNew>();
                if (health == null || !health.isDead)
                {
                    currentControlledIndex = nextIndex;
                    break;
                }
            }
        }
        
        if (currentControlledIndex != previousIndex)
        {
            SelectionOptions.Instance.currentControlledIndex = currentControlledIndex;
            
            // Disable control on previous character
            GameObject previousCharacter = playerTeamCharacters[previousIndex];
            if (previousCharacter != null)
            {
                PlayerScript prevPS = previousCharacter.GetComponent<PlayerScript>();
                if (prevPS != null) prevPS.attack = false;
                
                TeamAIController prevAI = previousCharacter.GetComponent<TeamAIController>();
                if (prevAI != null) prevAI.enabled = true;
            }
            
            // Enable control on new character
            GameObject newCharacter = playerTeamCharacters[currentControlledIndex];
            if (newCharacter != null)
            {
                PlayerScript newPS = newCharacter.GetComponent<PlayerScript>();
                if (newPS != null)
                {
                    newPS.enabled = true;
                    newPS.attack = true;
                }
                
                TeamAIController newAI = newCharacter.GetComponent<TeamAIController>();
                if (newAI != null) newAI.enabled = false;
                
                // Update camera
                UpdateCameraToCharacter(newCharacter);
            }
            
            DevLog.Log($"[CashSystemManager] Switched control to {playerTeamCharacters[currentControlledIndex].name}");
        }
    }
    
    /// <summary>
    /// Update camera to follow a specific character
    /// </summary>
    private void UpdateCameraToCharacter(GameObject character)
    {
        // Route through CameraManager (single authority) with correct Follow/LookAt separation
        if (CameraManager.Instance != null)
        {
            TeamMember teamMember = character.GetComponent<TeamMember>();
            if (teamMember != null)
            {
                CameraManager.Instance.SetTarget(teamMember);
            }
            else
            {
                CameraManager.Instance.SetTarget(character);
            }
            DevLog.Log($"[CashSystemManager] Updated camera via CameraManager to follow {character.name}");
            return;
        }
        
        // Fallback: direct Cinemachine target update with correct separation
        Transform followTarget = character.transform; // Root = orbit center
        Transform lookAtTarget = FindCharacterHead(character); // Head = aim point
        
        Cinemachine.CinemachineFreeLook[] freeLookCameras = FindObjectsOfType<Cinemachine.CinemachineFreeLook>();
        foreach (var cam in freeLookCameras)
        {
            if (cam.gameObject.activeInHierarchy)
            {
                cam.Follow = followTarget;
                cam.LookAt = lookAtTarget;
            }
        }
        
        Cinemachine.CinemachineVirtualCamera[] virtualCameras = FindObjectsOfType<Cinemachine.CinemachineVirtualCamera>();
        foreach (var cam in virtualCameras)
        {
            if (cam.gameObject.activeInHierarchy)
            {
                cam.Follow = followTarget;
                cam.LookAt = lookAtTarget;
            }
        }
        
        DevLog.Log($"[CashSystemManager] Updated camera to follow {character.name} (direct fallback)");
    }
    
    public void OnVaultUpdated(TeamVault vault)
    {
        // Legacy callback kept for backwards compat; real routing now via GameEvents
        GameEvents.FireScoreChanged(vault.TeamTag, vault.StoredCash);
    }
    
    // ─── Event Handlers ──────────────────────────────────────
    
    private void OnCashDepositedEvent(string teamTag, float value, int combo)
    {
        // UI updates itself via GameEvents — manager just tracks win conditions
    }
    
    private void OnVaultStolenEvent(TeamVault vault, float amount)
    {
        // UI updates itself via GameEvents — manager just tracks win conditions
    }
    
    // ─── Kill Reward System ($200 per kill) ──────────────────
    
    private void OnKillEvent(GameObject killer, GameObject victim)
    {
        if (matchEnded || killer == null || victim == null) return;
        
        string killerTeamTag = killer.tag;
        
        // Award $200 to killer's team
        AwardCashToTeam(killerTeamTag, killReward);
        
        GameEvents.FireKillReward(killer, killReward);
        GameEvents.FireKillFeedEntry(killer.name, "ELIMINATED", $"{victim.name} (+${killReward})");
        GameEvents.FirePopupMessage($"+${killReward} KILL REWARD", 1.5f);
        
        DevLog.Log($"[CashSystemManager] Kill reward: ${killReward} to {killerTeamTag} ({killer.name} killed {victim.name})");
        
        // Drop vault if victim was carrying one
        DropVaultOnDeath(victim);
        
        // Check for team wipe
        CheckTeamWipe(victim.tag);
    }
    
    // ─── Character Death + Respawn ───────────────────────────
    
    private void OnCharacterDiedEvent(GameObject character)
    {
        if (matchEnded || character == null) return;
        
        // Start respawn timer
        StartCoroutine(RespawnRoutine(character));
    }
    
    private IEnumerator RespawnRoutine(GameObject character)
    {
        if (character == null) yield break;
        
        HealthNew hp = character.GetComponent<HealthNew>();
        string teamTag = character.tag;
        
        DevLog.Log($"[CashSystemManager] {character.name} died, respawning in {respawnTime}s");
        
        // Countdown
        float remaining = respawnTime;
        while (remaining > 0f)
        {
            remaining -= Time.deltaTime;
            GameEvents.FireRespawnTimerUpdate(character, remaining);
            yield return null;
        }
        
        if (character == null || matchEnded) yield break;
        
        // Respawn at team spawn area
        Vector3 respawnPos = GetRespawnPosition(teamTag);
        
        // Reset health
        if (hp != null)
        {
            hp.currentHealth = hp.maxHealth;
            hp.isDead = false;
            if (hp.healthSlider != null) hp.healthSlider.value = hp.currentHealth;
        }
        
        // Teleport to respawn position
        UnityEngine.AI.NavMeshAgent agent = character.GetComponent<UnityEngine.AI.NavMeshAgent>();
        if (agent != null && agent.enabled)
        {
            agent.enabled = false;
            character.transform.position = respawnPos;
            agent.enabled = true;
            agent.Warp(respawnPos);
        }
        else
        {
            character.transform.position = respawnPos;
        }
        
        // Re-enable combat
        EnableCharacterCombat(character);
        
        // Re-enable the character if deactivated
        if (!character.activeInHierarchy)
            character.SetActive(true);
        
        GameEvents.FireCharacterRespawned(character);
        GameEvents.FireKillFeedEntry(character.name, "RESPAWNED", "");
        
        DevLog.Log($"[CashSystemManager] {character.name} respawned at {respawnPos}");
    }
    
    private Vector3 GetRespawnPosition(string teamTag)
    {
        // Use team spawn points or vault/station position
        Transform[] spawnPts = teamTag == "Player" ? playerTeamSpawnPoints : enemyTeamSpawnPoints;
        if (spawnPts != null && spawnPts.Length > 0)
        {
            Transform pt = spawnPts[Random.Range(0, spawnPts.Length)];
            if (pt != null) return pt.position;
        }
        
        // Fallback: near station or vault
        if (teamTag == "Player")
        {
            if (playerStation != null) return playerStation.transform.position + Vector3.forward * 3f;
            if (playerVault != null) return playerVault.transform.position + Vector3.forward * 3f;
        }
        else
        {
            if (enemyStation != null) return enemyStation.transform.position + Vector3.back * 3f;
            if (enemyVault != null) return enemyVault.transform.position + Vector3.back * 3f;
        }
        
        return Vector3.zero;
    }
    
    // ─── Team Wipe Detection (-30% cash penalty) ─────────────
    
    private void CheckTeamWipe(string victimTeamTag)
    {
        List<GameObject> teamChars = GetTeamCharacters(victimTeamTag);
        if (teamChars == null || teamChars.Count == 0) return;
        
        bool allDead = true;
        for (int i = 0; i < teamChars.Count; i++)
        {
            if (teamChars[i] == null) continue;
            HealthNew hp = teamChars[i].GetComponent<HealthNew>();
            if (hp == null || !hp.isDead)
            {
                allDead = false;
                break;
            }
        }
        
        if (allDead)
        {
            ApplyTeamWipePenalty(victimTeamTag);
            GameEvents.FireTeamWipe(victimTeamTag);
        }
    }
    
    private void ApplyTeamWipePenalty(string teamTag)
    {
        float currentCash = GetTeamTotalCash(teamTag);
        float penalty = currentCash * teamWipePenaltyPercent;
        
        if (penalty <= 0f) return;
        
        // Remove from CashoutStation first, then TeamVault
        if (teamTag == "Player" && playerStation != null)
            playerStation.RemoveCash(penalty);
        else if (teamTag == "Enemy" && enemyStation != null)
            enemyStation.RemoveCash(penalty);
        else if (teamTag == "Player" && playerVault != null)
            playerVault.DepositCash(-penalty); // Negative deposit = removal
        else if (teamTag == "Enemy" && enemyVault != null)
            enemyVault.DepositCash(-penalty);
        
        GameEvents.FirePopupMessage($"TEAM WIPE! -{teamWipePenaltyPercent * 100:F0}% CASH (${penalty:F0})", 3f);
        GameEvents.FireKillFeedEntry(teamTag, "TEAM WIPED!", $"-${penalty:F0}");
        
        DevLog.Log($"[CashSystemManager] Team wipe penalty: {teamTag} lost ${penalty:F0} ({teamWipePenaltyPercent * 100}%)");
    }
    
    // ─── Vault Drop on Death ─────────────────────────────────
    
    private void DropVaultOnDeath(GameObject character)
    {
        var vaults = EntityRegistry<ExtractionVault>.GetAll();
        for (int i = 0; i < vaults.Count; i++)
        {
            if (vaults[i] != null && vaults[i].IsCarried && vaults[i].Carrier == character)
            {
                vaults[i].Drop(character.transform.position);
                GameEvents.FirePopupMessage("VAULT DROPPED!", 2f);
                return;
            }
        }
    }
    
    // ─── Cash Helpers ────────────────────────────────────────
    
    /// <summary>Get total cash for a team from all sources (CashoutStation + TeamVault).</summary>
    public float GetTeamTotalCash(string teamTag)
    {
        float total = 0f;
        
        if (teamTag == "Player")
        {
            if (playerStation != null) total += playerStation.StoredCash;
            if (playerVault != null) total += playerVault.StoredCash;
        }
        else
        {
            if (enemyStation != null) total += enemyStation.StoredCash;
            if (enemyVault != null) total += enemyVault.StoredCash;
        }
        
        return total;
    }
    
    /// <summary>Award cash to a team's CashoutStation (or fallback to TeamVault).</summary>
    private void AwardCashToTeam(string teamTag, float amount)
    {
        if (teamTag == "Player")
        {
            if (playerStation != null)
                playerStation.AddDirectCash(amount);
            else if (playerVault != null)
                playerVault.DepositCash(amount);
        }
        else
        {
            if (enemyStation != null)
                enemyStation.AddDirectCash(amount);
            else if (enemyVault != null)
                enemyVault.DepositCash(amount);
        }
    }
    
    private void EndMatch(bool? playerWon = null)
    {
        if (matchEnded) return;
        matchEnded = true;
        
        // Restore time scale if buzzer was active
        if (_buzzerActive)
        {
            Time.timeScale = 1f;
            Time.fixedDeltaTime = 0.02f;
        }
        
        if (playerWon == null)
        {
            float playerScore = GetTeamTotalCash("Player");
            float enemyScore = GetTeamTotalCash("Enemy");
            playerWon = playerScore > enemyScore;
        }
        
        string winnerTag = playerWon == true ? "Player" : "Enemy";
        
        GameEvents.FireCombatEnabled(false);
        GameEvents.FireMatchEnd(winnerTag);
        GameEvents.FireMatchResult(playerWon == true);
        
        // MatchResultUI subscribes to OnMatchResult and shows itself.
        // Keep legacy screens as fallback only if MatchResultUI is absent.
        if (MatchResultUI.Instance == null)
        {
            if (playerWon == true && victoryScreen != null)
                victoryScreen.SetActive(true);
            else if (playerWon == false && defeatScreen != null)
                defeatScreen.SetActive(true);
        }
        
        StartCoroutine(EndMatchSequence());
    }
    
    private IEnumerator EndMatchSequence()
    {
        // If MatchResultUI is present, it handles navigation via Continue/Restart buttons.
        // Only auto-navigate if MatchResultUI is NOT present (legacy fallback).
        if (MatchResultUI.Instance != null)
        {
            // Let the player use the Continue / Restart buttons — don't auto-load.
            yield break;
        }
        
        yield return new WaitForSeconds(5f);
        
        GameEvents.ClearAll();
        CashSystemAI.ClearAll();
        SelectionOptions.Instance.isCashSystemSelected = false;
        SceneManager.LoadScene("MenuScene");
    }
    
    /// <summary>
    /// Get all characters on a team
    /// </summary>
    public List<GameObject> GetTeamCharacters(string teamTag)
    {
        return teamTag == "Player" ? playerTeamCharacters : enemyTeamCharacters;
    }
    
    /// <summary>
    /// Get the vault for a team
    /// </summary>
    public TeamVault GetVault(string teamTag)
    {
        return teamTag == "Player" ? playerVault : enemyVault;
    }
    
    /// <summary>
    /// Switch control to a specific character index in the player team.
    /// Called by TeamHUDPanel when a portrait is clicked.
    /// </summary>
    public void SwitchToCharacterAtIndex(int index)
    {
        if (index < 0 || index >= playerTeamCharacters.Count) return;
        if (index == currentControlledIndex) return;
        
        GameObject targetCharacter = playerTeamCharacters[index];
        if (targetCharacter == null) return;
        
        HealthNew targetHealth = targetCharacter.GetComponent<HealthNew>();
        if (targetHealth != null && targetHealth.isDead) return;
        
        // Check TeamControlManager first
        if (TeamControlManager.Instance != null)
        {
            TeamControlManager.Instance.SwitchToCharacter(index);
            
            GameObject newControlled = TeamControlManager.Instance.GetCurrentControlledCharacter();
            if (newControlled != null)
            {
                GameObject oldControlled = currentControlledIndex < playerTeamCharacters.Count
                    ? playerTeamCharacters[currentControlledIndex] : null;
                currentControlledIndex = index;
                SelectionOptions.Instance.currentControlledIndex = currentControlledIndex;
                GameEvents.FireCharacterSwitched(oldControlled, newControlled);
            }
            return;
        }
        
        // Fallback: Manual switching
        int previousIndex = currentControlledIndex;
        currentControlledIndex = index;
        SelectionOptions.Instance.currentControlledIndex = currentControlledIndex;
        
        // Disable control on previous character
        GameObject previousCharacter = playerTeamCharacters[previousIndex];
        if (previousCharacter != null)
        {
            PlayerScript prevPS = previousCharacter.GetComponent<PlayerScript>();
            if (prevPS != null) prevPS.attack = false;
            
            TeamAIController prevAI = previousCharacter.GetComponent<TeamAIController>();
            if (prevAI != null) prevAI.enabled = true;
        }
        
        // Enable control on new character
        if (targetCharacter != null)
        {
            PlayerScript newPS = targetCharacter.GetComponent<PlayerScript>();
            if (newPS != null)
            {
                newPS.enabled = true;
                newPS.attack = true;
            }
            
            TeamAIController newAI = targetCharacter.GetComponent<TeamAIController>();
            if (newAI != null) newAI.enabled = false;
            
            UpdateCameraToCharacter(targetCharacter);
        }
        
        GameEvents.FireCharacterSwitched(previousCharacter, targetCharacter);
        DevLog.Log($"[CashSystemManager] Switched control to index {index}: {targetCharacter.name}");
    }
}
