using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine.InputSystem;
using TMPro;

// Force recompile - 2024-11-15 15:45
public class MainSceneManager : MonoBehaviour
{
    [Header("Configuration")]
    public string configUrl = "STREAMING_ASSETS/json/main-config.json";

    [Header("Debug")]
    public bool showDebugSprites = false;

    private MainSceneConfig sceneConfig;
    private GameObject backgroundObject;
    private List<GameObject> mapEntrySprites = new List<GameObject>();
    private Canvas canvas;
    private GameObject tooltipPanel;
    private TMPro.TextMeshProUGUI tooltipText;
    
    // Variables pour détecter les clics manuellement (WebGL fix)
    private bool wasMouseDownLastFrame = false;
    
    // Variables pour détecter le survol manuellement (WebGL fix)
    private GameObject currentHoveredIcon = null;
    
    // Popup d'identification
    private LoginPopup loginPopup;

    void Awake()
    {
        // NETTOYAGE IMMÉDIAT : Supprimer tous les StandaloneInputModule AVANT même de commencer
        // Cela évite les exceptions qui se produisent pendant le chargement
        CleanupStandaloneInputModules();
    }

    void Start()
    {
        Debug.Log("🔴🔴🔴 TEST BUILD WEBGL - SI VOUS VOYEZ CECI, LE BUILD EST À JOUR ! 🔴🔴🔴");
        
        // Afficher les informations utilisateur stockées au démarrage
        if (UserDataManager.Instance != null)
        {
            UserDataManager.Instance.LogUserData();
        }
        
        StartCoroutine(InitializeMainScene());
        
        // Afficher le panneau d'identification si l'utilisateur n'est pas connecté
        StartCoroutine(CheckLoginStatusAndShowPopup());
    }
    
    /// <summary>
    /// Vérifie le statut de connexion et affiche le panneau d'identification si nécessaire
    /// </summary>
    private System.Collections.IEnumerator CheckLoginStatusAndShowPopup()
    {
        Debug.Log("[MainSceneManager] ⏳ CheckLoginStatusAndShowPopup - Début");
        
        // Attendre quelques frames pour que UserDataManager ait chargé les PlayerPrefs
        yield return new WaitForSeconds(0.5f);
        
        Debug.Log($"[MainSceneManager] UserDataManager.Instance: {(UserDataManager.Instance != null ? "OK" : "NULL")}");
        
        if (UserDataManager.Instance != null)
        {
            bool isLoggedIn = UserDataManager.Instance.IsLoggedIn();
            Debug.Log($"[MainSceneManager] IsLoggedIn: {isLoggedIn}");
            
            if (!isLoggedIn)
            {
                Debug.Log("[MainSceneManager] ⚠️ Utilisateur NON connecté - Affichage automatique du panneau d'identification");
                ShowLoginPopup();
            }
            else
            {
                Debug.Log("[MainSceneManager] ✅ Utilisateur DÉJÀ connecté - Pas besoin d'afficher le panneau d'identification");
            }
        }
        else
        {
            Debug.LogError("[MainSceneManager] ❌ UserDataManager.Instance est NULL !");
        }
    }
    
    void CleanupStandaloneInputModules()
    {
        EnsureEventSystemsAreReady();
    }

    void EnsureEventSystemsAreReady()
    {
        var eventSystems = FindObjectsByType<UnityEngine.EventSystems.EventSystem>(FindObjectsSortMode.None);

        if (eventSystems == null || eventSystems.Length == 0)
        {
            GameObject esObj = new GameObject("EventSystem");
            var newEventSystem = esObj.AddComponent<UnityEngine.EventSystems.EventSystem>();
#if ENABLE_INPUT_SYSTEM
            esObj.AddComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
#endif
            eventSystems = new[] { newEventSystem };
            Debug.Log("[MainSceneManager] ✅ Aucun EventSystem détecté - création d'un nouveau");
        }

        foreach (var es in eventSystems)
        {
            if (es == null) continue;

            var standaloneModules = es.GetComponents<UnityEngine.EventSystems.StandaloneInputModule>();
            foreach (var module in standaloneModules)
            {
                if (module == null) continue;
#if UNITY_EDITOR
                DestroyImmediate(module);
#else
                Destroy(module);
#endif
                Debug.Log($"[MainSceneManager] ⚠️ StandaloneInputModule supprimé sur '{es.gameObject.name}'");
            }

#if ENABLE_INPUT_SYSTEM
            var inputModule = es.GetComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
            if (inputModule == null)
            {
                inputModule = es.gameObject.AddComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
                Debug.Log($"[MainSceneManager] ✅ InputSystemUIInputModule ajouté sur '{es.gameObject.name}'");
            }
            else if (!inputModule.enabled)
            {
                inputModule.enabled = true;
            }
#endif

            if (!es.enabled) es.enabled = true;
            if (!es.gameObject.activeInHierarchy) es.gameObject.SetActive(true);
        }
    }

    IEnumerator InitializeMainScene()
    {
        // Nettoyer les objets existants si on revient à la scène
        CleanupExistingObjects();

        // IMPORTANT : Ne PAS détruire les EventSystem - ils sont nécessaires pour les EventTrigger
        // Supprimer tous les StandaloneInputModule (incompatibles avec le nouveau Input System)
        // Utiliser InputSystemUIInputModule à la place
        UnityEngine.EventSystems.EventSystem[] eventSystems = FindObjectsByType<UnityEngine.EventSystems.EventSystem>(FindObjectsSortMode.None);
        foreach (var es in eventSystems)
        {
            if (es != null)
            {
                // Supprimer tous les StandaloneInputModule (causent des exceptions avec le nouveau Input System)
                var standaloneModules = es.GetComponents<UnityEngine.EventSystems.StandaloneInputModule>();
                foreach (var module in standaloneModules)
                {
                    if (module != null)
                    {
                        module.enabled = false;
                        Destroy(module);
                    }
                }
                
                // S'assurer qu'il y a un InputSystemUIInputModule (compatible avec le nouveau Input System)
                if (es.GetComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>() == null)
                {
                    es.gameObject.AddComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
                }
            }
        }
        
        // Supprimer les StandaloneInputModule orphelins
        UnityEngine.EventSystems.StandaloneInputModule[] orphanStandaloneModules = FindObjectsByType<UnityEngine.EventSystems.StandaloneInputModule>(FindObjectsSortMode.None);
        foreach (var module in orphanStandaloneModules)
        {
            if (module != null)
            {
                module.enabled = false;
                Destroy(module.gameObject);
            }
        }

        // Créer GeneralConfigManager s'il n'existe pas
        if (GeneralConfigManager.Instance == null)
        {
            GameObject configManagerObj = new GameObject("GeneralConfigManager");
            configManagerObj.AddComponent<GeneralConfigManager>();
        }

        // Attendre que GeneralConfigManager soit initialisé et chargé
        while (GeneralConfigManager.Instance == null || !GeneralConfigManager.Instance.IsConfigLoaded())
        {
            yield return null;
        }
        
        // S'assurer qu'au moins un EventSystem actif est présent pour toutes les interactions UI (scroll, clic, etc.)
        EnsureEventSystemsAreReady();
        
        Debug.Log("[MainSceneManager] ✅ EventSystem actif et configuré pour le nouveau Input System");

        // Afficher l'écran de chargement
        if (UnifiedLoadingManager.Instance != null)
        {
            UnifiedLoadingManager.ShowLoading("Chargement de la scène principale...", LoadingContext.Menu);
        }

        yield return StartCoroutine(LoadConfiguration());
    }

    IEnumerator LoadConfiguration()
    {
        Debug.Log("[MainSceneManager] 🔍 Début du chargement de la configuration...");
        
        // Vérifier que GeneralConfigManager est disponible
        if (GeneralConfigManager.Instance == null)
        {
            Debug.LogError("[MainSceneManager] ❌ GeneralConfigManager.Instance est null");
            yield return StartCoroutine(LoadConfigurationFromFile());
            yield break;
        }

        // Construire l'URL de l'API
        string apiUrl = GeneralConfigManager.Instance.GetMainSceneConfigApiUrl();
        
        Debug.Log($"[MainSceneManager] 🔍 URL API construite: '{apiUrl}'");
        
        if (string.IsNullOrEmpty(apiUrl))
        {
            Debug.LogError("[MainSceneManager] ❌ Impossible de construire l'URL de l'API - Vérifiez general-config.json");
            Debug.LogError("[MainSceneManager] Vérifiez que 'slug' est défini dans general-config.json");
            Debug.LogError("[MainSceneManager] Vérifiez que 'apiUrls.baseUrl' est défini dans general-config.json");
            // Fallback vers le fichier local si l'API n'est pas configurée
            yield return StartCoroutine(LoadConfigurationFromFile());
            yield break;
        }

        Debug.Log($"[MainSceneManager] 🌐 Appel API: {apiUrl}");

        // Vérifier si l'utilisateur est connecté pour ajouter le token
        bool isLoggedIn = UserDataManager.Instance != null && !string.IsNullOrEmpty(UserDataManager.Instance?.token);
        string token = isLoggedIn ? UserDataManager.Instance.token : null;

        if (isLoggedIn)
        {
            Debug.Log($"[MainSceneManager] ✅ Token trouvé (longueur: {token.Length} caractères)");
        }
        else
        {
            Debug.Log("[MainSceneManager] ⚠️ Utilisateur non connecté - Chargement depuis l'API sans authentification");
        }

        using (UnityWebRequest www = UnityWebRequest.Get(apiUrl))
        {
            // User-Agent requis pour éviter les blocages par Varnish/CloudFlare
            www.SetRequestHeader("User-Agent", $"Unity/{Application.unityVersion} UJSA-Game");
            www.SetRequestHeader("Accept", "application/json");
            
            // Ajouter l'authentification Bearer Token seulement si l'utilisateur est connecté
            if (isLoggedIn && !string.IsNullOrEmpty(token))
            {
                www.SetRequestHeader("Authorization", $"Bearer {token}");
            }
            
            // NOTE: Les headers Cache-Control, Pragma, Expires causent des problèmes CORS
            // Le serveur ne les autorise pas dans Access-Control-Allow-Headers
            // On les retire pour éviter les erreurs CORS en WebGL

            yield return www.SendWebRequest();

            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"[MainSceneManager] ❌ Erreur de chargement de la configuration depuis l'API : {www.error}");
                Debug.LogError($"URL utilisée : {apiUrl}");
                Debug.LogError($"Code de réponse : {www.responseCode}");
                if (!string.IsNullOrEmpty(www.downloadHandler?.text))
                {
                    Debug.LogError($"Réponse serveur : {www.downloadHandler.text}");
                }
                // Fallback vers le fichier local en cas d'erreur API
                Debug.LogWarning("[MainSceneManager] ⚠️ Fallback vers le fichier local main-config.json");
                yield return StartCoroutine(LoadConfigurationFromFile());
                yield break;
            }

