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

public class GameConfigLoader : MonoBehaviour
{
    [Serializable]
    public class GameConfigData
    {
        public string questionsUrl;
        public string dialoguesUrl; // Fichier de dialogues groupés
        public string dialogueBeforeUrl; // Ancien système (deprecated)
        public string dialogueSuccessUrl; // Ancien système (deprecated)
        public string dialogueFailUrl; // Ancien système (deprecated)
    }

    [Serializable]
    public class GameConfigWrapper
    {
        public GameConfigData gameConfig;
    }
    
    // Structures pour les dialogues groupés
    [Serializable]
    public class DialogueContent
    {
        public string title;
        public string speaker;
        public string video;
        public System.Collections.Generic.List<DialogueLine> lines = new System.Collections.Generic.List<DialogueLine>();
    }
    
    [Serializable]
    public class DialogueLine
    {
        public string text;
        public string image;
    }
    
    [Serializable]
    public class DialoguesData
    {
        public AllDialogues dialogues;
    }
    
    [Serializable]
    public class AllDialogues
    {
        public DialogueContent intro;
        public DialogueContent success;
        public DialogueContent fail;
    }
    
    // Wrapper pour la sérialisation JSON vers SubtitleManager
    [Serializable]
    private class DialogueWrapperForJson
    {
        public DialogueContent dialogue;
    }

    private void Awake()
    {
        // 🧹 NETTOYAGE IMMÉDIAT : Supprimer tous les éléments de jeu résiduels dès l'Awake
        // Ceci est crucial quand on arrive depuis un changement de quête (via panel Options)
        // car les éléments du jeu précédent pourraient encore exister dans DontDestroyOnLoad
        CleanupGameElements();
    }
    
    private void Start()
    {
        StartCoroutine(LoadAndProcessConfig());
    }
    
    /// <summary>
    /// Nettoie les éléments de jeu qui pourraient persister (ShootingGameLayout, etc.)
    /// Appelé dans Awake et au début de la phase "After"
    /// </summary>
    private void CleanupGameElements()
    {
        Debug.Log("[GameConfigLoader] 🧹 Nettoyage des éléments de jeu résiduels...");
        
        // Détruire les layouts de jeu (chercher dans TOUTES les scènes y compris DontDestroyOnLoad)
        var shootingLayouts = FindObjectsByType<ShootingGameLayout>(FindObjectsInactive.Include, FindObjectsSortMode.None);
        foreach (var layout in shootingLayouts)
        {
            Debug.Log($"[GameConfigLoader] 🗑️ ShootingGameLayout détruit (scene: {layout.gameObject.scene.name})");
            DestroyImmediate(layout.gameObject);
        }
        
        var calculatorLayouts = FindObjectsByType<CalculatorGameLayout>(FindObjectsInactive.Include, FindObjectsSortMode.None);
        foreach (var layout in calculatorLayouts)
        {
            Debug.Log($"[GameConfigLoader] 🗑️ CalculatorGameLayout détruit (scene: {layout.gameObject.scene.name})");
            DestroyImmediate(layout.gameObject);
        }
        
        var trousLayouts = FindObjectsByType<TrousGameLayout>(FindObjectsInactive.Include, FindObjectsSortMode.None);
        foreach (var layout in trousLayouts)
        {
            Debug.Log($"[GameConfigLoader] 🗑️ TrousGameLayout détruit (scene: {layout.gameObject.scene.name})");
            DestroyImmediate(layout.gameObject);
        }
        
        // Détruire les GameManagers résiduels
        var gameManagers = FindObjectsByType<GameManager>(FindObjectsInactive.Include, FindObjectsSortMode.None);
        foreach (var manager in gameManagers)
        {
            Debug.Log($"[GameConfigLoader] 🗑️ GameManager détruit (scene: {manager.gameObject.scene.name})");
            DestroyImmediate(manager.gameObject);
        }
        
        var calculatorManagers = FindObjectsByType<CalculatorGameManager>(FindObjectsInactive.Include, FindObjectsSortMode.None);
        foreach (var manager in calculatorManagers)
        {
            Debug.Log($"[GameConfigLoader] 🗑️ CalculatorGameManager détruit (scene: {manager.gameObject.scene.name})");
            DestroyImmediate(manager.gameObject);
        }
        
        var trousManagers = FindObjectsByType<TrousGameManager>(FindObjectsInactive.Include, FindObjectsSortMode.None);
        foreach (var manager in trousManagers)
        {
            Debug.Log($"[GameConfigLoader] 🗑️ TrousGameManager détruit (scene: {manager.gameObject.scene.name})");
            DestroyImmediate(manager.gameObject);
        }
        
        // Nettoyer les éléments UI du jeu par nom (incluant ceux qui pourraient être dans DontDestroyOnLoad)
        string[] gameObjectNames = new string[] {
            "ShootingGameCanvas",
            "CalculatorGameCanvas", 
            "TrousGameCanvas",
            "GameCanvas",
            "HeaderPanel",
            "GameAreaPanel",
            "TopBand",
            "BottomBand",
            "MainBackgroundImage",
            "VideoMaskContainer"
        };
        
        foreach (string objName in gameObjectNames)
        {
            // Chercher dans tous les objets, y compris inactifs
            GameObject[] allObjects = FindObjectsByType<GameObject>(FindObjectsInactive.Include, FindObjectsSortMode.None);
            foreach (var obj in allObjects)
            {
                if (obj != null && obj.name == objName)
                {
                    Debug.Log($"[GameConfigLoader] 🗑️ {objName} détruit (scene: {obj.scene.name})");
                    DestroyImmediate(obj);
                }
            }
        }
        
        // Réinitialiser les singletons statiques des layouts
        // (au cas où Instance pointe vers un objet détruit)
        if (ShootingGameLayout.Instance != null)
        {
            Debug.Log("[GameConfigLoader] ⚠️ ShootingGameLayout.Instance encore défini après nettoyage - forçage à null");
        }
        
        Debug.Log("[GameConfigLoader] ✅ Nettoyage des éléments de jeu terminé");
    }

