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

/// <summary>
/// Gestionnaire de niveaux – version JSON simplifiée
/// Compatible avec le système multi-scènes
/// </summary>
public class LevelManager : MonoBehaviour
{
    [Header("Configuration")]
    [Tooltip("URL du JSON des niveaux (nouveau format). Si vide, utilise la valeur de general-config.json")]
    public string levelsConfigUrl = "";

    [Header("Scenes")]
    [SerializeField] private string mainMenuSceneName = "menu";

    [Header("Debug")]
    public bool debugMode = false; // Désactivé par défaut pour moins de logs

    // Données chargées
    private LevelsConfig levelsConfig;

    // Variables internes
    private bool isLoadingConfiguration = false;
    private bool configurationLoaded = false;

    // Pour la compatibilité avec l'ancien système
    private string gameTitle = "UJSA / Jeux";
    private string gameVersion = "1.0.0";
    private List<LevelData> levels = new List<LevelData>();

    // Événements
    public System.Action OnConfigurationLoaded;

    // Singleton pour accès global
    public static LevelManager Instance { get; private set; }

    void Awake()
    {
        // Implémentation Singleton
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
            return;
        }
    }

    void Start()
    {
        StartCoroutine(LoadLevelsConfiguration());
    }

    /// <summary>
    /// Recharge la configuration (utile pour le bouton Refresh du menu)
    /// </summary>
    public void ReloadConfiguration(bool forceReload = false)
    {
        if (forceReload || !IsConfigurationLoaded())
        {
            configurationLoaded = false;
            StartCoroutine(LoadLevelsConfiguration());
        }
    }

    /// <summary>
    /// Retourne à la scène du menu principal
    /// </summary>
    public void ReturnToMainMenu()
    {
        if (string.IsNullOrEmpty(mainMenuSceneName))
        {
            Debug.LogError("[LevelManager] mainMenuSceneName n'est pas défini.");
            return;
        }

        SceneManager.LoadScene(mainMenuSceneName);
    }

    /// <summary>
    /// Charge la configuration des niveaux depuis l'URL
    /// </summary>
    IEnumerator LoadLevelsConfiguration()
    {
        if (isLoadingConfiguration)
        {
            DebugLogger.LogWarning("Configuration déjà en cours de chargement", "LevelManager");
            yield break;
        }

        isLoadingConfiguration = true;

        try
        {
            // Attendre un peu pour éviter le rate limiting
            yield return new WaitForSeconds(0.5f);

            // PRIORITÉ : Essayer d'abord le fichier local (StreamingAssets)
            string localPath = System.IO.Path.Combine(Application.streamingAssetsPath, "json", "levels-config.json");
            string localUrl = "file:///" + localPath.Replace("\\", "/");
            
            // En mode éditeur ou build local, utiliser le fichier local en priorité
            #if UNITY_EDITOR || !UNITY_WEBGL
            if (System.IO.File.Exists(localPath))
            {
                DebugLogger.LogInfo($"Chargement depuis fichier local: {localUrl}", "LevelManager");
                using (var www = UnityWebRequest.Get(localUrl))
                {
                    yield return www.SendWebRequest();
                    
                    if (www.result == UnityWebRequest.Result.Success)
                    {
                        string json = www.downloadHandler.text;
                        DebugLogger.LogInfo("Configuration chargée depuis fichier local avec succès", "LevelManager");
                        
                        try
                        {
                            levelsConfig = JsonUtility.FromJson<LevelsConfig>(json);
                            
                            if (levelsConfig != null && levelsConfig.levels != null)
                            {
                                // Forcer l'utilisation des valeurs depuis general-config.json
                                ApplyGeneralConfigOverrides();
                                
                                levels = levelsConfig.levels;
                                gameTitle = levelsConfig.gameTitle;
                                gameVersion = levelsConfig.gameVersion;
                                
                                DebugLogger.LogInfo($"{levelsConfig.levels.Count} niveaux chargés depuis fichier local", "LevelManager");
                                configurationLoaded = true;
                                
                                if (debugMode)
                                    LogAllLevels();
                                
                                OnConfigurationLoaded?.Invoke();
                                yield break; // Succès, sortir
                            }
                        }
                        catch (System.Exception e)
                        {
                            DebugLogger.LogError($"Erreur parsing JSON local: {e.Message}", "LevelManager");
                            // Continuer avec l'URL distante en fallback
                        }
                    }
                    else
                    {
                        DebugLogger.LogWarning($"Erreur chargement fichier local: {www.error}, fallback vers URL distante", "LevelManager");
                    }
                }
            }
            else
            {
                DebugLogger.LogInfo($"Fichier local introuvable: {localPath}, utilisation URL distante", "LevelManager");
            }
            #endif

            // Fallback : charger depuis l'URL distante
            // Si levelsConfigUrl est vide, utiliser la valeur depuis general-config.json
            string finalLevelsConfigUrl = levelsConfigUrl;
            if (string.IsNullOrEmpty(finalLevelsConfigUrl))
            {
                finalLevelsConfigUrl = GeneralConfigManager.Instance?.GetDefaultGameConfigUrl("levels") ?? "";
                if (!string.IsNullOrEmpty(finalLevelsConfigUrl))
                {
                    DebugLogger.LogInfo($"Utilisation de la config par défaut: {finalLevelsConfigUrl}", "LevelManager");
                }
            }
            
            if (string.IsNullOrEmpty(finalLevelsConfigUrl))
            {
                DebugLogger.LogError("levelsConfigUrl introuvable et aucune valeur par défaut disponible", "LevelManager");
                CreateFallbackConfig();
                yield break;
            }
            
            DebugLogger.LogInfo($"Chargement depuis URL distante: {finalLevelsConfigUrl}", "LevelManager");
            using (var www = UnityWebRequest.Get(finalLevelsConfigUrl))
            {
                www.SetRequestHeader("Cache-Control", "no-cache");
                yield return www.SendWebRequest();

                if (www.result == UnityWebRequest.Result.Success)
                {
                    string json = www.downloadHandler.text;
                    DebugLogger.LogInfo("Configuration chargée avec succès", "LevelManager");

                    try
                    {
                        // Parser avec la structure LevelsConfig
                        levelsConfig = JsonUtility.FromJson<LevelsConfig>(json);

                        if (levelsConfig != null && levelsConfig.levels != null)
                        {
                            // Forcer l'utilisation des valeurs depuis general-config.json
                            ApplyGeneralConfigOverrides();
                            
                            // Mettre à jour les variables de compatibilité
                            levels = levelsConfig.levels;
                            gameTitle = levelsConfig.gameTitle;
                            gameVersion = levelsConfig.gameVersion;

                            DebugLogger.LogInfo($"{levelsConfig.levels.Count} niveaux chargés", "LevelManager");
                            DebugLogger.LogInfo($"Jeu: {gameTitle} v{gameVersion}", "LevelManager");

                            // Marquer comme chargé
                            configurationLoaded = true;

                            if (debugMode)
                                LogAllLevels();

                            // Déclencher l'événement
                            OnConfigurationLoaded?.Invoke();
                        }
                        else
                        {
                            DebugLogger.LogError("Structure JSON invalide", "LevelManager");
                            CreateFallbackConfig();
                        }
                    }
                    catch (System.Exception e)
                    {
                        DebugLogger.LogError($"Erreur parsing JSON: {e.Message}", "LevelManager");
                        CreateFallbackConfig();
                    }
                }
                else
                {
                    DebugLogger.LogError($"Erreur chargement config niveaux : {www.error}", "LevelManager");
                    CreateFallbackConfig();
                }
            }
        }
        finally
        {
            isLoadingConfiguration = false;
        }
    }

    /// <summary>
    /// Applique les valeurs depuis general-config.json pour forcer l'utilisation des URLs centralisées
    /// </summary>
    void ApplyGeneralConfigOverrides()
    {
        if (levelsConfig == null) return;
        
        // Forcer l'utilisation de urlRootThumbnails depuis general-config.json
        string urlRootThumbnails = GeneralConfigManager.Instance?.GetLevelsConfigUrlRootThumbnails() ?? "";
        if (!string.IsNullOrEmpty(urlRootThumbnails))
        {
            levelsConfig.urlRootThumbnails = urlRootThumbnails;
            DebugLogger.LogInfo($"✅ urlRootThumbnails forcé depuis general-config.json: {urlRootThumbnails}", "LevelManager");
        }
        else
        {
            Debug.LogError("[LevelManager] ❌ urlRootThumbnails non défini dans general-config.json");
        }
        
        // Forcer aussi urlRootJson depuis general-config.json pour cohérence
        string urlRootJson = GeneralConfigManager.Instance?.GetLevelsConfigUrlRootJson() ?? "";
        if (!string.IsNullOrEmpty(urlRootJson))
        {
            levelsConfig.urlRootJson = urlRootJson;
            DebugLogger.LogInfo($"✅ urlRootJson forcé depuis general-config.json: {urlRootJson}", "LevelManager");
        }
    }

    /// <summary>
    /// Crée une configuration de fallback si le chargement échoue
    /// </summary>
    void CreateFallbackConfig()
    {
        // Récupérer les URLs depuis general-config.json
        string urlRootJson = GeneralConfigManager.Instance?.GetLevelsConfigUrlRootJson() ?? "";
        string urlRootThumbnails = GeneralConfigManager.Instance?.GetLevelsConfigUrlRootThumbnails() ?? "";
        
        if (string.IsNullOrEmpty(urlRootJson))
        {
            Debug.LogError("[LevelManager] ❌ urlRootJson non défini dans general-config.json");
            urlRootJson = ""; // Laisser vide plutôt qu'une valeur en dur
        }
        if (string.IsNullOrEmpty(urlRootThumbnails))
        {
            Debug.LogError("[LevelManager] ❌ urlRootThumbnails non défini dans general-config.json");
            urlRootThumbnails = ""; // Laisser vide plutôt qu'une valeur en dur
        }
        
        levelsConfig = new LevelsConfig
        {
            gameTitle = "UJSA / Jeux",
            gameVersion = "1.0.0",
            urlRootJson = urlRootJson,
            urlRootThumbnails = urlRootThumbnails,
            extensionJson = ".json",
            extensionThumbnails = ".jpg",
            levels = new List<LevelData>
            {
                new LevelData
                {
                    id = "quete01_shooting_smouth",
                    title = "Demo Shooting (Fallback)",
                    type = "shooting",
                    questId = "quete01",
                    isEnabled = true
                }
            }
        };

        // Mettre à jour les variables de compatibilité
        levels = levelsConfig.levels;
        gameTitle = levelsConfig.gameTitle;
        gameVersion = levelsConfig.gameVersion;
        configurationLoaded = true;

        DebugLogger.LogWarning("Configuration de fallback créée.", "LevelManager");
    }

    /// <summary>
    /// Charge un niveau spécifique (NOUVEAU SYSTÈME MULTI-SCÈNES)
    /// </summary>
    public void LoadLevel(string levelId)
    {
        if (!IsConfigurationLoaded())
        {
            DebugLogger.LogError("Configuration non chargée !", "LevelManager");
            return;
        }

        LevelData level = levels.Find(l => l.id == levelId);
        if (level == null)
        {
            DebugLogger.LogError($"Niveau '{levelId}' introuvable !", "LevelManager");
            return;
        }

        if (!level.isEnabled)
        {
            DebugLogger.LogWarning($"Niveau '{levelId}' est désactivé !", "LevelManager");
            return;
        }

        DebugLogger.LogInfo($"Lancement niveau: {level.title} ({level.type})", "LevelManager");

        // NOUVEAU SYSTÈME : Lancer le flow multi-scènes
        LaunchLevelWithMultiScene(level);
    }

    /// <summary>
    /// Lance un niveau avec le nouveau système multi-scènes
    /// </summary>
    void LaunchLevelWithMultiScene(LevelData level)
    {
        // Construire l'URL du JSON principal du jeu
        string gameConfigUrl = GetLevelConfigUrl(level);
        
        // IMPORTANT : Sauvegarder la scène actuelle pour y retourner après le jeu
        string currentScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
        PlayerPrefs.SetString("ReturnToScene", currentScene);
        DebugLogger.LogInfo($"Scène d'origine: {currentScene}", "LevelManager");

        // Stocker les infos pour le système multi-scènes
        PlayerPrefs.SetString("CurrentLevelId", level.id);
        PlayerPrefs.SetString("CurrentLevelType", level.type);
        PlayerPrefs.SetString("GameConfigUrl", gameConfigUrl);
        PlayerPrefs.SetString("GamePhase", "Before");
        
        // CORRECTION : Définir CurrentMapId pour le retour après le jeu (si c'est une Map)
        // Si returnToMapId existe, l'utiliser, sinon utiliser le mapId par défaut
        if (currentScene.ToLower() == "map")
        {
            string mapId = !string.IsNullOrEmpty(level.returnToMapId) 
                ? level.returnToMapId 
                : (GeneralConfigManager.Instance != null 
                    ? GeneralConfigManager.Instance.GetDefaultMapId() 
                    : "map-Q2");
            PlayerPrefs.SetString("CurrentMapId", mapId);
            DebugLogger.LogInfo($"Map retour: {mapId}", "LevelManager");
        }
        
        PlayerPrefs.Save();

        DebugLogger.LogInfo($"Niveau: {level.title} ({level.type})", "LevelManager");
        DebugLogger.LogInfo($"Config URL: {gameConfigUrl}", "LevelManager");

        if (debugMode)
        {
            DebugLogger.Log($"Phase: Before", "LevelManager");
            DebugLogger.Log("Transition vers scène Player...", "LevelManager");
        }

        // Charger la scène Player pour le dialogue BEFORE
        SceneManager.LoadScene("Player");
    }

    /// <summary>
    /// Vérifie si les prérequis pour débloquer un niveau sont remplis (optionnel)
    /// </summary>
    bool CheckUnlockRequirements(LevelData level)
    {
        if (level.unlockRequirements == null ||
            level.unlockRequirements.requiredLevels == null ||
            level.unlockRequirements.requiredLevels.Count == 0)
        {
            return true; // Pas de prérequis
        }

        // TODO: logique réelle si besoin
        return true;
    }

    // =======================
    // Helpers publics
    // =======================

    public List<LevelData> GetAllLevels()
        => levels ?? new List<LevelData>();

    public LevelData GetLevel(string levelId)
        => levels?.Find(l => l.id == levelId);

    public string GetGameTitle()
        => gameTitle;

    public string GetGameVersion()
        => gameVersion;

    public bool IsConfigurationLoaded()
        => configurationLoaded && levels != null && levels.Count > 0;

    // URLs calculées
    public string GetLevelConfigUrl(LevelData level)
    {
        // Compatibilité : si un ancien JSON a encore configUrl, on le prend
        if (!string.IsNullOrEmpty(level.configUrl))
        {
            DebugLogger.Log($"URL config (explicite) pour {level.id}: {level.configUrl}", "LevelManager");
            return level.configUrl;
        }

        string url = UrlJoin(levelsConfig?.urlRootJson, $"{level.id}{levelsConfig?.extensionJson}");
        
        // Convertir STREAMING_ASSETS/ en chemin local file:/// si nécessaire
        if (url.StartsWith("STREAMING_ASSETS/"))
        {
            string fileName = url.Substring("STREAMING_ASSETS/".Length);
            string streamingAssetsPath = System.IO.Path.Combine(Application.streamingAssetsPath, fileName);
            streamingAssetsPath = streamingAssetsPath.Replace("\\", "/");
            
            #if UNITY_WEBGL && !UNITY_EDITOR
            url = streamingAssetsPath;
            #else
            url = "file:///" + streamingAssetsPath;
            #endif
            
            DebugLogger.Log($"URL config (convertie) pour {level.id}: {url}", "LevelManager");
        }
        else
        {
            DebugLogger.Log($"URL config (construite) pour {level.id}: {url}", "LevelManager");
        }
        
        return url;
    }

    public string GetLevelThumbnailUrl(LevelData level)
    {
        // Compatibilité : si un ancien JSON a encore thumbnailUrl, on le prend
        if (!string.IsNullOrEmpty(level.thumbnailUrl))
        {
            DebugLogger.Log($"URL thumbnail (explicite) pour {level.id}: {level.thumbnailUrl}", "LevelManager");
            return level.thumbnailUrl;
        }

        string url = UrlJoin(levelsConfig?.urlRootThumbnails, $"{level.id}{levelsConfig?.extensionThumbnails}");
        
        // Convertir STREAMING_ASSETS/ en chemin local file:/// si nécessaire
        if (url.StartsWith("STREAMING_ASSETS/"))
        {
            string fileName = url.Substring("STREAMING_ASSETS/".Length);
            string streamingAssetsPath = System.IO.Path.Combine(Application.streamingAssetsPath, fileName);
            streamingAssetsPath = streamingAssetsPath.Replace("\\", "/");
            
            #if UNITY_WEBGL && !UNITY_EDITOR
            url = streamingAssetsPath;
            #else
            url = "file:///" + streamingAssetsPath;
            #endif
            
            DebugLogger.Log($"URL thumbnail (convertie) pour {level.id}: {url}", "LevelManager");
        }
        else
        {
            DebugLogger.Log($"URL thumbnail (construite) pour {level.id}: {url}", "LevelManager");
        }
        
        return url;
    }

    public static string UrlJoin(string root, string tail)
    {
        if (string.IsNullOrEmpty(root)) return tail ?? "";
        if (string.IsNullOrEmpty(tail)) return root ?? "";
        if (!root.EndsWith("/")) root += "/";
        if (tail.StartsWith("/")) tail = tail.Substring(1);
        return root + tail;
    }

    void LogAllLevels()
    {
        DebugLogger.Log("=== TOUS LES NIVEAUX ===", "LevelManager");
        foreach (var level in levels)
        {
            string cfg = GetLevelConfigUrl(level);
            string th = GetLevelThumbnailUrl(level);
            DebugLogger.Log($"[{level.id}] {level.title} - Type:{level.type} - Quête:{level.questId} - Enabled:{level.isEnabled}", "LevelManager");
        }
        DebugLogger.Log("========================", "LevelManager");
    }

    /// <summary>
    /// MODIFIÉ : Retour à la scène d'origine (Menu ou Map) avec support du système de steps
    /// </summary>
    public void ReturnToMap()
    {
        // CORRECTION : Retourner à la scène d'origine (Menu ou Map)
        string returnToScene = PlayerPrefs.GetString("ReturnToScene", "menu");
        DebugLogger.LogInfo($"Retour à la scène: {returnToScene}", "LevelManager");
        
        // Si on retourne à la Map, gérer le nextStepId
        if (returnToScene.ToLower() == "map")
        {
            // PRIORITÉ 1: Utiliser le CurrentMapId déjà sauvegardé (depuis MapManager.LaunchLevel)
            string mapId = PlayerPrefs.GetString("CurrentMapId", "");
            DebugLogger.LogInfo($"ReturnToMap - CurrentMapId récupéré: '{mapId}'", "LevelManager");
            
            // PRIORITÉ 2: Si pas de CurrentMapId, chercher dans currentLevel
            if (string.IsNullOrEmpty(mapId))
            {
                LevelData currentLevel = GetLevel(PlayerPrefs.GetString("CurrentLevelId", ""));
                if (currentLevel != null && !string.IsNullOrEmpty(currentLevel.returnToMapId))
                {
                    mapId = currentLevel.returnToMapId;
                    DebugLogger.LogInfo($"ReturnToMap - mapId depuis currentLevel: '{mapId}'", "LevelManager");
                }
            }
            
            // PRIORITÉ 3: Fallback sur la map par défaut
            if (string.IsNullOrEmpty(mapId))
            {
                mapId = GeneralConfigManager.Instance != null ? 
                    GeneralConfigManager.Instance.GetDefaultMapId() : "map-Q0";
                DebugLogger.LogWarning($"ReturnToMap - Aucun mapId trouvé, utilisation du défaut: '{mapId}'", "LevelManager");
            }

            PlayerPrefs.SetString("CurrentMapId", mapId);

            // NOUVEAU: Appliquer le nextStepId si disponible
            string nextStepId = PlayerPrefs.GetString("NextStepId_" + mapId, "");
            DebugLogger.LogInfo($"ReturnToMap - mapId: {mapId}, nextStepId trouvé: '{nextStepId}'", "LevelManager");
            
            if (!string.IsNullOrEmpty(nextStepId))
            {
                PlayerPrefs.SetString("CurrentStepId_" + mapId, nextStepId);
                PlayerPrefs.DeleteKey("NextStepId_" + mapId);
                DebugLogger.LogInfo($"Passage au step: {nextStepId}", "LevelManager");
            }
            else
            {
                DebugLogger.LogWarning($"Aucun NextStepId trouvé pour {mapId} - restera sur le step actuel", "LevelManager");
            }
        }
        else
        {
            DebugLogger.LogInfo($"Retour au {returnToScene} - pas de gestion de steps", "LevelManager");
        }

        // Nettoyer les PlayerPrefs temporaires
        PlayerPrefs.DeleteKey("GameConfigUrl");
        PlayerPrefs.DeleteKey("GamePhase");
        PlayerPrefs.DeleteKey("ReturnToScene");
        PlayerPrefs.Save();
        
        // Charger la scène d'origine
        SceneManager.LoadScene(returnToScene);
    }

    public DialogueConfig GetDialogueConfig()
    {
        return levelsConfig?.dialogueConfig;
    }
}

// ========================================
// CLASSES DE DONNÉES
// ========================================

[Serializable]
public class LevelsConfig
{
    public string gameTitle;
    public string gameVersion;
    public string urlRootJson;
    public string urlRootThumbnails;
    public string extensionJson = ".json";
    public string extensionThumbnails = ".jpg";
    public DialogueConfig dialogueConfig;
    public List<LevelData> levels;
}