            // Parser la réponse de l'API (en dehors du try-catch pour éviter les problèmes avec yield)
            string jsonData = www.downloadHandler.text;
            bool parseSuccess = false;
            
            if (!string.IsNullOrEmpty(jsonData))
            {
                Debug.Log($"[MainSceneManager] ✅ Configuration reçue depuis l'API ({jsonData.Length} caractères)");
                Debug.Log($"[MainSceneManager] 🔍 Début de la réponse: {jsonData.Substring(0, Mathf.Min(500, jsonData.Length))}...");

                // Parser la réponse de l'API
                // Format API: {"status": "success", "message": "...", "data": {...}}
                // Format fichier local: {"mainSceneConfig": {...}}
                ApiMainSceneResponse apiResponse = null;
                MainSceneConfigWrapper fileWrapper = null;
                
                try
                {
                    // Essayer d'abord le format API
                    apiResponse = JsonUtility.FromJson<ApiMainSceneResponse>(jsonData);
                    if (apiResponse != null && apiResponse.data != null && apiResponse.status == "success")
                    {
                        // Convertir le format API vers le format interne
                        sceneConfig = ConvertApiResponseToConfig(apiResponse);
                        if (sceneConfig != null)
                        {
                            Debug.Log("[MainSceneManager] ✅ Configuration parsée depuis l'API (format API)");
                            Debug.Log($"[MainSceneManager] 🔍 Background config: type={sceneConfig.background?.type}, url={sceneConfig.background?.url}");
                            Debug.Log($"[MainSceneManager] 🔍 Map entries count: {sceneConfig.mapEntries?.Count ?? 0}");
                            parseSuccess = true;
                        }
                    }
                    else
                    {
                        // Essayer le format fichier local (fallback)
                        fileWrapper = JsonUtility.FromJson<MainSceneConfigWrapper>(jsonData);
                        if (fileWrapper != null && fileWrapper.mainSceneConfig != null)
                        {
                            sceneConfig = fileWrapper.mainSceneConfig;
                            Debug.Log("[MainSceneManager] ✅ Configuration parsée avec wrapper (format fichier local)");
                            Debug.Log($"[MainSceneManager] 🔍 Background config: type={sceneConfig.background?.type}, url={sceneConfig.background?.url}");
                            Debug.Log($"[MainSceneManager] 🔍 Map entries count: {sceneConfig.mapEntries?.Count ?? 0}");
                            parseSuccess = true;
                        }
                    }
                }
                catch (System.Exception e)
                {
                    Debug.LogError($"[MainSceneManager] ❌ Erreur lors du parsing de la réponse API : {e.Message}");
                    Debug.LogError($"[MainSceneManager] Stack trace: {e.StackTrace}");
                }
                
                if (!parseSuccess)
                {
                    Debug.LogError("[MainSceneManager] ❌ Structure de réponse invalide depuis l'API");
                    Debug.LogError($"[MainSceneManager] Réponse complète: {jsonData}");
                }
            }
            else
            {
                Debug.LogError("[MainSceneManager] ❌ Réponse API vide");
            }

            // Si le parsing a échoué, fallback vers le fichier local
            if (!parseSuccess)
            {
                Debug.LogWarning("[MainSceneManager] ⚠️ Fallback vers le fichier local main-config.json");
                yield return StartCoroutine(LoadConfigurationFromFile());
                yield break;
            }

            // Vérifier que sceneConfig est bien défini avant de continuer
            if (sceneConfig == null)
            {
                Debug.LogError("[MainSceneManager] ❌ sceneConfig est null après parsing - Fallback vers fichier local");
                yield return StartCoroutine(LoadConfigurationFromFile());
                yield break;
            }