    private IEnumerator LoadAndProcessConfig()
    {
        // Attendre que GeneralConfigManager soit prêt
        while (GeneralConfigManager.Instance == null)
        {
            yield return null;
        }
        
        while (!GeneralConfigManager.Instance.IsConfigLoaded())
        {
            yield return null;
        }
        
        string configUrl = PlayerPrefs.GetString("GameConfigUrl");
        string phase = PlayerPrefs.GetString("GamePhase", "Before");
        string levelId = PlayerPrefs.GetString("CurrentLevelId");
        string levelType = PlayerPrefs.GetString("CurrentLevelType");
        
        // 🧹 NOUVEAU : Si on est en phase "After", nettoyer les éléments de jeu
        if (phase == "After")
        {
            CleanupGameElements();
        }

        DebugLogger.Log("=== DEBUG PLAYERPREFS ===", "GameConfigLoader");
        DebugLogger.Log($"ConfigUrl: '{configUrl}'", "GameConfigLoader");
        DebugLogger.Log($"Phase: '{phase}'", "GameConfigLoader");
        DebugLogger.Log($"LevelId: '{levelId}'", "GameConfigLoader");
        DebugLogger.Log($"LevelType: '{levelType}'", "GameConfigLoader");
        DebugLogger.Log("========================", "GameConfigLoader");
        
        // NOUVEAU : Vérifier si des données API sont disponibles via GameDataManager
        if (GameDataManager.Instance != null && GameDataManager.Instance.HasData)
        {
            DebugLogger.LogInfo("✅ Données API disponibles via GameDataManager", "GameConfigLoader");
            DebugLogger.LogInfo($"Background: {GameDataManager.Instance.CurrentGameData?.background?.url}", "GameConfigLoader");
            DebugLogger.LogInfo($"Questions: {GameDataManager.Instance.CurrentGameData?.questions?.Length ?? 0}", "GameConfigLoader");
            DebugLogger.LogInfo($"Phase actuelle: {phase}", "GameConfigLoader");
            
            // Gérer le flux avec les données API
            yield return StartCoroutine(ProcessApiGameData(phase));
            yield break;
        }
        
        DebugLogger.LogInfo("⚠️ Pas de données API - Chargement depuis le fichier local", "GameConfigLoader");

        DebugLogger.LogInfo($"URL: {configUrl}, Phase: {phase}", "GameConfigLoader");

        if (string.IsNullOrEmpty(configUrl))
        {
            DebugLogger.LogError("Aucune URL de config trouvée dans PlayerPrefs", "GameConfigLoader");
            yield break;
        }

        // Convertir STREAMING_ASSETS/ en chemin local file:///
        string fullConfigUrl = configUrl;
        if (configUrl.StartsWith("STREAMING_ASSETS/"))
        {
            string fileName = configUrl.Substring("STREAMING_ASSETS/".Length);
            string streamingAssetsPath = System.IO.Path.Combine(Application.streamingAssetsPath, fileName);
            streamingAssetsPath = streamingAssetsPath.Replace("\\", "/");
            
            #if UNITY_WEBGL && !UNITY_EDITOR
            // WebGL: éviter qu'une config de jeu reste servie depuis le cache navigateur/CDN
            string v = string.IsNullOrEmpty(Application.version) ? "0" : Application.version;
            fullConfigUrl = streamingAssetsPath + (streamingAssetsPath.Contains("?") ? "&" : "?") + "v=" + UnityWebRequest.EscapeURL(v);
            #else
            fullConfigUrl = "file:///" + streamingAssetsPath;
            #endif
            
            DebugLogger.LogInfo($"URL convertie: {fullConfigUrl}", "GameConfigLoader");
        }

        using (var www = UnityWebRequest.Get(fullConfigUrl))
        {
            yield return www.SendWebRequest();

            if (www.result != UnityWebRequest.Result.Success)
            {
                DebugLogger.LogError($"Erreur chargement config: {www.error}", "GameConfigLoader");
                DebugLogger.LogError($"URL utilisée: {fullConfigUrl}", "GameConfigLoader");
                yield break;
            }

            try
            {
                var wrapper = JsonUtility.FromJson<GameConfigWrapper>(www.downloadHandler.text);
                var config = wrapper.gameConfig;

                string questionsUrl = string.IsNullOrEmpty(config.questionsUrl) ? "" : 
                    GeneralConfigManager.Instance.GetQuestionsUrl(config.questionsUrl);
                PlayerPrefs.SetString("QuestionsUrl", questionsUrl);
                DebugLogger.LogInfo($"Questions URL: {questionsUrl}", "GameConfigLoader");

                // SYSTÈME : Dialogues groupés (fichier unique)
                if (!string.IsNullOrEmpty(config.dialoguesUrl))
                {
                    DebugLogger.LogInfo($"Chargement dialogues depuis: {config.dialoguesUrl}", "GameConfigLoader");
                    string dialoguesGroupedUrl = GeneralConfigManager.Instance.GetDialogueUrl(config.dialoguesUrl);
                    
                    // Convertir STREAMING_ASSETS/ en chemin local file:/// si nécessaire
                    if (dialoguesGroupedUrl.StartsWith("STREAMING_ASSETS/"))
                    {
                        string fileName = dialoguesGroupedUrl.Substring("STREAMING_ASSETS/".Length);
                        string streamingAssetsPath = System.IO.Path.Combine(Application.streamingAssetsPath, fileName);
                        streamingAssetsPath = streamingAssetsPath.Replace("\\", "/");
                        
                        #if UNITY_WEBGL && !UNITY_EDITOR
                        dialoguesGroupedUrl = streamingAssetsPath;
                        #else
                        dialoguesGroupedUrl = "file:///" + streamingAssetsPath;
                        #endif
                        
                        DebugLogger.LogInfo($"URL dialogue convertie: {dialoguesGroupedUrl}", "GameConfigLoader");
                    }
                    
                    switch (phase)
                    {
                        case "Before":
                            DebugLogger.LogInfo($"Phase Before - Chargement dialogue depuis: {dialoguesGroupedUrl}", "GameConfigLoader");
                            LaunchBeforeDialogueFromGrouped(dialoguesGroupedUrl);
                            break;
                        case "After":
                            DebugLogger.LogInfo($"Phase After - Chargement dialogue depuis: {dialoguesGroupedUrl}", "GameConfigLoader");
                            LaunchAfterDialogueFromGrouped(dialoguesGroupedUrl);
                            break;
                        case "Shooting":
                            DebugLogger.LogInfo("Phase Shooting - Ne rien faire, GameLauncher va gérer", "GameConfigLoader");
                            // Ne rien faire - GameLauncher va gérer la transition vers le jeu
                            break;
                    }
                }
                else
                {
                    DebugLogger.LogWarning("Aucun dialoguesUrl défini, passage direct au jeu", "GameConfigLoader");
                    // Pas de dialogue, passer directement au jeu
                    GoToGame();
                }
            }
            catch (Exception e)
            {
                DebugLogger.LogError($"Erreur parsing config: {e.Message}", "GameConfigLoader");
                DebugLogger.LogError($"Stack trace: {e.StackTrace}", "GameConfigLoader");
            }
        }
    }

