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

/// <summary>
/// Manages the transition from travel events to battle scenes
/// Handles terrain setup, team data transfer, and battle initialization
/// </summary>
public class CombatSceneManager : MonoBehaviour
{
    [Header("Scene Management")]
    [Tooltip("Name of the battle scene to load")]
    public string battleSceneName = "BattleScene";

    [Header("Terrain Generation")]
    [Tooltip("Reference to BFM Terrain Generator for battle field terrain")]
    public BFMTerrainGenerator terrainGenerator;

    [Header("Debug Settings")]
    public bool showDebugLogs = true;

    // Singleton instance
    public static CombatSceneManager Instance { get; private set; }

    // Events for other systems to hook into
    public System.Action<CombatDataTransfer.CombatSessionData> OnCombatSessionStarted;
    public System.Action OnBattleSceneLoaded;

    private void Awake()
    {
        // Ensure singleton pattern
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
            return;
        }
    }

    private void Start()
    {
        // Try to find terrain generator if not assigned
        if (terrainGenerator == null)
        {
            terrainGenerator = FindFirstObjectByType<BFMTerrainGenerator>();
        }
    }

    /// <summary>
    /// Start a combat encounter by transitioning to the battle scene
    /// </summary>
    public void StartCombatEncounter(BattleEventData battleData, TravelEventContext context)
    {
        if (showDebugLogs)
        {
            Debug.Log("⚔️ CombatSceneManager: Starting combat encounter...");
        }

        // Get team members from the game state
        List<TeamCharacter> teamMembers = GetCurrentTeamMembers();

        if (teamMembers == null || teamMembers.Count == 0)
        {
            Debug.LogError("❌ No team members found! Cannot start combat.");
            return;
        }

        // Initialize the combat session data
        CombatDataTransfer.InitializeCombatSession(battleData, context, teamMembers);

        if (showDebugLogs)
        {
            CombatDataTransfer.DebugLogSession();
        }

        // Populate legacy battle setup data for compatibility
        CombatDataTransfer.PopulateLegacyBattleSetupData();

        // Notify listeners
        OnCombatSessionStarted?.Invoke(CombatDataTransfer.GetCurrentSession());

        // Load the battle scene
        StartCoroutine(LoadBattleSceneCoroutine());
    }

    /// <summary>
    /// Get current team members from various sources
    /// </summary>
    private List<TeamCharacter> GetCurrentTeamMembers()
    {
        List<TeamCharacter> teamMembers = new List<TeamCharacter>();

        // Method 1: Try MainTeamSelectScript first (if available)
        var teamSelectScript = FindFirstObjectByType<MainTeamSelectScript>();
        if (teamSelectScript != null)
        {
            var characters = teamSelectScript.GetConfiguredCharacters();
            if (characters != null && characters.Count > 0)
            {
                teamMembers.AddRange(characters);
                if (showDebugLogs)
                {
                    Debug.Log($"📋 Found {teamMembers.Count} team members from MainTeamSelectScript");
                }
                return teamMembers;
            }
        }

        // Method 2: Try GameStateManager
        if (GameStateManager.Instance != null && GameStateManager.Instance.savedTeam != null)
        {
            foreach (var character in GameStateManager.Instance.savedTeam)
            {
                if (character != null)
                {
                    teamMembers.Add(character);
                }
            }

            if (teamMembers.Count > 0)
            {
                if (showDebugLogs)
                {
                    Debug.Log($"📋 Found {teamMembers.Count} team members from GameStateManager");
                }
                return teamMembers;
            }
        }

        // Method 3: Try loading from PlayerPrefs as fallback
        for (int i = 0; i < 4; i++)
        {
            string prefix = $"Character{i}_";
            if (PlayerPrefs.HasKey(prefix + "Exists") && PlayerPrefs.GetInt(prefix + "Exists") == 1)
            {
                var character = new TeamCharacter();
                character.name = PlayerPrefs.GetString(prefix + "Name", "");
                character.isMale = PlayerPrefs.GetInt(prefix + "IsMale", 1) == 1;
                character.strength = PlayerPrefs.GetInt(prefix + "Strength", 10);
                character.dexterity = PlayerPrefs.GetInt(prefix + "Dexterity", 10);
                character.constitution = PlayerPrefs.GetInt(prefix + "Constitution", 10);
                character.wisdom = PlayerPrefs.GetInt(prefix + "Wisdom", 10);
                character.perception = PlayerPrefs.GetInt(prefix + "Perception", 10);
                character.gold = PlayerPrefs.GetInt(prefix + "Gold", 25);
                character.silver = PlayerPrefs.GetInt(prefix + "Silver", 0);
                character.copper = PlayerPrefs.GetInt(prefix + "Copper", 0);
                character.equippedWeapon = PlayerPrefs.GetString(prefix + "EquippedWeapon", "");
                character.equippedArmor = PlayerPrefs.GetString(prefix + "EquippedArmor", "");

                // Load weapon list using the same format as MainTeamSelectScript
                character.weapons = new List<string>();
                int weaponCount = PlayerPrefs.GetInt(prefix + "WeaponCount", 0);
                for (int j = 0; j < weaponCount; j++)
                {
                    string weapon = PlayerPrefs.GetString(prefix + $"Weapon{j}", "");
                    if (!string.IsNullOrEmpty(weapon))
                    {
                        character.weapons.Add(weapon);
                    }
                }

                // Load armor list using the same format as MainTeamSelectScript
                character.armor = new List<string>();
                int armorCount = PlayerPrefs.GetInt(prefix + "ArmorCount", 0);
                for (int j = 0; j < armorCount; j++)
                {
                    string armor = PlayerPrefs.GetString(prefix + $"Armor{j}", "");
                    if (!string.IsNullOrEmpty(armor))
                    {
                        character.armor.Add(armor);
                    }
                }

                // Debug the loaded character data
                if (showDebugLogs)
                {
                    Debug.Log($"🔧 Loaded character '{character.name}': equippedWeapon='{character.equippedWeapon}', weapons=[{string.Join(", ", character.weapons)}]");
                }

                teamMembers.Add(character);
            }
        }

        if (teamMembers.Count > 0)
        {
            if (showDebugLogs)
            {
                Debug.Log($"📋 Found {teamMembers.Count} team members from PlayerPrefs");
            }
        }
        else
        {
            Debug.LogWarning("⚠️ No team members found in any data source!");
        }

        return teamMembers;
    }

    /// <summary>
    /// Coroutine to handle battle scene loading
    /// </summary>
    private IEnumerator LoadBattleSceneCoroutine()
    {
        if (showDebugLogs)
        {
            Debug.Log($"🎬 Loading battle scene: {battleSceneName}");
        }

        // Check if scene exists in build settings
        if (!IsSceneInBuildSettings(battleSceneName))
        {
            Debug.LogError($"❌ Battle scene '{battleSceneName}' not found in Build Settings!");
            yield break;
        }

        // Start loading the scene asynchronously
        AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(battleSceneName);

        // Wait for the scene to load
        while (!asyncLoad.isDone)
        {
            // You could update a loading bar here
            yield return null;
        }

        if (showDebugLogs)
        {
            Debug.Log("✅ Battle scene loaded successfully");
        }

        // Notify that the battle scene has loaded
        OnBattleSceneLoaded?.Invoke();

        // Set up the terrain in the battle scene
        yield return StartCoroutine(SetupBattleTerrainCoroutine());
    }

    /// <summary>
    /// Set up the battle terrain based on the combat session data
    /// </summary>
    private IEnumerator SetupBattleTerrainCoroutine()
    {
        // Wait a frame to ensure the scene is fully loaded
        yield return null;

        var session = CombatDataTransfer.GetCurrentSession();
        if (session == null)
        {
            Debug.LogWarning("⚠️ No combat session data available for terrain setup");
            yield break;
        }

        // Find or create terrain generator in the new scene
        if (terrainGenerator == null)
        {
            terrainGenerator = FindFirstObjectByType<BFMTerrainGenerator>();
        }

        if (terrainGenerator != null)
        {
            // Convert TerrainType to BFMTerrainType
            BFMTerrainType bfmTerrain = ConvertToBFMTerrainType(session.battleTerrain);

            if (showDebugLogs)
            {
                Debug.Log($"🌍 Setting battle terrain to: {bfmTerrain} (from {session.battleTerrain})");
            }

            // Set the terrain type
            terrainGenerator.SetTerrainType(bfmTerrain);

            // Regenerate the terrain if there's a method for it
            if (terrainGenerator.GetComponent<MonoBehaviour>() != null)
            {
                // You might need to call a regeneration method here
                // terrainGenerator.RegenerateTerrain(); // If such method exists
            }
        }
        else
        {
            if (showDebugLogs)
            {
                Debug.LogWarning("⚠️ No BFMTerrainGenerator found in battle scene - terrain setup skipped");
            }
        }

        // Log the battle setup information
        if (showDebugLogs)
        {
            string terrainDesc = CombatDataTransfer.GetTerrainDescription(session.battleTerrain, session.battleFeature);
            Debug.Log($"🎯 Battle setup complete: Fighting {terrainDesc}");
            Debug.Log($"⏰ Time: {session.timeOfDay:F1}h, Weather: {session.weather}");
        }
    }

    /// <summary>
    /// Convert TerrainType to BFMTerrainType for battle field generation
    /// </summary>
    private BFMTerrainType ConvertToBFMTerrainType(TerrainType terrainType)
    {
        return terrainType switch
        {
            TerrainType.Plains => BFMTerrainType.Plain,
            TerrainType.Forest => BFMTerrainType.Forest,
            TerrainType.Mountain => BFMTerrainType.Mountain,
            TerrainType.ForestRiver => BFMTerrainType.Forest, // Forest with river features
            _ => BFMTerrainType.Plain // Default to plains for other terrain types
        };
    }

    /// <summary>
    /// Check if a scene exists in build settings
    /// </summary>
    private bool IsSceneInBuildSettings(string sceneName)
    {
        for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++)
        {
            string scenePath = UnityEngine.SceneManagement.SceneUtility.GetScenePathByBuildIndex(i);
            string sceneNameFromPath = System.IO.Path.GetFileNameWithoutExtension(scenePath);

            if (sceneNameFromPath.Equals(sceneName, System.StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
        }
        return false;
    }

    /// <summary>
    /// End the current combat session and return to the map
    /// </summary>
    public void EndCombatSession(bool playerVictory)
    {
        if (showDebugLogs)
        {
            Debug.Log($"🏆 Combat session ended - Player victory: {playerVictory}");
        }

        // Clear the combat session data
        CombatDataTransfer.ClearSession();

        // Return to the map scene
        // You might want to load "MapScene2" or whatever your main map scene is called
        StartCoroutine(ReturnToMapCoroutine());
    }

    /// <summary>
    /// Return to the map scene after combat
    /// </summary>
    private IEnumerator ReturnToMapCoroutine()
    {
        yield return new WaitForSeconds(2f); // Brief delay for any end-of-combat UI

        string mapSceneName = "MapScene2"; // Adjust this to your actual map scene name

        if (IsSceneInBuildSettings(mapSceneName))
        {
            if (showDebugLogs)
            {
                Debug.Log($"🗺️ Returning to map scene: {mapSceneName}");
            }
            SceneManager.LoadScene(mapSceneName);
        }
        else
        {
            Debug.LogError($"❌ Map scene '{mapSceneName}' not found in Build Settings!");
        }
    }

    /// <summary>
    /// Get current battle context for UI display
    /// </summary>
    public string GetBattleContextDescription()
    {
        var session = CombatDataTransfer.GetCurrentSession();
        if (session == null) return "Unknown battle";

        string terrainDesc = CombatDataTransfer.GetTerrainDescription(session.battleTerrain, session.battleFeature);
        string timeDesc = GetTimeDescription(session.timeOfDay);
        string weatherDesc = session.weather.ToString().ToLower();

        return $"Battle {terrainDesc} during {timeDesc} ({weatherDesc} weather)";
    }

    /// <summary>
    /// Convert time of day to readable description
    /// </summary>
    private string GetTimeDescription(float timeOfDay)
    {
        return timeOfDay switch
        {
            >= 6f and < 12f => "morning",
            >= 12f and < 18f => "afternoon",
            >= 18f and < 22f => "evening",
            _ => "night"
        };
    }

    /// <summary>
    /// Debug method to manually start a test combat
    /// </summary>
    [ContextMenu("Start Test Combat")]
    public void StartTestCombat()
    {
        // Create test battle data
        var testBattleData = new BattleEventData
        {
            enemyCount = 2,
            enemyType = "Test Bandit",
            battleDescription = "A test combat encounter"
        };

        // Create test context
        var testContext = new TravelEventContext(Vector2Int.zero, null, null)
        {
            currentWeather = Weather.Clear,
            timeOfDay = 14f
        };

        // Use fake tile data
        testContext.currentTile = new MapTile(0, 0)
        {
            terrainType = TerrainType.Plains,
            featureType = FeatureType.Road
        };

        StartCombatEncounter(testBattleData, testContext);
    }
}