            // Vérifier que background est défini
            if (sceneConfig.background == null)
            {
                Debug.LogError("[MainSceneManager] ❌ sceneConfig.background est null après parsing - Fallback vers fichier local");
                Debug.LogError($"[MainSceneManager] Structure sceneConfig: mapEntries count = {sceneConfig.mapEntries?.Count ?? 0}");
                yield return StartCoroutine(LoadConfigurationFromFile());
                yield break;
            }
        }

        // Continuer avec le reste du chargement (création du canvas, etc.)
        yield return StartCoroutine(ContinueAfterConfigLoaded());
    }

    /// <summary>
    /// Convertit la réponse API vers le format interne MainSceneConfig
    /// </summary>
    private MainSceneConfig ConvertApiResponseToConfig(ApiMainSceneResponse apiResponse)
    {
        if (apiResponse == null || apiResponse.data == null)
        {
            Debug.LogError("[MainSceneManager] ❌ Réponse API invalide (data null)");
            return null;
        }

        MainSceneConfig config = new MainSceneConfig();

        // Convertir le background
        if (apiResponse.data.background != null)
        {
            config.background = new MainSceneBackgroundConfig
            {
                type = apiResponse.data.background.type,
                url = apiResponse.data.background.url
            };
            Debug.Log($"[MainSceneManager] ✅ Background converti: type={config.background.type}, url={config.background.url}");
        }
        else
        {
            Debug.LogError("[MainSceneManager] ❌ Background manquant dans la réponse API");
            return null;
        }

        // Convertir les quests en mapEntries
        config.mapEntries = new List<MainSceneMapEntry>();
        
        if (apiResponse.data.quests != null && apiResponse.data.quests.Count > 0)
        {
            // TEMPORAIRE: Détecter si toutes les quêtes ont la même position
            // Si c'est le cas, appliquer un offset automatique pour les espacer
            bool allSamePosition = true;
            float firstX = apiResponse.data.quests[0].sprite_position?.x ?? 0;
            float firstY = apiResponse.data.quests[0].sprite_position?.y ?? 0;
            
            foreach (var q in apiResponse.data.quests)
            {
                if (q.sprite_position?.x != firstX || q.sprite_position?.y != firstY)
                {
                    allSamePosition = false;
                    break;
                }
            }
            
            // Si toutes les quêtes ont la même position, un espacement automatique sera appliqué
            float horizontalSpacing = 450f; // Espacement horizontal entre les quêtes
            
            for (int i = 0; i < apiResponse.data.quests.Count; i++)
            {
                var quest = apiResponse.data.quests[i];
                
                // Générer le mapId depuis l'index dans la liste (pas depuis quest.id)
                // Format attendu: "map-Q0", "map-Q1", etc.
                // Utiliser l'index dans la liste car les IDs de l'API peuvent être 38, 39, 40, etc.
                string mapId = $"map-Q{i}";
                
                // TEMPORAIRE: Si toutes les positions sont identiques, appliquer un offset
                Vector2Data adjustedPosition = quest.sprite_position;
                if (allSamePosition && apiResponse.data.quests.Count > 1)
                {
                    adjustedPosition = new Vector2Data
                    {
                        x = quest.sprite_position.x + (i * horizontalSpacing),
                        y = quest.sprite_position.y
                    };
                    Debug.Log($"[MainSceneManager] 📍 Quest {quest.id} (index {i}): position ajustée de ({quest.sprite_position.x}, {quest.sprite_position.y}) à ({adjustedPosition.x}, {adjustedPosition.y})");
                }
                
                MainSceneMapEntry entry = new MainSceneMapEntry
                {
                    id = $"map_q{i}", // Format: "map_q0", "map_q1", etc.
                    mapId = mapId, // Format: "map-Q0", "map-Q1", etc.
                    questId = quest.id, // ID original de la quest depuis l'API (peut être 38, 39, 40, etc.)
                    spriteUrl = quest.sprite_url,
                    position = adjustedPosition, // Position ajustée si nécessaire
                    size = quest.sprite_size, // Vector2Data est compatible
                    tooltipText = quest.tooltip_text,
                    sortingOrder = 10, // Valeur par défaut
                    has_access = quest.has_access, // Copier has_access depuis l'API
                    status = quest.status // Copier status depuis l'API
                };
                
                config.mapEntries.Add(entry);
                Debug.Log($"[MainSceneManager] ✅ Quest {quest.id} (index {i}) converti en mapEntry: id={entry.id}, mapId={entry.mapId}, questId={entry.questId}, has_access={entry.has_access}, status={entry.status ?? "null"}");
            }
            
            Debug.Log($"[MainSceneManager] ✅ {config.mapEntries.Count} mapEntries créés depuis les quests");
            
            // Stocker aussi les données complètes des quêtes pour le panel de prévisualisation
            config.quests = new List<Quest>();
            foreach (var apiQuest in apiResponse.data.quests)
            {
                Quest quest = new Quest
                {
                    id = apiQuest.id,
                    title = apiQuest.title,
                    description = apiQuest.description,
                    trailer_url = apiQuest.trailer_url,
                    duration = apiQuest.duration,
                    visibility = apiQuest.visibility,
                    status = apiQuest.status, // Copier status depuis l'API
                    has_access = apiQuest.has_access,
                    sprite_url = apiQuest.sprite_url,
                    sprite_position = apiQuest.sprite_position,
                    sprite_size = apiQuest.sprite_size,
                    tooltip_text = apiQuest.tooltip_text,
                    trainings = new List<Training>()
                };
                
                // Convertir les trainings
                if (apiQuest.trainings != null)
                {
                    foreach (var apiTraining in apiQuest.trainings)
                    {
                        quest.trainings.Add(new Training
                        {
                            title = apiTraining.title,
                            url = apiTraining.url
                        });
                    }
                }
                
                // Copier la progression utilisateur
                if (apiQuest.user != null)
                {
                    quest.user = new List<QuestUserProgress>();
                    foreach (var userProgress in apiQuest.user)
                    {
                        quest.user.Add(new QuestUserProgress
                        {
                            difficulty = userProgress.difficulty,
                            completion = userProgress.completion,
                            score = userProgress.score,
                            badge = userProgress.badge,
                            last_completed_game = userProgress.last_completed_game // IMPORTANT: pour reprendre au bon step
                        });
                    }
                    Debug.Log($"[MainSceneManager] 📊 Quest {quest.id}: {quest.user.Count} entrées de progression utilisateur copiées");
                }
                
                config.quests.Add(quest);
            }
            
            Debug.Log($"[MainSceneManager] ✅ {config.quests.Count} quêtes complètes stockées pour le panel de prévisualisation");
        }
        else
        {
            Debug.LogWarning("[MainSceneManager] ⚠️ Aucune quest dans la réponse API");
        }

        return config;
    }

    /// <summary>
    /// Charge la configuration depuis le fichier local (fallback)
    /// </summary>
    IEnumerator LoadConfigurationFromFile()
    {
        // Construire l'URL complète
        string fullUrl = GeneralConfigManager.Instance != null
            ? GeneralConfigManager.Instance.GetMapConfigUrl("main-config.json")
            : configUrl;

        // Remplacer STREAMING_ASSETS par le chemin réel
        if (fullUrl.StartsWith("STREAMING_ASSETS/"))
        {
            string fileName = fullUrl.Replace("STREAMING_ASSETS/", "");
            string streamingAssetsPath = System.IO.Path.Combine(Application.streamingAssetsPath, fileName);

#if UNITY_WEBGL && !UNITY_EDITOR
            fullUrl = streamingAssetsPath;
#else
            fullUrl = "file:///" + streamingAssetsPath.Replace("\\", "/");
#endif
        }

        Debug.Log($"[MainSceneManager] Chargement config depuis fichier local: {fullUrl}");

        using (UnityWebRequest www = UnityWebRequest.Get(fullUrl))
        {
            www.SetRequestHeader("Cache-Control", "no-cache");
            yield return www.SendWebRequest();

            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"[MainSceneManager] Erreur chargement config: {www.error}");
                yield break;
            }

            string json = www.downloadHandler.text;
            MainSceneConfigWrapper wrapper = JsonUtility.FromJson<MainSceneConfigWrapper>(json);
            sceneConfig = wrapper.mainSceneConfig;
        }

        // Continuer avec le reste du chargement
        yield return StartCoroutine(ContinueAfterConfigLoaded());
    }

    /// <summary>
    /// Continue le processus de chargement après que la configuration soit chargée
    /// </summary>
    IEnumerator ContinueAfterConfigLoaded()
    {
        // Détruire tous les canvas de la scène (sauf les persistants)
        Canvas[] allCanvases = FindObjectsByType<Canvas>(FindObjectsSortMode.None);
        foreach (Canvas existingCanvas in allCanvases)
        {
            if (existingCanvas != null && existingCanvas.gameObject != null)
            {
                bool isPersistent = existingCanvas.gameObject.scene.name == "DontDestroyOnLoad";
                bool isLoading = existingCanvas.name.Contains("Loading") || 
                                existingCanvas.GetComponentInParent<LoadingScreenManager>() != null || 
                                existingCanvas.GetComponentInParent<UnifiedLoadingManager>() != null;
                
                if (!isPersistent && !isLoading)
                {
                    DestroyImmediate(existingCanvas.gameObject);
                }
            }
        }
        
        // Créer un nouveau canvas propre
        GameObject canvasObj = new GameObject("MainCanvas");
        canvas = canvasObj.AddComponent<Canvas>();
        canvas.renderMode = RenderMode.ScreenSpaceOverlay;
        canvas.sortingOrder = 0;
        CanvasScaler scaler = canvasObj.AddComponent<CanvasScaler>();
        scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
        scaler.referenceResolution = new Vector2(1920, 1080);

        // Charger le background
        yield return StartCoroutine(SetupBackground());

        // Créer le header
        yield return StartCoroutine(CreateHeader());

        // Créer les sprites d'entrée de map
        yield return StartCoroutine(CreateMapEntries());

        // Vérifier que les icônes sont visibles
        int invisibleCount = 0;
        foreach (GameObject sprite in mapEntrySprites)
        {
            if (sprite != null)
            {
                Image img = sprite.GetComponent<Image>();
                bool visible = sprite.activeInHierarchy && img != null && img.enabled && img.sprite != null && img.color.a > 0;
                
                if (!visible)
                {
                    invisibleCount++;
                    Debug.LogError($"[MainSceneManager] Icône invisible: {sprite.name}");
                }
            }
            else
            {
                Debug.LogError($"[MainSceneManager] Icône NULL dans la liste!");
            }
        }
        
        if (invisibleCount == 0 && mapEntrySprites.Count > 0)
        {
            Debug.Log($"[MainSceneManager] ✅ {mapEntrySprites.Count} icônes créées et visibles");
        }

        // Masquer l'écran de chargement
        if (UnifiedLoadingManager.Instance != null)
        {
            UnifiedLoadingManager.HideLoadingAfterDelay(0.5f);
        }

        // Si on arrive depuis Options/QUÊTES avec une demande d'ouverture de preview, l'appliquer maintenant
        StartCoroutine(TryOpenPendingQuestPreviewAfterInit());
    }

    private const string PendingQuestPreviewMapIdKey = "PendingQuestPreviewMapId";
    private const string PendingQuestPreviewQuestIdKey = "PendingQuestPreviewQuestId";
    private bool pendingQuestPreviewOpened = false;

    private IEnumerator TryOpenPendingQuestPreviewAfterInit()
    {
        Debug.Log("[MainSceneManager] 🎮 JOUER: === TryOpenPendingQuestPreviewAfterInit APPELÉ ===");
        
        if (pendingQuestPreviewOpened)
        {
            Debug.Log("[MainSceneManager] 🎮 JOUER: ⚠️ Déjà ouvert, abort");
            yield break;
        }

        string mapId = PlayerPrefs.GetString(PendingQuestPreviewMapIdKey, "");
        int questId = PlayerPrefs.GetInt(PendingQuestPreviewQuestIdKey, 0);
        
        Debug.Log($"[MainSceneManager] 🎮 JOUER: PlayerPrefs lus - mapId='{mapId}', questId={questId}");
        
        if (string.IsNullOrEmpty(mapId) || questId <= 0)
        {
            Debug.Log($"[MainSceneManager] 🎮 JOUER: ⚠️ Pas de quête en attente - mapId vide={string.IsNullOrEmpty(mapId)}, questId<=0={questId <= 0}");
            yield break;
        }

        // Attendre que tout soit bien actif (canvas, header, etc.)
        yield return null;
        yield return new WaitForEndOfFrame();

        Debug.Log($"[MainSceneManager] 🎮 JOUER: 🎯 Ouverture du preview - mapId={mapId}, questId={questId}");
        yield return StartCoroutine(LoadQuestDataAndShowPanel(mapId, questId));

        // Marquer comme ouvert + nettoyer une fois tenté (évite répétition)
        pendingQuestPreviewOpened = true;
        PlayerPrefs.DeleteKey(PendingQuestPreviewMapIdKey);
        PlayerPrefs.DeleteKey(PendingQuestPreviewQuestIdKey);
        PlayerPrefs.Save();
        
        Debug.Log("[MainSceneManager] 🎮 JOUER: ✅ Preview ouvert et PlayerPrefs nettoyés");
    }

    IEnumerator SetupBackground()
    {
        if (sceneConfig == null)
        {
            Debug.LogError("[MainSceneManager] ❌ Configuration de background manquante - sceneConfig est null");
            yield break;
        }

        if (sceneConfig.background == null)
        {
            Debug.LogError("[MainSceneManager] ❌ Configuration de background manquante - sceneConfig.background est null");
            Debug.LogError($"[MainSceneManager] 🔍 sceneConfig.mapEntries count: {sceneConfig.mapEntries?.Count ?? 0}");
            Debug.LogError($"[MainSceneManager] 🔍 Type de sceneConfig: {sceneConfig.GetType().Name}");
            yield break;
        }

        // Créer le conteneur du background
        backgroundObject = new GameObject("Background");
        backgroundObject.transform.SetParent(canvas.transform, false);
        backgroundObject.transform.SetAsFirstSibling();
        backgroundObject.SetActive(true); // S'assurer que le background est actif

        RectTransform bgRect = backgroundObject.AddComponent<RectTransform>();
        bgRect.anchorMin = Vector2.zero;
        bgRect.anchorMax = Vector2.one;
        bgRect.offsetMin = Vector2.zero;
        bgRect.offsetMax = Vector2.zero;

        if (sceneConfig.background.type == "image")
        {
            yield return StartCoroutine(LoadBackgroundImage());
        }
        else if (sceneConfig.background.type == "video")
        {
            Debug.LogWarning("[MainSceneManager] Les vidéos de background ne sont pas encore supportées");
            
            // Masquer l'overlay même si le type vidéo n'est pas supporté
            if (IntroTransitionOverlay.Instance != null)
            {
                IntroTransitionOverlay.HideOverlay();
            }
        }
        else
        {
            // Type inconnu - masquer l'overlay quand même
            if (IntroTransitionOverlay.Instance != null)
            {
                IntroTransitionOverlay.HideOverlay();
            }
        }
    }

    IEnumerator LoadBackgroundImage()
    {
        string fullUrl = GeneralConfigManager.Instance.GetBackgroundImageUrl(sceneConfig.background.url);

        using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(fullUrl))
        {
            yield return www.SendWebRequest();

            if (www.result == UnityWebRequest.Result.Success)
            {
                Texture2D texture = ((DownloadHandlerTexture)www.downloadHandler).texture;
                RawImage rawImage = backgroundObject.AddComponent<RawImage>();
                rawImage.texture = texture;
                rawImage.raycastTarget = false;
                rawImage.color = Color.white;
                rawImage.enabled = true;

                Canvas bgCanvas = backgroundObject.GetComponent<Canvas>();
                if (bgCanvas != null)
                {
                    bgCanvas.sortingOrder = 0;
                }
                
                // Masquer l'overlay de transition dès que le background est chargé
                // Cela évite l'écran noir prolongé
                if (IntroTransitionOverlay.Instance != null)
                {
                    Debug.Log("[MainSceneManager] ✅ Background chargé - Masquage de l'overlay de transition");
                    IntroTransitionOverlay.HideOverlay();
                }
            }
            else
            {
                Debug.LogError($"[MainSceneManager] Erreur chargement background: {www.error}");
                
                // Même en cas d'erreur, masquer l'overlay pour ne pas bloquer
                if (IntroTransitionOverlay.Instance != null)
                {
                    IntroTransitionOverlay.HideOverlay();
                }
            }
        }
    }

    IEnumerator CreateMapEntries()
    {
        if (sceneConfig == null || sceneConfig.mapEntries == null || sceneConfig.mapEntries.Count == 0)
        {
            Debug.LogWarning("[MainSceneManager] Aucune entrée de map à créer");
            yield break;
        }

        // Créer un conteneur pour les sprites (comme dans MapManager)
        GameObject entriesContainer = new GameObject("MapEntriesContainer");
        entriesContainer.transform.SetParent(backgroundObject.transform, false);
        entriesContainer.SetActive(true); // S'assurer que le conteneur est actif

        RectTransform containerRect = entriesContainer.AddComponent<RectTransform>();
        containerRect.anchorMin = Vector2.zero;
        containerRect.anchorMax = Vector2.one;
        containerRect.pivot = new Vector2(0, 0);
        containerRect.anchoredPosition = Vector2.zero;
        containerRect.offsetMin = Vector2.zero;
        containerRect.offsetMax = Vector2.zero;

        // Attendre plusieurs frames pour que le background soit complètement chargé et dimensionné
        // En WebGL, le canvas peut mettre du temps à se dimensionner correctement
        yield return null;
        yield return null;
        yield return new WaitForEndOfFrame();

        // Calculer les facteurs de scale (comme dans MapManager)
        RawImage bgImage = backgroundObject.GetComponent<RawImage>();
        Texture2D bgTexture = bgImage?.texture as Texture2D;
        RectTransform bgRect = backgroundObject.GetComponent<RectTransform>();

        float scaleX = 1f;
        float scaleY = 1f;

        if (bgTexture != null && bgRect != null)
        {
            // Le background est en full screen, utiliser rect.rect au lieu de sizeDelta
            // En WebGL, rect.rect peut être plus petit que Screen.width/height à cause du ratio forcé
            float bgWidth = bgRect.rect.width > 0 ? bgRect.rect.width : Screen.width;
            float bgHeight = bgRect.rect.height > 0 ? bgRect.rect.height : Screen.height;
            
            Debug.Log($"[MainSceneManager] Calcul du scale - Texture: {bgTexture.width}x{bgTexture.height}, Canvas: {bgWidth}x{bgHeight}, Screen: {Screen.width}x{Screen.height}");
            
            scaleX = bgWidth / bgTexture.width;
            scaleY = bgHeight / bgTexture.height;
            
            if (scaleX == 0 || scaleY == 0 || float.IsInfinity(scaleX) || float.IsInfinity(scaleY))
            {
                Debug.LogWarning($"[MainSceneManager] Scale invalide ({scaleX}, {scaleY}), utilisation du fallback");
                scaleX = Screen.width / bgTexture.width;
                scaleY = Screen.height / bgTexture.height;
            }
            
            Debug.Log($"[MainSceneManager] Scale calculé: {scaleX}x{scaleY}");
        }
        else
        {
            Debug.LogWarning($"[MainSceneManager] Texture ou RectTransform manquant - bgTexture: {bgTexture != null}, bgRect: {bgRect != null}");
        }

        foreach (MainSceneMapEntry entry in sceneConfig.mapEntries)
        {
            // N'afficher le sprite que si l'utilisateur a accès ET le statut est "available"
            bool shouldDisplay = entry.has_access && entry.status == "available";
            
            if (!shouldDisplay)
            {
                Debug.Log($"[MainSceneManager] ⚠️ Quête {entry.id} (questId: {entry.questId}) non affichée - has_access: {entry.has_access}, status: {entry.status ?? "null"}");
                continue;
            }
            
            yield return StartCoroutine(CreateMapEntrySprite(entry, entriesContainer.transform, scaleX, scaleY));
        }
    }

    IEnumerator CreateMapEntrySprite(MainSceneMapEntry entry, Transform parent, float scaleX, float scaleY)
    {
        string fullSpriteUrl = GeneralConfigManager.Instance.GetDecoratorImageUrl(entry.spriteUrl);

        using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(fullSpriteUrl))
        {
            yield return www.SendWebRequest();

            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"[MainSceneManager] Erreur chargement sprite {entry.id}: {www.error}");
                yield break;
            }

            Texture2D texture = ((DownloadHandlerTexture)www.downloadHandler).texture;
            Sprite sprite = Sprite.Create(texture,
                new Rect(0, 0, texture.width, texture.height),
                new Vector2(0.5f, 0.5f));

            // Créer le GameObject du sprite
            GameObject spriteObj = new GameObject($"MapEntry_{entry.id}");
            // Mettre directement dans le background (comme MapManager) pour éviter les conflits de Canvas
            spriteObj.transform.SetParent(backgroundObject.transform, false);

            RectTransform rect = spriteObj.AddComponent<RectTransform>();
            rect.anchorMin = Vector2.zero;
            rect.anchorMax = Vector2.zero;
            rect.pivot = new Vector2(0.5f, 0.5f);

            // Calculer la position et la taille avec le scale (comme dans MapManager)
            Vector2 scaledPos = new Vector2(entry.position.x * scaleX, entry.position.y * scaleY);
            Vector2 scaledSize = new Vector2(entry.size.x * scaleX, entry.size.y * scaleY);

            rect.anchoredPosition = scaledPos;
            rect.sizeDelta = scaledSize;
            
            // Vérifier position valide en utilisant la taille réelle du canvas/background
            RectTransform bgRect = backgroundObject.GetComponent<RectTransform>();
            float canvasWidth = bgRect != null ? bgRect.rect.width : Screen.width;
            float canvasHeight = bgRect != null ? bgRect.rect.height : Screen.height;
            
            // En WebGL, le canvas peut être plus petit que l'écran à cause du ratio forcé
            // Utiliser la taille réelle du canvas pour la vérification
            bool inScreen = scaledPos.x >= -scaledSize.x/2 && scaledPos.x <= canvasWidth + scaledSize.x/2 && 
                           scaledPos.y >= -scaledSize.y/2 && scaledPos.y <= canvasHeight + scaledSize.y/2;
            if (!inScreen)
            {
                Debug.LogWarning($"[MainSceneManager] Icône {entry.id} hors écran: {scaledPos} (Canvas: {canvasWidth}x{canvasHeight}, Screen: {Screen.width}x{Screen.height})");
            }

            Image image = spriteObj.AddComponent<Image>();
            image.sprite = sprite;
            image.raycastTarget = true;
            image.color = Color.white;
            image.enabled = true;

            spriteObj.SetActive(true);

            MainSceneMapEntryData entryData = spriteObj.AddComponent<MainSceneMapEntryData>();
            entryData.Initialize(entry, this);

            Canvas entryCanvas = spriteObj.AddComponent<Canvas>();
            entryCanvas.overrideSorting = true;
            entryCanvas.sortingOrder = entry.sortingOrder > 0 ? entry.sortingOrder : 100;
            
            // Ajouter GraphicRaycaster pour permettre les clics
            UnityEngine.UI.GraphicRaycaster raycaster = spriteObj.GetComponent<UnityEngine.UI.GraphicRaycaster>();
            if (raycaster == null)
            {
                raycaster = spriteObj.AddComponent<UnityEngine.UI.GraphicRaycaster>();
            }
            
            // Ajouter EventTrigger pour gérer les clics (plus fiable en WebGL que Input System)
            UnityEngine.EventSystems.EventTrigger eventTrigger = spriteObj.GetComponent<UnityEngine.EventSystems.EventTrigger>();
            if (eventTrigger == null)
            {
                eventTrigger = spriteObj.AddComponent<UnityEngine.EventSystems.EventTrigger>();
            }
            
            // Créer un événement PointerClick
            UnityEngine.EventSystems.EventTrigger.Entry clickEntry = new UnityEngine.EventSystems.EventTrigger.Entry();
            clickEntry.eventID = UnityEngine.EventSystems.EventTriggerType.PointerClick;
            
            // Stocker le mapId dans une variable locale pour la closure
            string mapIdToLoad = entry.mapId;
            clickEntry.callback.AddListener((data) => {
                Debug.Log($"[MainSceneManager] ✅✅✅ EventTrigger: Clic détecté sur {entry.id}, mapId: {mapIdToLoad}");
                #if UNITY_WEBGL && !UNITY_EDITOR
                UnityEngine.Application.ExternalCall("console.log", $"[Unity] ✅✅✅ EventTrigger: Clic sur {entry.id}, mapId: {mapIdToLoad}");
                #endif
                OnMapEntryClicked(mapIdToLoad);
            });
            
            eventTrigger.triggers.Add(clickEntry);
            
            // Créer un événement PointerEnter pour le tooltip
            if (!string.IsNullOrEmpty(entry.tooltipText))
            {
                UnityEngine.EventSystems.EventTrigger.Entry enterEntry = new UnityEngine.EventSystems.EventTrigger.Entry();
                enterEntry.eventID = UnityEngine.EventSystems.EventTriggerType.PointerEnter;
                string tooltipText = entry.tooltipText;
                RectTransform spriteRect = rect;
                enterEntry.callback.AddListener((data) => {
                    Debug.Log($"[MainSceneManager] 🖱️ Survol détecté sur: {entry.id}, tooltip: {tooltipText}");
                    ShowTooltip(tooltipText, spriteRect);
                });
                eventTrigger.triggers.Add(enterEntry);
                
                // Créer un événement PointerExit pour masquer le tooltip
                UnityEngine.EventSystems.EventTrigger.Entry exitEntry = new UnityEngine.EventSystems.EventTrigger.Entry();
                exitEntry.eventID = UnityEngine.EventSystems.EventTriggerType.PointerExit;
                exitEntry.callback.AddListener((data) => {
                    HideTooltip();
                });
                eventTrigger.triggers.Add(exitEntry);
            }

            mapEntrySprites.Add(spriteObj);
            
            Debug.Log($"[MainSceneManager] ✅ Icône créée: {entry.id}, mapId: {entry.mapId}, tooltip: {entry.tooltipText}, position: {scaledPos}, size: {scaledSize}");

            // Vérification visibilité
            bool isVisible = spriteObj.activeInHierarchy && image.enabled && image.color.a > 0 && image.sprite != null;
            if (!isVisible)
            {
                Debug.LogError($"[MainSceneManager] Icône {entry.id} invisible !");
            }
            
            if (spriteObj.transform.parent != null && !spriteObj.transform.parent.gameObject.activeSelf)
            {
                Debug.LogError($"[MainSceneManager] Parent de {entry.id} inactif !");
            }
        }
    }

    public void OnMapEntryClicked(string mapId)
    {
        Debug.Log($"[MainSceneManager] 🎯 OnMapEntryClicked appelé avec mapId: {mapId}");
        
        if (string.IsNullOrEmpty(mapId))
        {
            Debug.LogError("[MainSceneManager] ❌ mapId est vide ou null !");
            return;
        }
        
        // BLOQUER les clics si le panel de prévisualisation est déjà ouvert
        if (QuestPreviewPanelBuilder.Instance != null && QuestPreviewPanelBuilder.Instance.IsPanelOpen())
        {
            Debug.Log("[MainSceneManager] ⚠️ Panel de prévisualisation déjà ouvert - clic bloqué");
            return;
        }
        
        // Vérifier si l'utilisateur est connecté avant de charger la map
        if (UserDataManager.Instance == null || !UserDataManager.Instance.IsLoggedIn())
        {
            Debug.Log("[MainSceneManager] ⚠️ Utilisateur non connecté - Affichage du panneau d'identification");
            // Sauvegarder le mapId pour le charger après connexion réussie
            PlayerPrefs.SetString("PendingMapId", mapId);
            PlayerPrefs.Save();
            ShowLoginPopup();
            return;
        }
        
        // Afficher le panel de prévisualisation de la quête
        ShowQuestPreviewPanel(mapId);
    }
    
    /// <summary>
    /// Affiche le panel de prévisualisation de la quête
    /// </summary>
    void ShowQuestPreviewPanel(string mapId)
    {
        Debug.Log($"[MainSceneManager] 📋 Affichage du panel de prévisualisation pour: {mapId}");
        
        // Récupérer le questId
        MainSceneMapEntry entry = null;
        int questId = 0;
        
        if (sceneConfig != null && sceneConfig.mapEntries != null)
        {
            entry = sceneConfig.mapEntries.Find(e => e.mapId == mapId);
            if (entry != null && entry.questId > 0)
            {
                questId = entry.questId;
            }
        }
        
        // Récupérer les données de la quête depuis l'API
        StartCoroutine(LoadQuestDataAndShowPanel(mapId, questId));
    }
    
    /// <summary>
    /// Charge les données de la quête depuis l'API et affiche le panel
    /// </summary>
    IEnumerator LoadQuestDataAndShowPanel(string mapId, int questId)
    {
        Debug.Log($"[MainSceneManager] 🎮 JOUER: LoadQuestDataAndShowPanel APPELÉ - mapId={mapId}, questId={questId}");
        Debug.Log($"[MainSceneManager] 🎮 JOUER: sceneConfig null? {sceneConfig == null}");
        
        // Si sceneConfig n'est pas encore chargé, attendre
        float configTimeout = 5f;
        float configElapsed = 0f;
        while (sceneConfig == null && configElapsed < configTimeout)
        {
            Debug.Log($"[MainSceneManager] 🎮 JOUER: Attente sceneConfig... ({configElapsed}s)");
            yield return new WaitForSeconds(0.2f);
            configElapsed += 0.2f;
        }
        
        if (sceneConfig == null)
        {
            Debug.LogError("[MainSceneManager] 🎮 JOUER: ❌ sceneConfig toujours null après timeout!");
        }
        else
        {
            Debug.Log($"[MainSceneManager] 🎮 JOUER: ✅ sceneConfig chargé, quests count: {sceneConfig.quests?.Count ?? 0}");
        }
        
        Quest questData = null;
        
        // Récupérer les données des quêtes depuis MainSceneConfig
        if (sceneConfig != null && sceneConfig.quests != null && sceneConfig.quests.Count > 0)
        {
            // Trouver la quête par questId
            questData = sceneConfig.quests.Find(q => q.id == questId);
            
            if (questData != null)
            {
                Debug.Log($"[MainSceneManager] ✅ Données de quête trouvées - ID: {questData.id}, Titre: {questData.title}");
            }
            else
            {
                Debug.LogWarning($"[MainSceneManager] ⚠️ Quête {questId} non trouvée dans les données API");
            }
        }
        
        // Fallback si pas de données API
        if (questData == null)
        {
            var questPreviewConfig = GeneralConfigManager.Instance?.GetConfig()?.questPreviewPanel;
            var sampleQuest = questPreviewConfig?.sampleQuests?.quest01;
            
            questData = new Quest
            {
                id = questId,
                title = sampleQuest?.title ?? $"QUÊTE {questId}",
                description = sampleQuest?.description ?? "Découvrez cette nouvelle aventure passionnante !",
                duration = sampleQuest?.duration ?? "2 H 00",
                trailer_url = sampleQuest?.videoUrl ?? "",
                trainings = new List<Training>(),
                sprite_url = sampleQuest?.iconUrl ?? "UI_quest_icon_dda.png"
            };
            
            if (sampleQuest?.formations != null)
            {
                foreach (string formation in sampleQuest.formations)
                {
                    questData.trainings.Add(new Training { title = formation, url = "" });
                }
            }
            
            Debug.Log("[MainSceneManager] Utilisation des données de fallback");
        }
        
        yield return null;
        
        // Attendre que GeneralConfigManager soit prêt et ait chargé la configuration
        Debug.Log("[MainSceneManager] Attente du chargement de GeneralConfigManager...");
        float timeout = 10f;
        float elapsed = 0f;
        while ((GeneralConfigManager.Instance == null || !GeneralConfigManager.Instance.IsConfigLoaded()) && elapsed < timeout)
        {
            yield return new WaitForSeconds(0.1f);
            elapsed += 0.1f;
        }
        
        if (GeneralConfigManager.Instance == null || !GeneralConfigManager.Instance.IsConfigLoaded())
        {
            Debug.LogError("[MainSceneManager] ❌ Impossible de charger GeneralConfigManager - Annulation de l'affichage du panel");
            yield break;
        }
        
        Debug.Log("[MainSceneManager] ✅ GeneralConfigManager chargé et prêt");
        
        // Créer ou récupérer le QuestPreviewPanelBuilder
        QuestPreviewPanelBuilder panelBuilder = FindFirstObjectByType<QuestPreviewPanelBuilder>();
        if (panelBuilder == null)
        {
            GameObject builderObj = new GameObject("QuestPreviewPanelBuilder");
            panelBuilder = builderObj.AddComponent<QuestPreviewPanelBuilder>();
        }
        
        // Définir le canvas parent
        Canvas mainCanvas = FindFirstObjectByType<Canvas>();
        if (mainCanvas != null)
        {
            panelBuilder.SetParentCanvas(mainCanvas);
        }
        
        // Afficher le panel avec les données de l'API
        Debug.Log($"[MainSceneManager] 🎮 JOUER: Affichage du panel pour {questData?.title ?? "NULL"}...");
        panelBuilder.ShowQuestPreviewWithQuestData(
            mapId,
            questData,
            () => LaunchMapDirectly(mapId), // Action "Commencer la quête"
            () => Debug.Log("[MainSceneManager] Quête passée") // Action "Passer cette quête"
        );
        Debug.Log("[MainSceneManager] 🎮 JOUER: ✅ ShowQuestPreviewWithQuestData appelé");
    }
    
    /// <summary>
    /// Lance directement la map (appelé depuis le panel de prévisualisation)
    /// </summary>
    public void LaunchMapDirectly(string mapId)
    {
        Debug.Log($"[MainSceneManager] 🚀 Lancement direct de la map: {mapId}");
        
        // Trouver l'entrée correspondante pour récupérer le questId
        int questId = 0;
        if (sceneConfig != null && sceneConfig.mapEntries != null)
        {
            MainSceneMapEntry entry = sceneConfig.mapEntries.Find(e => e.mapId == mapId);
            if (entry != null && entry.questId > 0)
            {
                questId = entry.questId;
                Debug.Log($"[MainSceneManager] ✅ QuestId trouvé: {questId} pour mapId: {mapId}");
            }
            else
            {
                Debug.LogWarning($"[MainSceneManager] ⚠️ QuestId non trouvé pour mapId: {mapId}, tentative d'extraction depuis le mapId");
                // Fallback: extraire le questId depuis le mapId (format: "map-Q0" → questId = 1)
                // map-Q0 → Q0 → index 0 → questId = 0 + 1 = 1
                if (mapId.StartsWith("map-Q"))
                {
                    string indexStr = mapId.Replace("map-Q", "");
                    if (int.TryParse(indexStr, out int index))
                    {
                        questId = index + 1; // Q0 = questId 1, Q1 = questId 2, etc.
                        Debug.Log($"[MainSceneManager] ✅ QuestId extrait depuis mapId: {questId}");
                    }
                }
            }
        }
        
        PlayerPrefs.SetString("CurrentMapId", mapId);
        
        // Sauvegarder le questId pour l'API
        if (questId > 0)
        {
            PlayerPrefs.SetInt("CurrentQuestId", questId);
            Debug.Log($"[MainSceneManager] ✅ CurrentQuestId sauvegardé: {questId}");
        }
        else
        {
            Debug.LogWarning("[MainSceneManager] ⚠️ QuestId non disponible, le chargement depuis l'API pourrait échouer");
        }
        
        // Récupérer et sauvegarder le niveau de difficulté choisi pour cette quête
        string difficulty = UserDataManager.Instance.GetQuestDifficulty(mapId, "Débutant");
        PlayerPrefs.SetString("CurrentQuestDifficulty", difficulty);
        Debug.Log($"[MainSceneManager] ✅ Difficulté sauvegardée: {difficulty} pour la quête {mapId}");
        
        // IMPORTANT : Nettoyer NextStepId quand on clique sur une icône de map
        // car on veut reprendre là où on était (CurrentStepId), pas passer au step suivant
        PlayerPrefs.DeleteKey("NextStepId_" + mapId);
        
        PlayerPrefs.Save();
        
        Debug.Log($"[MainSceneManager] CurrentMapId sauvegardé: {mapId}");
        Debug.Log($"[MainSceneManager] NextStepId nettoyé pour la map: {mapId}");

        if (UnifiedLoadingManager.Instance != null)
        {
            Debug.Log($"[MainSceneManager] Chargement de la scène Map via UnifiedLoadingManager");
            UnifiedLoadingManager.LoadMapScene("Map");
        }
        else
        {
            // Fallback: chargement direct si UnifiedLoadingManager n'est pas disponible
            SceneManager.LoadScene("Map");
        }
    }

    // NOTE : Variables de suivi de souris supprimées - plus nécessaires avec EventTrigger

    void Update()
    {
        // Toggle debug avec la touche D
        if (Keyboard.current != null && Keyboard.current.dKey.wasPressedThisFrame)
        {
            showDebugSprites = !showDebugSprites;
            ToggleDebugSprites();
        }

        // La touche I n'est plus nécessaire - le panneau s'affiche automatiquement si l'utilisateur n'est pas connecté
        // (Code commenté mais conservé pour référence)
        // if (Keyboard.current != null && Keyboard.current.iKey.wasPressedThisFrame)
        // {
        //     ShowLoginPopup();
        // }

        // NETTOYAGE CONTINU : s'assurer qu'aucun StandaloneInputModule résiduel n'est présent
        CleanupStandaloneInputModules();

        // NOTE : Les clics sont gérés par EventTrigger ET par un système manuel de fallback
        // Le système manuel fonctionne même si l'EventSystem a des problèmes
        // Ne pas gérer les clics si le panneau des paramètres est ouvert
        if (SettingsManager.Instance != null && SettingsManager.Instance.settingsPanel != null && SettingsManager.Instance.settingsPanel.activeSelf)
        {
            Debug.Log("[MainSceneManager] Panneau des paramètres ouvert, clics bloqués");
            return; // Panneau des paramètres ouvert, ne pas gérer les clics
        }
        
        // Vérifier si la popup de login est ouverte
        LoginPopup loginPopup = FindFirstObjectByType<LoginPopup>();
        if (loginPopup != null)
        {
            Debug.Log("[MainSceneManager] Popup de login ouverte, clics bloqués");
            return; // Popup de login ouverte, ne pas gérer les clics
        }
        
        // Vérifier si le panel de prévisualisation des quêtes est ouvert
        if (QuestPreviewPanelBuilder.Instance != null && QuestPreviewPanelBuilder.Instance.IsPanelOpen())
        {
            return; // Panel de prévisualisation ouvert, ne pas gérer les clics
        }
        
        HandleClickManual();
        HandleHoverManual();
    }

    // Système de clic manuel utilisant le nouveau Input System (fallback si EventTrigger ne fonctionne pas)
    void HandleClickManual()
    {
        #if ENABLE_INPUT_SYSTEM
        // Utiliser le nouveau Input System pour détecter les clics
        if (Mouse.current == null)
        {
            #if UNITY_WEBGL && !UNITY_EDITOR
            if (Time.frameCount % 120 == 0) // Log toutes les 2 secondes
            {
                UnityEngine.Application.ExternalCall("console.log", "[Unity] ⚠️ Mouse.current est NULL");
            }
            #endif
            return;
        }
        
        // LOG DIAGNOSTIC : Position de la souris en continu (toutes les 60 frames = ~1 seconde)
        #if UNITY_WEBGL && !UNITY_EDITOR
        if (Time.frameCount % 60 == 0)
        {
            Vector2 mousePos = Mouse.current.position.ReadValue();
            bool isPressed = Mouse.current.leftButton.isPressed;
            
            string canvasInfo = "N/A";
            if (backgroundObject != null)
            {
                RectTransform bgRect = backgroundObject.GetComponent<RectTransform>();
                if (bgRect != null)
                {
                    canvasInfo = $"{bgRect.rect.width:F0}x{bgRect.rect.height:F0}";
                }
            }
            
            UnityEngine.Application.ExternalCall("console.log", $"[Unity] 🖱️ Souris: pos=({mousePos.x:F0},{mousePos.y:F0}), pressed={isPressed}, Canvas: {canvasInfo}, Screen: {Screen.width}x{Screen.height}");
        }
        #endif
        
        bool clicked = false;
        Vector2 clickPos = Vector2.zero;
        
        // MÉTHODE 1 : Détecter un clic avec wasPressedThisFrame (ne fonctionne pas toujours en WebGL)
        if (Mouse.current.leftButton.wasPressedThisFrame)
        {
            clicked = true;
            clickPos = Mouse.current.position.ReadValue();
            
            #if UNITY_WEBGL && !UNITY_EDITOR
            UnityEngine.Application.ExternalCall("console.log", $"[Unity] 🖱️ CLIC DÉTECTÉ (wasPressedThisFrame) à: ({clickPos.x:F0},{clickPos.y:F0})");
            #endif
        }
        
        // MÉTHODE 2 : Détecter manuellement le changement d'état (WebGL fallback)
        bool isMouseDownNow = Mouse.current.leftButton.isPressed;
        if (!wasMouseDownLastFrame && isMouseDownNow)
        {
            clicked = true;
            clickPos = Mouse.current.position.ReadValue();
            
            #if UNITY_WEBGL && !UNITY_EDITOR
            UnityEngine.Application.ExternalCall("console.log", $"[Unity] 🖱️ CLIC DÉTECTÉ (manual) à: ({clickPos.x:F0},{clickPos.y:F0})");
            #endif
        }
        wasMouseDownLastFrame = isMouseDownNow;
        
        // Détecter aussi les touches tactiles
        if (Touchscreen.current != null && Touchscreen.current.primaryTouch.press.wasPressedThisFrame)
        {
            clicked = true;
            clickPos = Touchscreen.current.primaryTouch.position.ReadValue();
            
            #if UNITY_WEBGL && !UNITY_EDITOR
            UnityEngine.Application.ExternalCall("console.log", $"[Unity] 👆 TOUCH DÉTECTÉ à: ({clickPos.x:F0},{clickPos.y:F0})");
            #endif
        }
        
        if (clicked)
        {
            #if UNITY_WEBGL && !UNITY_EDITOR
            UnityEngine.Application.ExternalCall("console.log", $"[Unity] 🔍 Vérification de {mapEntrySprites.Count} icônes...");
            #endif
            
            // Vérifier si on a cliqué sur une icône de map
            int iconIndex = 0;
            foreach (GameObject spriteObj in mapEntrySprites)
            {
                if (spriteObj != null && spriteObj.activeInHierarchy)
                {
                    RectTransform spriteRect = spriteObj.GetComponent<RectTransform>();
                    if (spriteRect != null)
                    {
                        // LOG: Position et taille de chaque icône
                        Vector3[] corners = new Vector3[4];
                        spriteRect.GetWorldCorners(corners);
                        
                        #if UNITY_WEBGL && !UNITY_EDITOR
                        UnityEngine.Application.ExternalCall("console.log", $"[Unity]   Icône {iconIndex}: {spriteObj.name}, worldCorners: ({corners[0].x:F0},{corners[0].y:F0}) -> ({corners[2].x:F0},{corners[2].y:F0})");
                        #endif
                        
                        // Utiliser RectangleContainsScreenPoint pour détecter le clic
                        bool contains = RectTransformUtility.RectangleContainsScreenPoint(spriteRect, clickPos, null);
                        
                        #if UNITY_WEBGL && !UNITY_EDITOR
                        UnityEngine.Application.ExternalCall("console.log", $"[Unity]   RectangleContainsScreenPoint = {contains}");
                        #endif
                        
                        if (contains)
                        {
                            MainSceneMapEntryData entryData = spriteObj.GetComponent<MainSceneMapEntryData>();
                            if (entryData != null && entryData.entryData != null)
                            {
                                Debug.Log($"[MainSceneManager] ✅✅✅ Clic manuel détecté sur: {entryData.entryData.id}, mapId: {entryData.entryData.mapId}");
                                #if UNITY_WEBGL && !UNITY_EDITOR
                                UnityEngine.Application.ExternalCall("console.log", $"[Unity] ✅✅✅ Clic manuel sur: {entryData.entryData.id}, mapId: {entryData.entryData.mapId}");
                                #endif
                                OnMapEntryClicked(entryData.entryData.mapId);
                                return;
                            }
                        }
                    }
                }
                iconIndex++;
            }
            
            #if UNITY_WEBGL && !UNITY_EDITOR
            UnityEngine.Application.ExternalCall("console.log", "[Unity] ❌ Aucune icône ne correspond au clic");
            #endif
        }
        #endif
    }

    /// <summary>
    /// Appelé par WebGLClickReceiver quand un clic est reçu depuis JavaScript
    /// </summary>
    public void OnWebGLClick(Vector2 clickPosition)
    {
        #if UNITY_WEBGL && !UNITY_EDITOR
        Application.ExternalCall("console.log", $"[Unity] MainSceneManager.OnWebGLClick: ({clickPosition.x:F0}, {clickPosition.y:F0})");
        #endif
        
        Debug.Log($"[MainSceneManager] 🖱️ Clic WebGL reçu: ({clickPosition.x:F0}, {clickPosition.y:F0})");
        
        // Bloquer les clics si le panel de prévisualisation est ouvert
        if (QuestPreviewPanelBuilder.Instance != null && QuestPreviewPanelBuilder.Instance.IsPanelOpen())
        {
            Debug.Log("[MainSceneManager] Panel de prévisualisation ouvert, clic WebGL bloqué");
            return;
        }
        
        // Vérifier si on a cliqué sur une icône de map
        foreach (GameObject spriteObj in mapEntrySprites)
        {
            if (spriteObj != null && spriteObj.activeInHierarchy)
            {
                RectTransform spriteRect = spriteObj.GetComponent<RectTransform>();
                if (spriteRect != null)
                {
                    // Utiliser RectangleContainsScreenPoint pour détecter le clic
                    if (RectTransformUtility.RectangleContainsScreenPoint(spriteRect, clickPosition, null))
                    {
                        MainSceneMapEntryData entryData = spriteObj.GetComponent<MainSceneMapEntryData>();
                        if (entryData != null && entryData.entryData != null)
                        {
                            Debug.Log($"[MainSceneManager] ✅✅✅ Clic WebGL sur: {entryData.entryData.id}, mapId: {entryData.entryData.mapId}");
                            #if UNITY_WEBGL && !UNITY_EDITOR
                            Application.ExternalCall("console.log", $"[Unity] ✅✅✅ Clic WebGL sur: {entryData.entryData.id}");
                            #endif
                            OnMapEntryClicked(entryData.entryData.mapId);
                            return;
                        }
                    }
                }
            }
        }
        
        Debug.Log("[MainSceneManager] ❌ Clic WebGL hors des icônes");
    }

    // Système de détection de survol manuel (fallback pour WebGL)
    void HandleHoverManual()
    {
        #if ENABLE_INPUT_SYSTEM
        if (Mouse.current == null) return;
        
        Vector2 mousePos = Mouse.current.position.ReadValue();
        GameObject hoveredIcon = null;
        
        // Vérifier quelle icône est survolée
        foreach (GameObject spriteObj in mapEntrySprites)
        {
            if (spriteObj != null && spriteObj.activeInHierarchy)
            {
                RectTransform spriteRect = spriteObj.GetComponent<RectTransform>();
                if (spriteRect != null)
                {
                    // Vérifier si la souris est sur cette icône
                    if (RectTransformUtility.RectangleContainsScreenPoint(spriteRect, mousePos, null))
                    {
                        hoveredIcon = spriteObj;
                        break;
                    }
                }
            }
        }
        
        // Si l'icône survolée a changé
        if (hoveredIcon != currentHoveredIcon)
        {
            // Masquer l'ancien tooltip
            if (currentHoveredIcon != null)
            {
                HideTooltip();
                
                #if UNITY_WEBGL && !UNITY_EDITOR
                UnityEngine.Application.ExternalCall("console.log", "[Unity] 👋 Survol quitté");
                #endif
            }
            
            // Afficher le nouveau tooltip
            if (hoveredIcon != null)
            {
                MainSceneMapEntryData entryData = hoveredIcon.GetComponent<MainSceneMapEntryData>();
                if (entryData != null && entryData.entryData != null)
                {
                    RectTransform iconRect = hoveredIcon.GetComponent<RectTransform>();
                    ShowTooltip(entryData.entryData.tooltipText, iconRect);
                    
                    #if UNITY_WEBGL && !UNITY_EDITOR
                    UnityEngine.Application.ExternalCall("console.log", $"[Unity] 👆 Survol: {entryData.entryData.id}, tooltip: {entryData.entryData.tooltipText}");
                    #endif
                }
            }
            
            currentHoveredIcon = hoveredIcon;
        }
        #endif
    }

    void ToggleDebugSprites()
    {
        foreach (GameObject sprite in mapEntrySprites)
        {
            if (sprite != null)
            {
                Image img = sprite.GetComponent<Image>();
                if (img != null)
                {
                    // Alterner entre opacité normale et semi-transparente pour le debug
                    Color color = img.color;
                    color.a = showDebugSprites ? 0.5f : 1f;
                    img.color = color;
                }
            }
        }
        Debug.Log($"[MainSceneManager] Debug sprites: {showDebugSprites}");
    }

    // NOTE : HandleHover() supprimé - les tooltips sont maintenant gérés par EventTrigger (PointerEnter/Exit)
    // Cela évite les exceptions InvalidOperationException causées par StandaloneInputModule
    // qui utilise en interne l'ancien système UnityEngine.Input

    void ShowTooltip(string text, RectTransform iconRect)
    {
        if (string.IsNullOrEmpty(text) || iconRect == null) return;

        // Créer le panneau de tooltip s'il n'existe pas
        if (tooltipPanel == null)
        {
            CreateTooltipPanel();
            
            if (tooltipPanel == null)
            {
                Debug.LogError("[MainSceneManager] Impossible de créer tooltip");
                return;
            }
        }
        
        if (tooltipPanel.transform.parent != canvas.transform)
        {
            tooltipPanel.transform.SetParent(canvas.transform, false);
        }

        if (tooltipPanel == null || tooltipText == null) return;

        // Afficher le panneau
        tooltipPanel.SetActive(true);

        // Mettre à jour le texte
        tooltipText.text = text;

        // Positionner le tooltip en bas de l'écran, centré horizontalement (comme un sous-titre)
        RectTransform tooltipRect = tooltipPanel.GetComponent<RectTransform>();
        if (tooltipRect != null && canvas != null)
        {
            RectTransform canvasRect = canvas.GetComponent<RectTransform>();
            if (canvasRect != null)
            {
                // Obtenir la hauteur du canvas
                float canvasHeight = canvasRect.rect.height;
                
                // Positionner le tooltip en bas de l'écran, centré horizontalement
                // Le pivot est (0.5, 0) donc le point de référence est le bas centré
                // On positionne à 50px du bas de l'écran
                tooltipRect.anchoredPosition = new Vector2(
                    0f, // Centré horizontalement (grâce au pivot 0.5, 0 et anchorMin/Max)
                    50f // 50px du bas de l'écran
                );
                
            }
        }
    }

    void HideTooltip()
    {
        if (tooltipPanel != null)
        {
            tooltipPanel.SetActive(false);
        }
    }

    void CreateTooltipPanel()
    {
        if (canvas == null)
        {
            Debug.LogError("[MainSceneManager] Canvas introuvable pour créer tooltip");
            return;
        }

        tooltipPanel = new GameObject("TooltipPanel");
        tooltipPanel.transform.SetParent(canvas.transform, false);

        RectTransform tooltipRect = tooltipPanel.AddComponent<RectTransform>();
        tooltipRect.anchorMin = new Vector2(0.5f, 0f); // Ancré au centre horizontal, en bas vertical
        tooltipRect.anchorMax = new Vector2(0.5f, 0f); // Ancré au centre horizontal, en bas vertical
        tooltipRect.pivot = new Vector2(0.5f, 0f); // Pivot centré horizontalement, en bas verticalement
        tooltipRect.sizeDelta = new Vector2(300, 50);

        // Ajouter un background
        Image bgImage = tooltipPanel.AddComponent<Image>();
        bgImage.color = new Color(0, 0, 0, 0.8f); // Fond noir semi-transparent

        // Créer le texte
        GameObject textObj = new GameObject("TooltipText");
        textObj.transform.SetParent(tooltipPanel.transform, false);

        RectTransform textRect = textObj.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.offsetMin = new Vector2(10, 5);
        textRect.offsetMax = new Vector2(-10, -5);

        tooltipText = textObj.AddComponent<TextMeshProUGUI>();
        tooltipText.text = "";
        tooltipText.fontSize = 16;
        tooltipText.color = Color.white;
        tooltipText.alignment = TextAlignmentOptions.Center; // Centrer le texte horizontalement
        tooltipText.textWrappingMode = TMPro.TextWrappingModes.Normal;

        // Désactiver par défaut
        tooltipPanel.SetActive(false);
    }

    void CleanupExistingObjects()
    {
        // Nettoyer les anciens sprites
        foreach (GameObject sprite in mapEntrySprites)
        {
            if (sprite != null)
            {
                DestroyImmediate(sprite);
            }
        }
        mapEntrySprites.Clear();

        // Nettoyer le background
        if (backgroundObject != null)
        {
            DestroyImmediate(backgroundObject);
            backgroundObject = null;
        }

        // Nettoyer le tooltip
        if (tooltipPanel != null)
        {
            DestroyImmediate(tooltipPanel);
            tooltipPanel = null;
            tooltipText = null;
        }

        // Réinitialiser les références
        sceneConfig = null;
        canvas = null;
    }

    IEnumerator CreateHeader()
    {
        if (canvas == null)
        {
            Debug.LogError("[MainSceneManager] Canvas introuvable pour créer le header");
            yield break;
        }

        // Utiliser HeaderManager pour créer le header
        yield return StartCoroutine(HeaderManager.Instance.CreateHeader(canvas, OnHeaderElementClick));
    }

    /// <summary>
    /// Callback appelé quand un élément du header est cliqué
    /// </summary>
    private void OnHeaderElementClick(string action)
    {
        Debug.Log($"[MainSceneManager] ✅ OnHeaderElementClick appelé avec action: {action}");

        switch (action)
        {
            case "settings":
                Debug.Log("[MainSceneManager] Tentative d'ouverture des paramètres...");
                
                // Obtenir ou créer l'instance du SettingsManager
                SettingsManager settingsManager = SettingsManager.GetOrCreateInstance();
                
                if (settingsManager != null)
                {
                    // Si l'instance vient d'être créée, attendre une frame pour l'initialisation
                    if (settingsManager.settingsPanel == null)
                    {
                        Debug.Log("[MainSceneManager] ⚙️ SettingsManager vient d'être créé, attente de l'initialisation...");
                        StartCoroutine(WaitForSettingsManagerAndOpen());
                    }
                    else
                    {
                        Debug.Log("[MainSceneManager] ✅ SettingsManager.Instance trouvé, appel de OpenSettings()");
                        settingsManager.OpenSettings();
                    }
                }
                else
                {
                    Debug.LogError("[MainSceneManager] ❌ Impossible de créer le SettingsManager !");
                }
                break;

            case "back":
                // Retour au menu principal si nécessaire
                Debug.Log("[MainSceneManager] Action 'back' non implémentée");
                break;

            default:
                Debug.LogWarning($"[MainSceneManager] Action inconnue: {action}");
                break;
        }
    }

    /// <summary>
    /// Attend que SettingsManager soit initialisé puis ouvre le panneau
    /// </summary>
    private System.Collections.IEnumerator WaitForSettingsManagerAndOpen()
    {
        yield return null; // Attendre une frame pour que Awake() soit appelé
        
        if (SettingsManager.Instance != null)
        {
            Debug.Log("[MainSceneManager] ✅ SettingsManager.Instance créé, ouverture du panneau...");
            SettingsManager.Instance.OpenSettings();
        }
        else
        {
            Debug.LogError("[MainSceneManager] ❌ SettingsManager.Instance est toujours NULL après création !");
        }
    }

    /// <summary>
    /// Affiche la popup d'identification
    /// </summary>
    private void ShowLoginPopup()
    {
        Debug.Log($"[MainSceneManager] ShowLoginPopup appelé - loginPopup existant: {(loginPopup != null ? "OUI" : "NON")}");
        
        // Ne pas créer plusieurs popups
        if (loginPopup != null)
        {
            Debug.Log("[MainSceneManager] ⚠️ LoginPopup existe déjà, on ne recrée pas");
            return;
        }

        Debug.Log("[MainSceneManager] 🔨 Création du LoginPopup...");
        GameObject popupObj = new GameObject("LoginPopup");
        loginPopup = popupObj.AddComponent<LoginPopup>();
        Debug.Log("[MainSceneManager] ✅ LoginPopup créé, appel de Initialize...");
        loginPopup.Initialize(
            onSuccess: () => {
                Debug.Log("[MainSceneManager] ✅ Connexion réussie");
                
                // Recharger la configuration du projet depuis l'API avec le token utilisateur
                RefreshProjectConfiguration();
                
                // Si une map était en attente, la charger maintenant
                string pendingMapId = PlayerPrefs.GetString("PendingMapId", "");
                if (!string.IsNullOrEmpty(pendingMapId))
                {
                    Debug.Log($"[MainSceneManager] Chargement de la map en attente: {pendingMapId}");
                    PlayerPrefs.DeleteKey("PendingMapId");
                    PlayerPrefs.Save();
                    // Charger la map après un court délai pour laisser le temps à la popup de se fermer
                    StartCoroutine(LoadPendingMapAfterDelay(pendingMapId));
                }
            },
            onCloseCallback: () => {
                // Réinitialiser la référence quand la popup est fermée
                loginPopup = null;
                Debug.Log("[MainSceneManager] Popup fermée - référence réinitialisée");
            }
        );
        loginPopup.Show();
    }
    
    /// <summary>
    /// Charge la map en attente après un court délai
    /// </summary>
    private System.Collections.IEnumerator LoadPendingMapAfterDelay(string mapId)
    {
        yield return new WaitForSeconds(0.5f); // Attendre que la popup se ferme
        OnMapEntryClicked(mapId);
    }
    
    /// <summary>
    /// Recharge la configuration du projet depuis l'API après une authentification
    /// Cela permet d'obtenir les données mises à jour pour l'utilisateur connecté
    /// </summary>
    public void RefreshProjectConfiguration()
    {
        Debug.Log("[MainSceneManager] 🔄 Rechargement de la configuration du projet après authentification...");
        StartCoroutine(RefreshProjectConfigurationCoroutine());
    }
    
    /// <summary>
    /// Coroutine pour recharger la configuration du projet depuis l'API
    /// </summary>
    private IEnumerator RefreshProjectConfigurationCoroutine()
    {
        // Afficher un indicateur de chargement léger
        if (UnifiedLoadingManager.Instance != null)
        {
            UnifiedLoadingManager.ShowLoading("Mise à jour des données...", LoadingContext.Menu);
        }
        
        // Construire l'URL de l'API
        string apiUrl = GeneralConfigManager.Instance?.GetMainSceneConfigApiUrl() ?? "";
        
        if (string.IsNullOrEmpty(apiUrl))
        {
            Debug.LogWarning("[MainSceneManager] ⚠️ Impossible de recharger la configuration - URL API non disponible");
            if (UnifiedLoadingManager.Instance != null)
            {
                UnifiedLoadingManager.HideLoadingAfterDelay(0.2f);
            }
            yield break;
        }
        
        Debug.Log($"[MainSceneManager] 🌐 Appel API pour rafraîchir la configuration: {apiUrl}");
        
        // Cette fois, l'utilisateur est connecté, donc on ajoute le token
        string token = UserDataManager.Instance?.token;
        
        using (UnityWebRequest www = UnityWebRequest.Get(apiUrl))
        {
            // User-Agent requis pour éviter les blocages par Varnish/CloudFlare
            www.SetRequestHeader("User-Agent", $"Unity/{Application.unityVersion} UJSA-Game");
            www.SetRequestHeader("Accept", "application/json");
            
            if (!string.IsNullOrEmpty(token))
            {
                www.SetRequestHeader("Authorization", $"Bearer {token}");
                Debug.Log($"[MainSceneManager] ✅ Token ajouté à la requête (longueur: {token.Length})");
            }
            
            yield return www.SendWebRequest();
            
            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"[MainSceneManager] ❌ Erreur lors du rafraîchissement de la configuration: {www.error}");
                if (UnifiedLoadingManager.Instance != null)
                {
                    UnifiedLoadingManager.HideLoadingAfterDelay(0.2f);
                }
                yield break;
            }
            
            string jsonData = www.downloadHandler.text;
            Debug.Log($"[MainSceneManager] ✅ Configuration rafraîchie reçue ({jsonData.Length} caractères)");
            Debug.Log($"[MainSceneManager] 📋 JSON COMPLET REÇU APRÈS AUTHENTIFICATION:\n{jsonData}");
            
            // Parser la réponse de l'API
            bool needsRefreshDisplay = false;
            try
            {
                ApiMainSceneResponse apiResponse = JsonUtility.FromJson<ApiMainSceneResponse>(jsonData);
                
                if (apiResponse != null && apiResponse.status == "success" && apiResponse.data != null)
                {
                    // Log détaillé des données parsées
                    Debug.Log($"[MainSceneManager] 📊 DONNÉES PARSÉES:");
                    Debug.Log($"  - Status: {apiResponse.status}");
                    Debug.Log($"  - Message: {apiResponse.message}");
                    Debug.Log($"  - Background: type={apiResponse.data.background?.type}, url={apiResponse.data.background?.url}");
                    Debug.Log($"  - Nombre de quests: {apiResponse.data.quests?.Count ?? 0}");
                    
                    if (apiResponse.data.quests != null)
                    {
                        foreach (var quest in apiResponse.data.quests)
                        {
                            Debug.Log($"  - Quest id={quest.id}, has_access={quest.has_access}, status={quest.status ?? "null"}, sprite_url={quest.sprite_url}, tooltip={quest.tooltip_text}");
                        }
                    }
                    
                    // Convertir le format API vers le format interne (comme dans LoadConfiguration)
                    sceneConfig = ConvertApiResponseToConfig(apiResponse);
                    if (sceneConfig != null)
                    {
                        Debug.Log("[MainSceneManager] ✅ Configuration du projet mise à jour avec succès");
                        Debug.Log($"[MainSceneManager] 🔍 Map entries count: {sceneConfig.mapEntries?.Count ?? 0}");
                        needsRefreshDisplay = true;
                    }
                    else
                    {
                        Debug.LogWarning("[MainSceneManager] ⚠️ Conversion de la configuration a échoué");
                    }
                }
                else
                {
                    Debug.LogWarning("[MainSceneManager] ⚠️ Réponse API invalide ou sans données");
                    Debug.LogWarning($"[MainSceneManager] apiResponse null: {apiResponse == null}");
                    Debug.LogWarning($"[MainSceneManager] status: {apiResponse?.status}");
                    Debug.LogWarning($"[MainSceneManager] data null: {apiResponse?.data == null}");
                }
            }
            catch (System.Exception e)
            {
                Debug.LogError($"[MainSceneManager] ❌ Erreur lors du parsing de la configuration: {e.Message}");
                Debug.LogError($"[MainSceneManager] Stack trace: {e.StackTrace}");
            }
            
            // Rafraîchir l'affichage des maps si nécessaire (en dehors du try-catch)
            if (needsRefreshDisplay)
            {
                yield return StartCoroutine(RefreshMapEntriesDisplay());
            }
        }
        
        if (UnifiedLoadingManager.Instance != null)
        {
            UnifiedLoadingManager.HideLoadingAfterDelay(0.3f);
        }
    }
    
    /// <summary>
    /// Rafraîchit l'affichage des entrées de map après un rechargement de configuration
    /// </summary>
    private IEnumerator RefreshMapEntriesDisplay()
    {
        if (sceneConfig == null || sceneConfig.mapEntries == null)
        {
            Debug.LogWarning("[MainSceneManager] ⚠️ Pas de configuration de maps à rafraîchir");
            yield break;
        }
        
        Debug.Log($"[MainSceneManager] 🔄 Rafraîchissement de l'affichage des {sceneConfig.mapEntries.Count} maps...");
        
        // Supprimer les anciennes entrées de map
        foreach (var sprite in mapEntrySprites)
        {
            if (sprite != null)
            {
                Destroy(sprite);
            }
        }
        mapEntrySprites.Clear();
        
        // Recréer les entrées de map avec les nouvelles données
        yield return StartCoroutine(CreateMapEntries());
        
        Debug.Log("[MainSceneManager] ✅ Affichage des maps rafraîchi");
    }
}