    private void LaunchBeforeDialogueFromGrouped(string dialoguesGroupedUrl)
    {
        DebugLogger.LogInfo($"Chargement dialogue groupé: {dialoguesGroupedUrl}", "GameConfigLoader");
        
        // 🚀 NOUVEAU : Démarrer le préchargement des assets en parallèle du dialogue
        if (GameDataManager.Instance != null && GameDataManager.Instance.HasData)
        {
            if (!GameDataManager.Instance.AssetsPreloaded && !GameDataManager.Instance.IsPreloading)
            {
                DebugLogger.LogInfo("🚀 Démarrage du préchargement des assets pendant le dialogue", "GameConfigLoader");
                GameDataManager.Instance.PreloadGameAssets();
            }
        }
        
        // Timeout de sécurité : si le dialogue ne se charge pas en 5 secondes, passer au jeu
        StartCoroutine(TimeoutDialogueLoad(() =>
        {
            DebugLogger.LogWarning("Timeout dialogue - passage direct au jeu", "GameConfigLoader");
            GoToGame();
        }));
        
        StartCoroutine(LoadGroupedDialogueAndPlay(dialoguesGroupedUrl, "intro", () =>
        {
            DebugLogger.LogInfo("Dialogue intro terminé, passage au jeu", "GameConfigLoader");
            GoToGame();
        }));
    }
    
    private bool dialogueLoadCompleted = false;
    
    private IEnumerator TimeoutDialogueLoad(System.Action onTimeout)
    {
        dialogueLoadCompleted = false;
        yield return new WaitForSeconds(5f);
        
        if (!dialogueLoadCompleted)
        {
            DebugLogger.LogWarning("Timeout: le dialogue n'a pas été chargé dans les 5 secondes", "GameConfigLoader");
            onTimeout?.Invoke();
        }
    }
    
    private void LaunchAfterDialogueFromGrouped(string dialoguesGroupedUrl)
    {
        DebugLogger.LogInfo($"Chargement dialogue groupé: {dialoguesGroupedUrl}", "GameConfigLoader");
        
        string dialogueType = PlayerPrefs.GetString("LastGameResult", "fail"); // "success" ou "fail"
        
        StartCoroutine(LoadGroupedDialogueAndPlay(dialoguesGroupedUrl, dialogueType, () =>
        {
            DebugLogger.LogInfo("Dialogue après terminé, retour à la map", "GameConfigLoader");
            ReturnToMap();
        }));
    }
    
    private IEnumerator LoadGroupedDialogueAndPlay(string url, string dialogueType, System.Action onComplete)
    {
        // Convertir STREAMING_ASSETS/ en chemin local file:/// si nécessaire
        string fullUrl = url;
        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
            fullUrl = streamingAssetsPath;
            #else
            fullUrl = "file:///" + streamingAssetsPath;
            #endif
            
            DebugLogger.LogInfo($"URL dialogue convertie: {fullUrl}", "GameConfigLoader");
        }
        
        using (UnityWebRequest www = UnityWebRequest.Get(fullUrl))
        {
            yield return www.SendWebRequest();
            
            if (www.result != UnityWebRequest.Result.Success)
            {
                DebugLogger.LogError($"Erreur chargement dialogues groupés: {www.error}", "GameConfigLoader");
                DebugLogger.LogError($"URL utilisée: {fullUrl}", "GameConfigLoader");
                DebugLogger.LogWarning("Passage direct au jeu sans dialogue", "GameConfigLoader");
                dialogueLoadCompleted = true;
                onComplete?.Invoke();
                yield break;
            }
            
            try
            {
                DialoguesData dialoguesData = JsonUtility.FromJson<DialoguesData>(www.downloadHandler.text);
                DialogueContent dialogue = null;
                
                if (dialogueType == "intro" && dialoguesData.dialogues.intro != null)
                {
                    dialogue = dialoguesData.dialogues.intro;
                }
                else if (dialogueType == "success" && dialoguesData.dialogues.success != null)
                {
                    dialogue = dialoguesData.dialogues.success;
                }
                else if (dialogueType == "fail" && dialoguesData.dialogues.fail != null)
                {
                    dialogue = dialoguesData.dialogues.fail;
                }
                
                if (dialogue != null && dialogue.lines != null && dialogue.lines.Count > 0)
                {
                    DebugLogger.LogInfo($"Dialogue {dialogueType} trouvé avec {dialogue.lines.Count} lignes", "GameConfigLoader");
                    
                    // Créer le wrapper pour la sérialisation
                    var wrapper = new DialogueWrapperForJson { dialogue = dialogue };
                    string dialogueJson = JsonUtility.ToJson(wrapper);
                    
                    DebugLogger.LogInfo($"JSON généré ({dialogueJson.Length} caractères): {dialogueJson.Substring(0, Math.Min(200, dialogueJson.Length))}...", "GameConfigLoader");
                    
                    dialogueLoadCompleted = true;
                    ConfigureSubtitleManagerFromJson(dialogueJson, onComplete);
                }
                else
                {
                    DebugLogger.LogWarning($"Dialogue {dialogueType} non trouvé ou vide dans les dialogues groupés", "GameConfigLoader");
                    dialogueLoadCompleted = true;
                    onComplete?.Invoke();
                }
            }
            catch (Exception e)
            {
                DebugLogger.LogError($"Erreur parsing dialogues groupés: {e.Message}", "GameConfigLoader");
                dialogueLoadCompleted = true;
                onComplete?.Invoke();
            }
        }
    }

    private void GoToGame()
    {
        string levelType = PlayerPrefs.GetString("CurrentLevelType", "shooting");
        
        DebugLogger.LogInfo($"═══════════════════════════════════════", "GameConfigLoader");
        DebugLogger.LogInfo($"=== GO TO GAME ===", "GameConfigLoader");
        DebugLogger.LogInfo($"═══════════════════════════════════════", "GameConfigLoader");
        DebugLogger.LogInfo($"Level Type depuis PlayerPrefs: '{levelType}'", "GameConfigLoader");
        DebugLogger.LogInfo($"GameConfigUrl: '{PlayerPrefs.GetString("GameConfigUrl")}'", "GameConfigLoader");
        DebugLogger.LogInfo($"CurrentLevelId: '{PlayerPrefs.GetString("CurrentLevelId")}'", "GameConfigLoader");
        DebugLogger.LogInfo($"═══════════════════════════════════════", "GameConfigLoader");

        // Définir la phase pour le gameplay
        PlayerPrefs.SetString("GamePhase", "Shooting");
        PlayerPrefs.Save();
        
        // Charger directement la scène du jeu selon le type
        string sceneToLoad = "shooting"; // Par défaut
        
        if (levelType.ToLowerInvariant() == "calculator")
        {
            sceneToLoad = "calculator";
            DebugLogger.LogInfo("→ Chargement scène: calculator", "GameConfigLoader");
        }
        else if (levelType.ToLowerInvariant() == "trous")
        {
            sceneToLoad = "trous";
            DebugLogger.LogInfo("→ Chargement scène: trous", "GameConfigLoader");
        }
        else
        {
            DebugLogger.LogInfo("→ Chargement scène: shooting", "GameConfigLoader");
        }
        
        SceneManager.LoadScene(sceneToLoad);
    }

    private void ReturnToMap()
    {
        // Récupérer la scène d'origine (Menu ou Map)
        string returnToScene = PlayerPrefs.GetString("ReturnToScene", "menu");
        DebugLogger.LogInfo($"Retour à la scène: {returnToScene}", "GameConfigLoader");
        
        // Si on retourne à la Map, utiliser le LevelManager pour gérer le système de steps
        if (returnToScene.ToLower() == "map")
        {
            LevelManager levelManager = FindFirstObjectByType<LevelManager>();
            if (levelManager != null)
            {
                DebugLogger.LogInfo("Utilisation du LevelManager.ReturnToMap()", "GameConfigLoader");
                levelManager.ReturnToMap();
            }
            else
            {
                // Fallback : charger directement la scène Map
                DebugLogger.LogWarning("LevelManager non trouvé, chargement direct de la scène Map", "GameConfigLoader");
                string mapId = PlayerPrefs.GetString("CurrentMapId", GeneralConfigManager.Instance != null ? 
                    GeneralConfigManager.Instance.GetDefaultMapId() : "map-Q0");
                PlayerPrefs.SetString("CurrentMapId", mapId);
                SceneManager.LoadScene("Map");
            }
        }
        else
        {
            // Retour au menu ou autre scène
            DebugLogger.LogInfo($"Chargement de la scène: {returnToScene}", "GameConfigLoader");
            SceneManager.LoadScene(returnToScene);
        }
    }

    private void ConfigureSubtitleManagerFromJson(string dialogueJson, System.Action onComplete)
    {
        SubtitleManager subtitleManager = FindFirstObjectByType<SubtitleManager>();
        if (subtitleManager != null)
        {
            DebugLogger.LogInfo("SubtitleManager trouvé, chargement du dialogue", "GameConfigLoader");
            
            // Appliquer la configuration globale des dialogues depuis GeneralConfigManager (prioritaire)
            // puis LevelManager en fallback
            DialogueConfig configToApply = null;
            
            // Priorité 1 : GeneralConfigManager (general-config.json)
            if (GeneralConfigManager.Instance != null && GeneralConfigManager.Instance.IsConfigLoaded())
            {
                var defConfig = GeneralConfigManager.Instance.GetDefaultDialogueConfig();
                if (defConfig != null)
                {
                    configToApply = ConvertDefaultDialogueToConfig(defConfig);
                    DebugLogger.LogInfo($"Config dialogue chargée depuis GeneralConfigManager: useFrameMode={configToApply.useFrameMode}", "GameConfigLoader");
                }
            }
            
            // Priorité 2 : LevelManager (fallback)
            if (configToApply == null && LevelManager.Instance != null)
            {
                configToApply = LevelManager.Instance.GetDialogueConfig();
                if (configToApply != null)
                {
                    DebugLogger.LogInfo("Config dialogue chargée depuis LevelManager (fallback)", "GameConfigLoader");
                }
            }
            
            if (configToApply != null)
            {
                subtitleManager.ApplyDialogueConfig(configToApply);
            }
            else
            {
                DebugLogger.LogWarning("Aucune config dialogue trouvée, utilisation des valeurs par défaut", "GameConfigLoader");
                subtitleManager.ApplyDialogueConfig(null); // Laisse SubtitleManager charger depuis GeneralConfigManager
            }
            
            subtitleManager.OnDialogueComplete = onComplete;
            subtitleManager.LoadDialogueFromJson(dialogueJson);
        }
        else
        {
            DebugLogger.LogError("SubtitleManager non trouvé dans la scène Player - passage direct au jeu", "GameConfigLoader");
            dialogueLoadCompleted = true;
            onComplete?.Invoke();
        }
    }
    
    /// <summary>
    /// Convertit DefaultDialogueConfig en DialogueConfig
    /// </summary>
    private DialogueConfig ConvertDefaultDialogueToConfig(DefaultDialogueConfig def)
    {
        if (def == null) return null;
        
        return new DialogueConfig
        {
            // Paramètres de texte
            dialogueTextSize = def.dialogueTextSize > 0 ? def.dialogueTextSize : 28f,
            dialogueTextColor = !string.IsNullOrEmpty(def.dialogueTextColor) ? def.dialogueTextColor : "#4a4a4a",
            speakerTextSize = def.speakerTextSize > 0 ? def.speakerTextSize : 32f,
            speakerTextColor = !string.IsNullOrEmpty(def.speakerTextColor) ? def.speakerTextColor : "#64477f",
            speakerTextBold = def.speakerTextBold,
            speakerMarginBottom = def.speakerMarginBottom > 0 ? def.speakerMarginBottom : 15f,
            dialogueTextAlignment = !string.IsNullOrEmpty(def.dialogueTextAlignment) ? def.dialogueTextAlignment : "left",
            backgroundDimming = def.backgroundDimming,
            
            // Mode cadre centré
            useFrameMode = def.useFrameMode,
            frameWidth = def.frameWidth > 0 ? def.frameWidth : 1230f,
            frameHeight = def.frameHeight > 0 ? def.frameHeight : 340f,
            frameRadius = def.frameRadius > 0 ? def.frameRadius : 20f,
            frameBottomMargin = def.frameBottomMargin > 0 ? def.frameBottomMargin : 40f,
            frameBackgroundColor = !string.IsNullOrEmpty(def.frameBackgroundColor) ? def.frameBackgroundColor : "#f5ece5",
            framePaddingLeft = def.framePaddingLeft > 0 ? def.framePaddingLeft : 40f,
            framePaddingRight = def.framePaddingRight > 0 ? def.framePaddingRight : 40f,
            framePaddingTop = def.framePaddingTop > 0 ? def.framePaddingTop : 30f,
            framePaddingBottom = def.framePaddingBottom > 0 ? def.framePaddingBottom : 30f,
            
            // Padding intérieur du conteneur titre+sous-titre
            textContentPaddingLeft = def.textContentPaddingLeft,
            textContentPaddingRight = def.textContentPaddingRight,
            textContentPaddingTop = def.textContentPaddingTop,
            textContentPaddingBottom = def.textContentPaddingBottom,
            
            // Indicateur de continuation
            showContinueIndicator = def.showContinueIndicator,
            continueIndicatorColor = !string.IsNullOrEmpty(def.continueIndicatorColor) ? def.continueIndicatorColor : "#64477f",
            continueIndicatorSize = def.continueIndicatorSize > 0 ? def.continueIndicatorSize : 24f,
            continueIndicatorBottomMargin = def.continueIndicatorBottomMargin > 0 ? def.continueIndicatorBottomMargin : 20f,
            
            // Mode bandeau legacy
            bottomBarHeightRatio = def.bottomBarHeightRatio > 0 ? def.bottomBarHeightRatio : 0.32f,
            bottomBarColor = !string.IsNullOrEmpty(def.bottomBarColor) ? def.bottomBarColor : "#00000099",
            paddingLeft = def.paddingLeft,
            paddingRight = def.paddingRight,
            
            // Instructions
            instructionsText = !string.IsNullOrEmpty(def.instructionsText) ? def.instructionsText : "Cliquez pour continuer"
        };
    }
    
    // ========================================
    // NOUVEAU : Gestion des données API
    // ========================================
    
    private IEnumerator ProcessApiGameData(string phase)
    {
        DebugLogger.LogInfo($"═══════════════════════════════════════", "GameConfigLoader");
        DebugLogger.LogInfo($"🎮 TRAITEMENT DONNÉES API - Phase: {phase}", "GameConfigLoader");
        DebugLogger.LogInfo($"═══════════════════════════════════════", "GameConfigLoader");
        
        APIGameData gameData = GameDataManager.Instance.CurrentGameData;
        
        if (gameData == null)
        {
            DebugLogger.LogError("❌ CurrentGameData est null malgré HasData=true !", "GameConfigLoader");
            yield break;
        }
        
        // Log des données disponibles
        DebugLogger.LogInfo($"📊 Background: {gameData.background?.type} - {gameData.background?.url}", "GameConfigLoader");
        DebugLogger.LogInfo($"📊 Questions: {gameData.questions?.Length ?? 0}", "GameConfigLoader");
        DebugLogger.LogInfo($"📊 Zones: {gameData.zones?.Length ?? 0}", "GameConfigLoader");
        DebugLogger.LogInfo($"📊 Dialogues disponibles:", "GameConfigLoader");
        DebugLogger.LogInfo($"   - Intro: {(gameData.dialogues?.intro != null ? "✅" : "❌")}", "GameConfigLoader");
        DebugLogger.LogInfo($"   - Success: {(gameData.dialogues?.success != null ? "✅" : "❌")}", "GameConfigLoader");
        DebugLogger.LogInfo($"   - Fail: {(gameData.dialogues?.fail != null ? "✅" : "❌")}", "GameConfigLoader");
        
        switch (phase)
        {
            case "Before":
                // 🚀 NOUVEAU : Démarrer le préchargement des assets en parallèle du dialogue
                // Les assets seront téléchargés pendant que l'utilisateur lit les sous-titres
                if (!GameDataManager.Instance.AssetsPreloaded && !GameDataManager.Instance.IsPreloading)
                {
                    DebugLogger.LogInfo("🚀 Démarrage du préchargement des assets pendant le dialogue", "GameConfigLoader");
                    GameDataManager.Instance.PreloadGameAssets();
                }
                
                // Lancer le dialogue d'intro
                if (gameData.dialogues?.intro != null)
                {
                    DebugLogger.LogInfo("▶️ Lancement dialogue INTRO", "GameConfigLoader");
                    yield return StartCoroutine(PlayApiDialogue(gameData.dialogues.intro, () => {
                        DebugLogger.LogInfo("✅ Dialogue intro terminé, passage au jeu", "GameConfigLoader");
                        GoToGame();
                    }));
                }
                else
                {
                    DebugLogger.LogWarning("⚠️ Pas de dialogue intro, passage direct au jeu", "GameConfigLoader");
                    GoToGame();
                }
                break;
                
            case "Shooting":
                // Aller directement au jeu (les questions sont dans GameDataManager)
                DebugLogger.LogInfo("▶️ Phase Shooting - Passage direct au jeu", "GameConfigLoader");
                GoToGame();
                break;
                
            case "After":
                // Déterminer si succès ou échec
                string lastGameResult = PlayerPrefs.GetString("LastGameResult", "fail");
                bool isSuccess = (lastGameResult == "success");
                DebugLogger.LogInfo($"▶️ Phase After - Résultat: {(isSuccess ? "SUCCÈS" : "ÉCHEC")} (LastGameResult: {lastGameResult})", "GameConfigLoader");
                
                APIDialogueContent afterDialogue = isSuccess ? gameData.dialogues?.success : gameData.dialogues?.fail;
                
                if (afterDialogue != null)
                {
                    yield return StartCoroutine(PlayApiDialogue(afterDialogue, () => {
                        DebugLogger.LogInfo("✅ Dialogue after terminé, retour à la map", "GameConfigLoader");
                        ReturnToMap();
                    }));
                }
                else
                {
                    DebugLogger.LogWarning("⚠️ Pas de dialogue after, retour direct à la map", "GameConfigLoader");
                    ReturnToMap();
                }
                break;
                
            default:
                DebugLogger.LogError($"❌ Phase inconnue: {phase}", "GameConfigLoader");
                break;
        }
    }
    
    /// <summary>
    /// Joue un dialogue depuis les données API
    /// </summary>
    private IEnumerator PlayApiDialogue(APIDialogueContent dialogueContent, System.Action onComplete)
    {
        if (dialogueContent == null)
        {
            DebugLogger.LogWarning("Dialogue content est null", "GameConfigLoader");
            onComplete?.Invoke();
            yield break;
        }
        
        DebugLogger.LogInfo($"🎬 Lecture dialogue: {dialogueContent.title}", "GameConfigLoader");
        DebugLogger.LogInfo($"   Video: {dialogueContent.video}", "GameConfigLoader");
        DebugLogger.LogInfo($"   Lignes: {dialogueContent.lines?.Length ?? 0}", "GameConfigLoader");
        
        // Convertir le dialogue API en JSON pour SubtitleManager
        string dialogueJson = ConvertApiDialogueToJson(dialogueContent);
        
        DebugLogger.LogInfo($"📋 JSON dialogue généré ({dialogueJson.Length} caractères)", "GameConfigLoader");
        
        // Utiliser le système existant de SubtitleManager
        dialogueLoadCompleted = false;
        
        ConfigureSubtitleManagerFromJson(dialogueJson, () => {
            dialogueLoadCompleted = true;
            onComplete?.Invoke();
        });
        
        // Attendre que le dialogue soit terminé
        while (!dialogueLoadCompleted)
        {
            yield return null;
        }
    }
    
    /// <summary>
    /// Convertit un dialogue API en JSON compatible avec SubtitleManager
    /// </summary>
    private string ConvertApiDialogueToJson(APIDialogueContent dialogueContent)
    {
        // Structure attendue par SubtitleManager:
        // { "dialogue": { "title": "...", "speaker": "...", "video": "...", "lines": [{ "text": "...", "image": "..." }] } }
        
        var wrapper = new DialogueWrapperForJson();
        wrapper.dialogue = new DialogueContent();
        wrapper.dialogue.title = dialogueContent.title ?? "";
        // Utiliser "title" comme "speaker" (affiché en haut de l'écran)
        wrapper.dialogue.speaker = dialogueContent.title ?? "";
        wrapper.dialogue.video = dialogueContent.video ?? "";
        
        if (dialogueContent.lines != null)
        {
            foreach (var line in dialogueContent.lines)
            {
                wrapper.dialogue.lines.Add(new DialogueLine
                {
                    text = line.text ?? "",
                    image = line.image ?? ""
                });
            }
        }
        
        return JsonUtility.ToJson(wrapper);
    }
}