using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using TMPro;
using UnityEngine.Networking;
using System.Collections;

public class SettingsPanelBuilder : MonoBehaviour
{
    [Header("Configuration")]
    [SerializeField] private Vector2 panelSize = new Vector2(1400, 800);
    [SerializeField] private Color panelBackgroundColor = new Color(0.95f, 0.92f, 0.88f, 1f); // Beige clair
    [SerializeField] private Color darkBackgroundColor = new Color(0f, 0f, 0f, 0.95f); // Très sombre : 95% d'opacité
    [SerializeField] private Color headerBackgroundColor = new Color(0.90f, 0.87f, 0.83f, 1f); // Beige moyen
    [SerializeField] private float headerHeight = 80f;
    [SerializeField] private float cornerRadius = 40f;
    
    private Canvas parentCanvas;
    private Sprite closeButtonSprite;
    private bool isBuildingPanel = false; // Flag pour éviter les créations multiples
    
    // Configuration chargée depuis general-config.json
    private SettingsPanelConfig panelConfig;
    private TMP_FontAsset tabFont;
    
    // Listes pour tracker les ressources créées dynamiquement (nettoyage WebGL)
    private readonly RuntimeResourceTracker resourceTracker = new RuntimeResourceTracker();
    
    /// <summary>
    /// Définit le Canvas parent pour la construction du panneau
    /// </summary>
    public void SetParentCanvas(Canvas canvas)
    {
        parentCanvas = canvas;
        Debug.Log($"[SettingsPanelBuilder] parentCanvas défini: {canvas?.name ?? "null"}");
    }
    
    void Start()
    {
        // NE PAS créer automatiquement le panneau dans Start()
        // Le panneau sera créé uniquement via SettingsManager.OpenSettings()
        // Cela évite les créations multiples
        Debug.Log("[SettingsPanelBuilder] Start() - Pas de création automatique du panneau (sera créé via SettingsManager)");
    }
    
    public void BuildSettingsPanel()
    {
        // Charger les images depuis la configuration avant de créer le panneau
        StartCoroutine(BuildSettingsPanelCoroutine());
    }
    
    private IEnumerator BuildSettingsPanelCoroutine()
    {
        // Vérifier si un panneau est déjà en cours de création
        if (SettingsManager.Instance != null && SettingsManager.Instance.settingsPanel != null)
        {
            Debug.Log("[SettingsPanelBuilder] ⚠️ Un panneau existe déjà, destruction avant recréation");
            Destroy(SettingsManager.Instance.settingsPanel);
            SettingsManager.Instance.settingsPanel = null;
            SettingsManager.Instance.darkBackground = null;
            SettingsManager.Instance.closeButton = null;
            // Attendre une frame pour que la destruction soit complète
            yield return null;
        }
        
        // Vérifier qu'on n'est pas déjà en train de créer un panneau
        // (protection contre les appels multiples)
        if (isBuildingPanel)
        {
            yield break;
        }
        
        isBuildingPanel = true;

        // Vérifier que parentCanvas est défini
        if (parentCanvas == null)
        {
            parentCanvas = GetComponentInParent<Canvas>();
            if (parentCanvas == null)
            {
                parentCanvas = FindFirstObjectByType<Canvas>();
            }
        }

        if (parentCanvas == null)
        {
            Debug.LogError("[SettingsPanelBuilder] ❌ Canvas parent introuvable ! Impossible de créer le panneau.");
            yield break;
        }

        // Charger la configuration depuis GeneralConfigManager
        var config = GeneralConfigManager.Instance?.GetConfig();
        if (config != null && config.settingsPanelConfig != null)
        {
            panelConfig = config.settingsPanelConfig;
            
            // Charger la taille du panneau depuis la config
            if (panelConfig.panelSize != Vector2.zero)
            {
                panelSize = panelConfig.panelSize;
            }
            
            // Charger le rayon des coins
            if (panelConfig.cornerRadius > 0)
            {
                cornerRadius = panelConfig.cornerRadius;
            }
            
            // Charger la couleur de fond du panneau
            if (!string.IsNullOrEmpty(panelConfig.backgroundColor))
            {
                ColorUtility.TryParseHtmlString(panelConfig.backgroundColor, out panelBackgroundColor);
            }
            
            // Charger le bouton fermer
            if (panelConfig.closeButton != null && !string.IsNullOrEmpty(panelConfig.closeButton.imageUrl))
            {
                string closeUrl = GeneralConfigManager.Instance.GetUIUrl(panelConfig.closeButton.imageUrl);
                yield return StartCoroutine(LoadSpriteFromUrl(closeUrl, (sprite) => closeButtonSprite = sprite));
            }
            
            // Charger les couleurs depuis la config
            if (!string.IsNullOrEmpty(panelConfig.darkBackgroundColor))
            {
                ColorUtility.TryParseHtmlString(panelConfig.darkBackgroundColor, out darkBackgroundColor);
            }
            
            // Header config
            if (panelConfig.header != null)
            {
                if (!string.IsNullOrEmpty(panelConfig.header.backgroundColor))
                {
                    ColorUtility.TryParseHtmlString(panelConfig.header.backgroundColor, out headerBackgroundColor);
                }
                
                if (panelConfig.header.height > 0)
                {
                    headerHeight = panelConfig.header.height;
                }
                
                if (panelConfig.header.cornerRadius > 0)
                {
                    // Le cornerRadius du header sera utilisé dans CreateHeaderWithTabs
                }
                
                Debug.Log($"[SettingsPanelBuilder] Header config: height={headerHeight}, cornerRadius={panelConfig.header.cornerRadius}");
            }
            
            // Charger la police pour les onglets
            if (panelConfig.tabs?.normal != null && !string.IsNullOrEmpty(panelConfig.tabs.normal.fontName))
            {
                tabFont = Resources.Load<TMP_FontAsset>($"Fonts/{panelConfig.tabs.normal.fontName}");
                if (tabFont == null)
                {
                    tabFont = Resources.Load<TMP_FontAsset>("Fonts/Anton-Regular SDF");
                }
            }
        }
        
        Debug.Log($"[SettingsPanelBuilder] Canvas parent trouvé: {parentCanvas.name}, panelSize: {panelSize}");

        // S'assurer qu'un EventSystem existe pour les interactions UI
        EnsureEventSystem();

        // 1. GameObject racine
        GameObject settingsPanel = new GameObject("SettingsPanel");
        settingsPanel.transform.SetParent(parentCanvas.transform, false);
        
        // Réinitialiser complètement la transformation
        settingsPanel.transform.localPosition = Vector3.zero;
        settingsPanel.transform.localRotation = Quaternion.identity;
        settingsPanel.transform.localScale = Vector3.one;
        
        RectTransform panelRect = settingsPanel.AddComponent<RectTransform>();
        panelRect.anchorMin = Vector2.zero;
        panelRect.anchorMax = Vector2.one;
        panelRect.pivot = new Vector2(0.5f, 0.5f);
        panelRect.offsetMin = Vector2.zero;
        panelRect.offsetMax = Vector2.zero;
        panelRect.anchoredPosition = Vector2.zero;
        panelRect.localScale = Vector3.one;
        
        CanvasGroup canvasGroup = settingsPanel.AddComponent<CanvasGroup>();
        canvasGroup.alpha = 1f;
        canvasGroup.interactable = true;
        canvasGroup.blocksRaycasts = true;
        
        Canvas settingsCanvas = settingsPanel.AddComponent<Canvas>();
        settingsCanvas.overrideSorting = true;
        settingsCanvas.sortingOrder = 10000; // Très élevé pour être au-dessus de tout
        settingsCanvas.renderMode = RenderMode.ScreenSpaceOverlay; // IMPORTANT : Même mode que le Canvas parent
        
        // Récupérer les paramètres du CanvasScaler du Canvas parent pour les réutiliser
        CanvasScaler parentScaler = parentCanvas.GetComponent<CanvasScaler>();
        CanvasScaler scaler = settingsPanel.AddComponent<CanvasScaler>();
        
        if (parentScaler != null)
        {
            // Copier les paramètres du Canvas parent
            scaler.uiScaleMode = parentScaler.uiScaleMode;
            scaler.referenceResolution = parentScaler.referenceResolution;
            scaler.screenMatchMode = parentScaler.screenMatchMode;
            scaler.matchWidthOrHeight = parentScaler.matchWidthOrHeight;
            Debug.Log($"[SettingsPanelBuilder] ✅ CanvasScaler configuré avec les paramètres du Canvas parent: {parentScaler.referenceResolution}, matchWidthOrHeight: {parentScaler.matchWidthOrHeight}");
        }
        else
        {
            // Valeurs par défaut si le Canvas parent n'a pas de CanvasScaler
            scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
            scaler.referenceResolution = new Vector2(1920, 1080);
            scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
            scaler.matchWidthOrHeight = 0.5f;
            Debug.Log("[SettingsPanelBuilder] ⚠️ Canvas parent n'a pas de CanvasScaler, utilisation des valeurs par défaut");
        }
        
        GraphicRaycaster raycaster = settingsPanel.AddComponent<GraphicRaycaster>();
        raycaster.enabled = true; // S'assurer qu'il est activé
        Debug.Log($"[SettingsPanelBuilder] ✅ GraphicRaycaster ajouté et activé");
        
        Debug.Log($"[SettingsPanelBuilder] ✅ SettingsPanel racine créé - Parent: {parentCanvas.name}, Position: {panelRect.anchoredPosition}, Scale: {panelRect.localScale}");
        
        // 2. Dark Background (DOIT être créé en premier pour être en arrière-plan)
        GameObject darkBg = CreateDarkBackground(settingsPanel.transform);
        darkBg.transform.SetAsFirstSibling(); // S'assurer qu'il est en arrière-plan
        
        // 3. Panel Container (rectangle central beige)
        // IMPORTANT : Créer le panelContainer APRÈS le darkBackground pour qu'il soit testé en premier pour les raycasts
        GameObject panelContainer = CreatePanelContainer(settingsPanel.transform);
        panelContainer.transform.SetAsLastSibling(); // S'assurer qu'il est au-dessus du fond ET testé en premier pour les raycasts
        
        // 4. Header avec onglets + croix
        GameObject headerBar = CreateHeaderWithTabs(panelContainer.transform, out GameObject closeButton);
        
        // 5. Content Area
        GameObject contentArea = CreateContentArea(panelContainer.transform);
        
        // 6. Créer les 5 onglets
        Debug.Log("[SettingsPanelBuilder] Création des onglets...");
        GameObject scoresTab = CreateScoresTab(contentArea.transform);
        Debug.Log($"[SettingsPanelBuilder] ScoresTab créé: {scoresTab != null}, active: {scoresTab.activeSelf}");
        GameObject classementTab = CreateClassementTab(contentArea.transform);
        
        Debug.Log("[SettingsPanelBuilder] 🎮 JOUER: Avant CreateQuetesTab");
        GameObject quetesTab = CreateQuetesTab(contentArea.transform);
        Debug.Log($"[SettingsPanelBuilder] 🎮 JOUER: QuetesTab créé: {quetesTab != null}, QuetesTab component: {quetesTab?.GetComponent<QuetesTab>() != null}");
        
        GameObject parametresTab = CreateParametresTab(contentArea.transform);
        // 🔥 DEBUG tab supprimé (demandé): on garde uniquement 4 onglets (SCORES, CLASSEMENT, QUÊTES, PARAMÈTRES)
        
        // 7. S'assurer que SettingsManager.Instance existe
        // Attendre un peu pour que SettingsManager.Instance soit initialisé
        SettingsManager settingsManager = null;
        int attempts = 0;
        while (settingsManager == null && attempts < 10)
        {
            settingsManager = SettingsManager.Instance;
            if (settingsManager == null)
            {
                yield return new WaitForSeconds(0.1f);
                attempts++;
            }
        }
        
        if (settingsManager == null)
        {
            // Créer un GameObject pour SettingsManager s'il n'existe pas
            GameObject settingsManagerObj = new GameObject("SettingsManager");
            DontDestroyOnLoad(settingsManagerObj);
            settingsManager = settingsManagerObj.AddComponent<SettingsManager>();
            // Attendre que Awake() soit appelé
            yield return new WaitForSeconds(0.1f);
            Debug.Log("[SettingsPanelBuilder] ✅ Nouveau SettingsManager créé");
        }
        else
        {
            Debug.Log("[SettingsPanelBuilder] ✅ Utilisation de SettingsManager.Instance existant");
        }
        
        Debug.Log($"[SettingsPanelBuilder] SettingsManager: {settingsManager != null}");
        
        // Mettre à jour les références
        if (settingsManager != null)
        {
            settingsManager.settingsPanel = settingsPanel;
            settingsManager.darkBackground = darkBg;
            
            // S'assurer que le bouton fermer est bien assigné
            Button closeBtnComponent = closeButton.GetComponent<Button>();
            if (closeBtnComponent != null)
            {
                settingsManager.closeButton = closeBtnComponent;
                // Réassigner le listener dans SettingsManager aussi (au cas où)
                closeBtnComponent.onClick.RemoveAllListeners();
                closeBtnComponent.onClick.AddListener(() => {
                    Debug.Log("[SettingsPanelBuilder] Réassignation du listener du bouton fermer");
                    if (SettingsManager.Instance != null)
                    {
                        SettingsManager.Instance.CloseSettings();
                    }
                });
                Debug.Log("[SettingsPanelBuilder] ✅ Bouton fermer assigné à SettingsManager");
            }
            else
            {
                Debug.LogError("[SettingsPanelBuilder] ❌ Le bouton fermer n'a pas de composant Button !");
            }
            
            settingsManager.tabs.Clear();
            SettingsTab scoresTabComponent = scoresTab.GetComponent<SettingsTab>();
            Debug.Log($"[SettingsPanelBuilder] ScoresTab component: {scoresTabComponent != null}, type: {scoresTabComponent?.GetType().Name}");
            
            if (scoresTabComponent == null)
            {
                Debug.LogError("[SettingsPanelBuilder] ❌ ScoresTab component est null !");
            }
            
            // Ordre des onglets : QUETES, CLASSEMENT, PARAMETRES, SCORES
            settingsManager.tabs.Add(quetesTab.GetComponent<SettingsTab>());
            settingsManager.tabs.Add(classementTab.GetComponent<SettingsTab>());
            settingsManager.tabs.Add(parametresTab.GetComponent<SettingsTab>());
            settingsManager.tabs.Add(scoresTabComponent);
            
            Debug.Log($"[SettingsPanelBuilder] ✅ {settingsManager.tabs.Count} onglets enregistrés");
            Debug.Log($"[SettingsPanelBuilder] ScoresTab GameObject active: {scoresTab.activeSelf}, activeInHierarchy: {scoresTab.activeInHierarchy}");
            
            // Important : Les boutons d'onglets seront dans le header
            settingsManager.tabsContainer = headerBar.transform.Find("TabsContainer");
            settingsManager.contentContainer = contentArea.transform;
            
            Debug.Log($"[SettingsPanelBuilder] tabsContainer assigné: {settingsManager.tabsContainer != null}, childCount: {(settingsManager.tabsContainer != null ? settingsManager.tabsContainer.childCount : 0)}");
            
            // Activer le premier onglet (QuetesTab) par défaut
            if (settingsManager.tabs.Count > 0)
            {
                Debug.Log("[SettingsPanelBuilder] Activation du premier onglet QUÊTES par défaut (ShowTab(0))");
                // S'assurer que tabsContainer est bien assigné avant d'appeler ShowTab
                if (settingsManager.tabsContainer == null)
                {
                    Debug.LogError("[SettingsPanelBuilder] ❌ tabsContainer est null, impossible d'activer le premier onglet");
                }
                else
                {
                    settingsManager.ShowTab(0);
                    Debug.Log($"[SettingsPanelBuilder] Après ShowTab(0) - Premier onglet active: {settingsManager.tabs[0].gameObject.activeSelf}, activeInHierarchy: {settingsManager.tabs[0].gameObject.activeInHierarchy}");
                }
            }
            else
            {
                Debug.LogError($"[SettingsPanelBuilder] ❌ Impossible d'activer le premier onglet - tabs.Count: {settingsManager.tabs.Count}");
            }
            
            Debug.Log("[SettingsPanelBuilder] ✅ Références mises à jour dans SettingsManager");
        }
        else
        {
            Debug.LogError("[SettingsPanelBuilder] ❌ SettingsManager est NULL ! Impossible d'assigner le panneau.");
        }
        
        // Vérifier que le fond sombre est bien présent et visible
        if (darkBg != null)
        {
            Image darkBgImage = darkBg.GetComponent<Image>();
            if (darkBgImage != null)
            {
                Debug.Log($"[SettingsPanelBuilder] ✅ DarkBackground créé - Couleur: {darkBgImage.color}, RaycastTarget: {darkBgImage.raycastTarget}");
            }
            else
            {
                Debug.LogError("[SettingsPanelBuilder] ❌ DarkBackground n'a pas d'Image !");
            }
        }
        else
        {
            Debug.LogError("[SettingsPanelBuilder] ❌ DarkBackground est NULL !");
        }
        
        // Vérifier la taille du panneau
        RectTransform containerRect = panelContainer.GetComponent<RectTransform>();
        if (containerRect != null)
        {
            Debug.Log($"[SettingsPanelBuilder] ✅ PanelContainer - Taille: {containerRect.sizeDelta}, Position: {containerRect.anchoredPosition}, Anchors: {containerRect.anchorMin} - {containerRect.anchorMax}");
        }
        
        // Forcer une mise à jour complète du layout après création
        Canvas.ForceUpdateCanvases();
        LayoutRebuilder.ForceRebuildLayoutImmediate(containerRect);
        
        // Désactiver au départ
        settingsPanel.SetActive(false);
        
        isBuildingPanel = false; // Réinitialiser le flag
        
        Debug.Log("[SettingsPanelBuilder] ✅ Panneau Settings créé avec succès !");
    }
    
    /// <summary>
    /// S'assure qu'un EventSystem existe pour les interactions UI
    /// </summary>
    private void EnsureEventSystem()
    {
        // Vérifier si un EventSystem existe et est actif
        UnityEngine.EventSystems.EventSystem eventSystem = UnityEngine.EventSystems.EventSystem.current;
        
        if (eventSystem == null || !eventSystem.enabled)
        {
            // Chercher un EventSystem existant mais désactivé
            eventSystem = FindFirstObjectByType<UnityEngine.EventSystems.EventSystem>();
            
            if (eventSystem != null && !eventSystem.enabled)
            {
                // Réactiver l'EventSystem existant
                eventSystem.enabled = true;
                Debug.Log("[SettingsPanelBuilder] ✅ EventSystem existant réactivé");
            }
            else if (eventSystem == null)
            {
                // Créer un nouvel EventSystem
                GameObject eventSystemObj = new GameObject("EventSystem");
                eventSystem = eventSystemObj.AddComponent<UnityEngine.EventSystems.EventSystem>();
                Debug.Log("[SettingsPanelBuilder] ✅ Nouvel EventSystem créé");
            }
        }
        else
        {
            Debug.Log("[SettingsPanelBuilder] ✅ EventSystem actif trouvé");
        }
        
        // S'assurer qu'il y a un InputSystemUIInputModule (compatible avec le nouveau Input System)
        if (eventSystem != null)
        {
            var inputModule = eventSystem.GetComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
            
            if (inputModule == null)
            {
                // Vérifier s'il y a un StandaloneInputModule (à supprimer)
                var standaloneModule = eventSystem.GetComponent<UnityEngine.EventSystems.StandaloneInputModule>();
                if (standaloneModule != null)
                {
                    standaloneModule.enabled = false;
                    Destroy(standaloneModule);
                    Debug.Log("[SettingsPanelBuilder] ⚠️ StandaloneInputModule supprimé");
                }
                
                // Ajouter InputSystemUIInputModule
                eventSystem.gameObject.AddComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
                Debug.Log("[SettingsPanelBuilder] ✅ InputSystemUIInputModule ajouté");
            }
            else
            {
                Debug.Log("[SettingsPanelBuilder] ✅ InputSystemUIInputModule déjà présent");
            }
            
            // Vérifier que l'EventSystem est bien actif
            Debug.Log($"[SettingsPanelBuilder] EventSystem status - enabled: {eventSystem.enabled}, gameObject.activeInHierarchy: {eventSystem.gameObject.activeInHierarchy}");
        }
        else
        {
            Debug.LogError("[SettingsPanelBuilder] ❌ EventSystem est null après création !");
        }
    }
    
    /// <summary>
    /// Charge un sprite depuis une URL
    /// </summary>
    private IEnumerator LoadSpriteFromUrl(string url, System.Action<Sprite> onComplete)
    {
        if (string.IsNullOrEmpty(url))
        {
            Debug.LogWarning("[SettingsPanelBuilder] URL vide pour le chargement du sprite");
            onComplete?.Invoke(null);
            yield break;
        }
        
        Debug.Log($"[SettingsPanelBuilder] 📥 Chargement sprite depuis: {url}");
        
        using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
        {
            yield return www.SendWebRequest();
            
            if (www.result == UnityWebRequest.Result.Success)
            {
                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),
                    100f
                );
                sprite.name = System.IO.Path.GetFileName(url);
                Debug.Log($"[SettingsPanelBuilder] ✅ Sprite chargé: {sprite.name} ({texture.width}x{texture.height})");
                onComplete?.Invoke(sprite);
            }
            else
            {
                Debug.LogError($"[SettingsPanelBuilder] ❌ Erreur chargement sprite depuis {url}: {www.error}");
                onComplete?.Invoke(null);
            }
        }
    }
    
    GameObject CreateDarkBackground(Transform parent)
    {
        GameObject darkBg = new GameObject("DarkBackground");
        darkBg.transform.SetParent(parent, false);
        
        RectTransform rect = darkBg.AddComponent<RectTransform>();
        rect.anchorMin = Vector2.zero;
        rect.anchorMax = Vector2.one;
        rect.offsetMin = Vector2.zero;
        rect.offsetMax = Vector2.zero;
        
        Image image = darkBg.AddComponent<Image>();
        image.color = darkBackgroundColor;
        image.raycastTarget = true; // IMPORTANT : Bloquer les raycasts vers la scène
        
        // Le darkBackground bloque les raycasts vers la scène
        // MAIS le panelContainer sera au-dessus dans la hiérarchie (SetAsLastSibling)
        // et recevra les clics en priorité grâce à l'ordre de rendu
        CanvasGroup darkBgGroup = darkBg.AddComponent<CanvasGroup>();
        darkBgGroup.blocksRaycasts = true; // Bloquer les raycasts vers la scène
        darkBgGroup.interactable = false; // Ne pas permettre l'interaction avec le fond
        
        Debug.Log("[SettingsPanelBuilder] DarkBackground créé avec blocage des raycasts");
        
        return darkBg;
    }
    
    GameObject CreatePanelContainer(Transform parent)
    {
        // Créer un conteneur pour tout (ombre + panneau) comme LoginPopup
        GameObject outerContainer = new GameObject("PanelOuterContainer");
        outerContainer.transform.SetParent(parent, false);
        
        RectTransform outerRect = outerContainer.AddComponent<RectTransform>();
        outerRect.anchorMin = new Vector2(0.5f, 0.5f);
        outerRect.anchorMax = new Vector2(0.5f, 0.5f);
        outerRect.pivot = new Vector2(0.5f, 0.5f);
        outerRect.sizeDelta = panelSize;
        outerRect.anchoredPosition = Vector2.zero;
        
        // Créer l'ombre comme un élément séparé DERRIÈRE le panneau
        if (panelConfig?.shadow != null && panelConfig.shadow.enabled)
        {
            GameObject shadowObj = new GameObject("PanelShadow");
            shadowObj.transform.SetParent(outerContainer.transform, false);
            
            RectTransform shadowRect = shadowObj.AddComponent<RectTransform>();
            shadowRect.anchorMin = Vector2.zero;
            shadowRect.anchorMax = Vector2.one;
            shadowRect.sizeDelta = Vector2.zero;
            // Décaler l'ombre selon la config
            shadowRect.anchoredPosition = new Vector2(panelConfig.shadow.offsetX, -panelConfig.shadow.offsetY);
            
            Image shadowImage = shadowObj.AddComponent<Image>();
            Color shadowColor = HexToColor(panelConfig.shadow.color);
            shadowImage.sprite = CreateRoundedColorSprite((int)panelSize.x, (int)panelSize.y, cornerRadius, shadowColor);
            shadowImage.color = Color.white;
            shadowImage.type = Image.Type.Simple; // Simple, pas Sliced
            shadowImage.raycastTarget = false;
            
            // L'ombre doit être en premier (derrière le panneau)
            shadowObj.transform.SetAsFirstSibling();
            
            Debug.Log($"[SettingsPanelBuilder] ✅ Ombre panneau créée: {panelConfig.shadow.color}, offset: ({panelConfig.shadow.offsetX}, {panelConfig.shadow.offsetY})");
        }
        
        // Créer le panneau principal
        GameObject container = new GameObject("PanelContainer");
        container.transform.SetParent(outerContainer.transform, false);
        
        RectTransform rect = container.AddComponent<RectTransform>();
        
        // Remplir tout le conteneur parent
        rect.anchorMin = Vector2.zero;
        rect.anchorMax = Vector2.one;
        rect.sizeDelta = Vector2.zero;
        rect.offsetMin = Vector2.zero;
        rect.offsetMax = Vector2.zero;
        rect.localScale = Vector3.one;
        rect.localRotation = Quaternion.identity;
        
        Image image = container.AddComponent<Image>();
        
        // Créer un sprite arrondi avec la couleur de fond (taille exacte comme LoginPopup)
        image.sprite = CreateRoundedColorSprite((int)panelSize.x, (int)panelSize.y, cornerRadius, panelBackgroundColor);
        image.color = Color.white;
        image.type = Image.Type.Simple; // Simple, pas Sliced (comme LoginPopup)
        image.raycastTarget = true; // Bloquer les clics sur le panneau
        
        Debug.Log($"[SettingsPanelBuilder] ✅ Fond du panneau créé avec coins arrondis: {cornerRadius}px");
        
        // Forcer une mise à jour du layout immédiatement
        LayoutRebuilder.ForceRebuildLayoutImmediate(rect);
        
        Debug.Log($"[SettingsPanelBuilder] ✅ PanelContainer créé - Position: {rect.anchoredPosition}, Taille: {rect.sizeDelta}, Scale: {rect.localScale}, WorldPosition: {rect.position}");
        
        return container;
    }
    
    GameObject CreateHeaderWithTabs(Transform parent, out GameObject closeButtonOut)
    {
        GameObject header = new GameObject("HeaderBar");
        header.transform.SetParent(parent, false);
        
        RectTransform rect = header.AddComponent<RectTransform>();
        rect.anchorMin = new Vector2(0, 1);
        rect.anchorMax = new Vector2(1, 1);
        rect.pivot = new Vector2(0.5f, 1);
        rect.sizeDelta = new Vector2(0, headerHeight);
        rect.anchoredPosition = Vector2.zero;
        
        Image image = header.AddComponent<Image>();
        
        // Créer un sprite arrondi uniquement en haut pour le header (taille exacte comme LoginPopup)
        float headerCornerRadius = panelConfig?.header?.cornerRadius ?? cornerRadius;
        image.sprite = CreateRoundedTopSprite((int)panelSize.x, (int)headerHeight, headerCornerRadius, headerBackgroundColor);
        image.color = Color.white;
        image.type = Image.Type.Simple; // Simple, pas Sliced
        
        // Container pour les onglets (centré)
        GameObject tabsContainer = new GameObject("TabsContainer");
        tabsContainer.transform.SetParent(header.transform, false);
        
        RectTransform tabsRect = tabsContainer.AddComponent<RectTransform>();
        tabsRect.anchorMin = new Vector2(0, 0);
        tabsRect.anchorMax = new Vector2(1, 1);
        
        // Marges depuis la config
        float marginLeft = panelConfig?.tabs?.marginLeft ?? 20f;
        float marginRight = panelConfig?.tabs?.marginRight ?? 80f;
        float tabsVerticalPadding = 10f; // Padding vertical des onglets dans le header
        tabsRect.offsetMin = new Vector2(marginLeft, tabsVerticalPadding);
        tabsRect.offsetMax = new Vector2(-marginRight, -tabsVerticalPadding);
        
        HorizontalLayoutGroup layout = tabsContainer.AddComponent<HorizontalLayoutGroup>();
        layout.spacing = panelConfig?.tabs?.spacing ?? 20f;
        layout.childAlignment = TextAnchor.MiddleCenter;
        layout.childControlWidth = false;
        layout.childControlHeight = false;  // NE PAS étirer la hauteur des boutons
        layout.childForceExpandWidth = false;
        layout.childForceExpandHeight = false;  // Garder la hauteur définie (52px)
        
        // Créer les 4 boutons d'onglets (DEBUG supprimé) et répartir l'espace avec des "spacers" flexibles
        // pour que l'en-tête soit bien équilibré sur toute la largeur.
        // Ordre : QUETES, CLASSEMENT, PARAMETRES, SCORES
        CreateTabSpacer(tabsContainer.transform);
        CreateTabButton(tabsContainer.transform, "QUÊTES", 0);
        CreateTabSpacer(tabsContainer.transform);
        CreateTabButton(tabsContainer.transform, "CLASSEMENT", 1);
        CreateTabSpacer(tabsContainer.transform);
        CreateTabButton(tabsContainer.transform, "PARAMÈTRES", 2);
        CreateTabSpacer(tabsContainer.transform);
        CreateTabButton(tabsContainer.transform, "SCORES", 3);
        CreateTabSpacer(tabsContainer.transform);
        
        // Bouton de fermeture (croix en haut à droite)
        GameObject closeButton = CreateCloseButtonInHeader(header.transform);
        closeButtonOut = closeButton;
        
        return header;
    }

    private void CreateTabSpacer(Transform parent)
    {
        GameObject spacer = new GameObject("TabSpacer");
        spacer.transform.SetParent(parent, false);
        RectTransform rt = spacer.AddComponent<RectTransform>();
        rt.sizeDelta = Vector2.zero;
        LayoutElement le = spacer.AddComponent<LayoutElement>();
        le.minWidth = 0f;
        le.preferredWidth = 0f;
        le.flexibleWidth = 1f;
    }
    
    void CreateTabButton(Transform parent, string label, int index)
    {
        // Récupérer les configs des onglets
        var normalConfig = panelConfig?.tabs?.normal;
        var selectedConfig = panelConfig?.tabs?.selected;
        var hoverConfig = panelConfig?.tabs?.hover;
        
        // Couleurs depuis la config
        Color normalTextColor = normalConfig != null ? HexToColor(normalConfig.textColor) : new Color(0.47f, 0.4f, 0.37f, 1f);
        Color selectedBgColor = selectedConfig != null ? HexToColor(selectedConfig.backgroundColor) : new Color(0.64f, 0.25f, 1f, 1f);
        Color selectedTextColor = selectedConfig != null ? HexToColor(selectedConfig.textColor) : Color.white;
        Color hoverBgColor = hoverConfig != null ? HexToColor(hoverConfig.backgroundColor) : new Color(0.78f, 0.49f, 1f, 1f);
        Color hoverTextColor = hoverConfig != null ? HexToColor(hoverConfig.textColor) : Color.white;
        
        // Taille et padding depuis la config
        float fontSize = normalConfig?.fontSize ?? 22f;
        float paddingH = selectedConfig?.paddingHorizontal ?? 25f;
        float paddingV = selectedConfig?.paddingVertical ?? 10f;
        
        Debug.Log($"[SettingsPanelBuilder] Tab config: fontSize={fontSize}, paddingH={paddingH}, paddingV={paddingV}");
        
        // Calculer la taille du bouton (fontSize = hauteur du texte)
        float buttonWidth = label.Length * (fontSize * 0.55f) + paddingH * 2;
        float buttonHeight = fontSize + paddingV * 2;
        
        Debug.Log($"[SettingsPanelBuilder] Tab '{label}': width={buttonWidth}, height={buttonHeight}");
        
        // Le cornerRadius doit être limité à la moitié de la hauteur pour une forme "pilule" propre
        float tabCornerRadius = selectedConfig?.cornerRadius ?? 25f;
        tabCornerRadius = Mathf.Min(tabCornerRadius, buttonHeight / 2f);
        
        GameObject tabButton = new GameObject($"TabButton_{label}");
        tabButton.transform.SetParent(parent, false);
        
        RectTransform rect = tabButton.AddComponent<RectTransform>();
        rect.sizeDelta = new Vector2(buttonWidth, buttonHeight);
        
        LayoutElement layoutElement = tabButton.AddComponent<LayoutElement>();
        layoutElement.preferredWidth = buttonWidth;
        layoutElement.preferredHeight = buttonHeight;
        
        Image image = tabButton.AddComponent<Image>();
        image.raycastTarget = true;
        
        // Créer un sprite BLANC avec coins arrondis à HAUTE RÉSOLUTION (4x) pour des bords lisses
        // Comme les boutons validationPurple de LoginPopup (300x80 pixels)
        int spriteScale = 4;
        int spriteWidth = (int)buttonWidth * spriteScale;
        int spriteHeight = (int)buttonHeight * spriteScale;
        float spriteRadius = tabCornerRadius * spriteScale;
        
        Debug.Log($"[SettingsPanelBuilder] Tab '{label}' sprite: {spriteWidth}x{spriteHeight}px, radius={spriteRadius}px (UI: {buttonWidth}x{buttonHeight}, cornerRadius={tabCornerRadius})");
        
        image.sprite = CreateRoundedColorSprite(spriteWidth, spriteHeight, spriteRadius, Color.white);
        image.type = Image.Type.Simple;
        image.color = Color.clear; // Transparent par défaut
        
        Button button = tabButton.AddComponent<Button>();
        button.targetGraphic = image;
        
        // IMPORTANT : Désactiver les transitions automatiques du Button
        // On gère les couleurs manuellement via EventTrigger et SettingsManager
        button.transition = Selectable.Transition.None;
        
        // Ajouter le listener
        button.onClick.AddListener(() => {
            Debug.Log($"[TabButton] Clic sur {label}");
            if (SettingsManager.Instance != null)
            {
                SettingsManager.Instance.ShowTab(index);
            }
        });
        
        // Ajouter un EventTrigger pour gérer le survol manuellement
        EventTrigger trigger = tabButton.AddComponent<EventTrigger>();
        
        // Event PointerEnter (survol)
        EventTrigger.Entry entryEnter = new EventTrigger.Entry();
        entryEnter.eventID = EventTriggerType.PointerEnter;
        entryEnter.callback.AddListener((data) => {
            if (SettingsManager.Instance != null && SettingsManager.Instance.GetActiveTabIndex() != index)
            {
                image.color = hoverBgColor;
                TextMeshProUGUI textComp = tabButton.GetComponentInChildren<TextMeshProUGUI>();
                if (textComp != null)
                {
                    textComp.color = hoverTextColor;
                }
            }
        });
        trigger.triggers.Add(entryEnter);
        
        // Event PointerExit (fin du survol)
        EventTrigger.Entry entryExit = new EventTrigger.Entry();
        entryExit.eventID = EventTriggerType.PointerExit;
        entryExit.callback.AddListener((data) => {
            if (SettingsManager.Instance != null && SettingsManager.Instance.GetActiveTabIndex() != index)
            {
                image.color = Color.clear;
                TextMeshProUGUI textComp = tabButton.GetComponentInChildren<TextMeshProUGUI>();
                if (textComp != null)
                {
                    textComp.color = normalTextColor;
                }
            }
        });
        trigger.triggers.Add(entryExit);
        
        // Texte
        GameObject textObj = new GameObject("Text");
        textObj.transform.SetParent(tabButton.transform, false);
        
        RectTransform textRect = textObj.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.offsetMin = Vector2.zero;
        textRect.offsetMax = Vector2.zero;
        
        TextMeshProUGUI text = textObj.AddComponent<TextMeshProUGUI>();
        text.text = label;
        text.fontSize = fontSize;
        text.fontStyle = FontStyles.Normal;
        text.alignment = TextAlignmentOptions.Center;
        text.color = normalTextColor;
        
        // Appliquer la police depuis la config
        if (tabFont != null)
        {
            text.font = tabFont;
        }
    }
    
    GameObject CreateCloseButtonInHeader(Transform parent)
    {
        // Récupérer la config du bouton fermer
        float buttonSize = panelConfig?.closeButton?.size ?? 50f;
        float marginRight = panelConfig?.closeButton?.marginRight ?? 15f;
        
        Debug.Log($"[SettingsPanelBuilder] CloseButton config: size={buttonSize}, marginRight={marginRight}");
        
        GameObject closeBtn = new GameObject("CloseButton");
        closeBtn.transform.SetParent(parent, false);
        
        RectTransform rect = closeBtn.AddComponent<RectTransform>();
        rect.anchorMin = new Vector2(1, 0.5f);
        rect.anchorMax = new Vector2(1, 0.5f);
        rect.pivot = new Vector2(0.5f, 0.5f);
        rect.sizeDelta = new Vector2(buttonSize, buttonSize);
        rect.anchoredPosition = new Vector2(-marginRight - buttonSize/2, 0);
        
        Image image = closeBtn.AddComponent<Image>();
        image.raycastTarget = true; // IMPORTANT : Permettre les clics
        
        // Utiliser le sprite du bouton fermer si disponible, sinon créer un cercle
        if (closeButtonSprite != null)
        {
            image.sprite = closeButtonSprite;
            image.type = Image.Type.Simple;
            image.color = Color.white;  // Pas de teinte sur le sprite
            Debug.Log($"[SettingsPanelBuilder] ✅ Bouton fermer: sprite '{closeButtonSprite.name}' utilisé");
        }
        else
        {
            image.color = new Color(0.7f, 0.5f, 0.85f, 1f); // Violet par défaut (fallback)
            image.sprite = CreateCircleSprite();
            Debug.Log("[SettingsPanelBuilder] ⚠️ Bouton fermer: sprite par défaut utilisé (sprite non chargé)");
        }
        
        Button button = closeBtn.AddComponent<Button>();
        button.targetGraphic = image;
        
        // Couleurs du bouton : blanc par défaut (pas de voile), effet hover léger
        ColorBlock colors = button.colors;
        colors.normalColor = Color.white;  // Pas de teinte sur le sprite
        colors.highlightedColor = new Color(0.9f, 0.9f, 0.9f, 1f);  // Légèrement grisé au hover
        colors.pressedColor = new Color(0.8f, 0.8f, 0.8f, 1f);  // Plus grisé au clic
        button.colors = colors;
        
        // Le listener sera assigné plus tard dans BuildSettingsPanelCoroutine
        // pour éviter les conflits avec SettingsManager
        Debug.Log("[SettingsPanelBuilder] ✅ Bouton fermer créé");
        
        // Icône X uniquement si le sprite n'est pas chargé (le sprite contient déjà l'icône)
        if (closeButtonSprite == null)
        {
            GameObject icon = CreateXIcon(closeBtn.transform);
        }
        
        return closeBtn;
    }
    
    GameObject CreateXIcon(Transform parent)
    {
        GameObject xIcon = new GameObject("XIcon");
        xIcon.transform.SetParent(parent, false);
        
        RectTransform rect = xIcon.AddComponent<RectTransform>();
        rect.anchorMin = Vector2.zero;
        rect.anchorMax = Vector2.one;
        rect.offsetMin = new Vector2(15, 15);
        rect.offsetMax = new Vector2(-15, -15);
        
        // Ligne 1
        GameObject line1 = new GameObject("Line1");
        line1.transform.SetParent(xIcon.transform, false);
        RectTransform line1Rect = line1.AddComponent<RectTransform>();
        line1Rect.anchorMin = new Vector2(0.5f, 0.5f);
        line1Rect.anchorMax = new Vector2(0.5f, 0.5f);
        line1Rect.pivot = new Vector2(0.5f, 0.5f);
        line1Rect.sizeDelta = new Vector2(35, 4);
        line1Rect.localEulerAngles = new Vector3(0, 0, 45);
        Image line1Image = line1.AddComponent<Image>();
        line1Image.color = Color.white;
        
        // Ligne 2
        GameObject line2 = new GameObject("Line2");
        line2.transform.SetParent(xIcon.transform, false);
        RectTransform line2Rect = line2.AddComponent<RectTransform>();
        line2Rect.anchorMin = new Vector2(0.5f, 0.5f);
        line2Rect.anchorMax = new Vector2(0.5f, 0.5f);
        line2Rect.pivot = new Vector2(0.5f, 0.5f);
        line2Rect.sizeDelta = new Vector2(35, 4);
        line2Rect.localEulerAngles = new Vector3(0, 0, -45);
        Image line2Image = line2.AddComponent<Image>();
        line2Image.color = Color.white;
        
        return xIcon;
    }
    
    GameObject CreateContentArea(Transform parent)
    {
        GameObject contentArea = new GameObject("ContentArea");
        contentArea.transform.SetParent(parent, false);
        
        RectTransform rect = contentArea.AddComponent<RectTransform>();
        float contentPadding = panelConfig?.content?.padding ?? 20f;
        rect.anchorMin = new Vector2(0, 0);
        rect.anchorMax = new Vector2(1, 1);
        rect.offsetMin = new Vector2(contentPadding, contentPadding);
        rect.offsetMax = new Vector2(-contentPadding, -headerHeight - contentPadding);
        
        return contentArea;
    }
    
    // Créer les 4 onglets (contenus vides pour l'instant)
    
    GameObject CreateScoresTab(Transform parent)
    {
        GameObject tab = new GameObject("ScoresTab");
        tab.transform.SetParent(parent, false);
        
        RectTransform rect = tab.AddComponent<RectTransform>();
        rect.anchorMin = Vector2.zero;
        rect.anchorMax = Vector2.one;
        rect.offsetMin = Vector2.zero;
        rect.offsetMax = Vector2.zero;
        
        // Ajouter le composant ScoresTab qui va créer son contenu dans Awake()
        ScoresTab scoresTab = tab.AddComponent<ScoresTab>();
        
        Debug.Log("[SettingsPanelBuilder] ScoresTab créé");
        
        return tab;
    }
    
    GameObject CreateClassementTab(Transform parent)
    {
        GameObject tab = new GameObject("ClassementTab");
        tab.transform.SetParent(parent, false);
        
        RectTransform rect = tab.AddComponent<RectTransform>();
        rect.anchorMin = Vector2.zero;
        rect.anchorMax = Vector2.one;
        rect.offsetMin = Vector2.zero;
        rect.offsetMax = Vector2.zero;
        
        // Ajouter le composant ClassementTab qui va créer son contenu dans Awake()
        ClassementTab classementTab = tab.AddComponent<ClassementTab>();
        
        return tab;
    }
    
    GameObject CreateQuetesTab(Transform parent)
    {
        Debug.Log("[SettingsPanelBuilder] 🎮 JOUER: CreateQuetesTab APPELÉ");
        
        GameObject tab = new GameObject("QuetesTab");
        tab.transform.SetParent(parent, false);
        
        RectTransform rect = tab.AddComponent<RectTransform>();
        rect.anchorMin = Vector2.zero;
        rect.anchorMax = Vector2.one;
        rect.offsetMin = Vector2.zero;
        rect.offsetMax = Vector2.zero;
        
        Debug.Log("[SettingsPanelBuilder] 🎮 JOUER: Ajout du composant QuetesTab...");
        // Ajouter le composant QuetesTab qui gère toute l'interface
        QuetesTab quetesTab = tab.AddComponent<QuetesTab>();
        Debug.Log($"[SettingsPanelBuilder] 🎮 JOUER: QuetesTab ajouté = {quetesTab != null}");
        
        return tab;
    }
    
    GameObject CreateParametresTab(Transform parent)
    {
        GameObject tab = new GameObject("ParametresTab");
        tab.transform.SetParent(parent, false);
        
        RectTransform rect = tab.AddComponent<RectTransform>();
        rect.anchorMin = Vector2.zero;
        rect.anchorMax = Vector2.one;
        rect.offsetMin = Vector2.zero;
        rect.offsetMax = Vector2.zero;
        
        // Récupération de la configuration depuis general-config.json
        var config = GeneralConfigManager.Instance?.GetConfig();
        var layoutConfig = config?.parametresTabConfig?.layout;
        
        VerticalLayoutGroup layout = tab.AddComponent<VerticalLayoutGroup>();
        
        // Utiliser les valeurs de la config si disponibles, sinon valeurs par défaut
        if (layoutConfig != null)
        {
            layout.padding = new RectOffset(
                (int)layoutConfig.paddingLeft,
                (int)layoutConfig.paddingRight,
                (int)layoutConfig.paddingTop,
                (int)layoutConfig.paddingBottom
            );
            layout.spacing = layoutConfig.spacing;
        }
        else
        {
            // Valeurs par défaut si la config n'est pas disponible
            layout.padding = new RectOffset(40, 40, 40, 40);
            layout.spacing = 30;
        }
        
        layout.childAlignment = TextAnchor.UpperCenter;
        layout.childControlWidth = false; // Ne pas étirer les boutons horizontalement
        layout.childControlHeight = false;
        layout.childForceExpandWidth = false; // Ne pas forcer l'expansion des boutons
        
        // Infos utilisateur (déplacées depuis l'onglet DEBUG): email (si connecté) + temps de jeu
        GameObject userInfoSection = CreateParametresUserInfoSection(tab.transform, out TextMeshProUGUI emailInfoText, out TextMeshProUGUI playTimeInfoText);

        // Son
        GameObject soundSection = CreateSoundSection(tab.transform);
        
        // Créer les boutons
        GameObject logoutButton = null;
        GameObject quitButton = null;
        
        if (UserDataManager.Instance != null && UserDataManager.Instance.IsLoggedIn())
        {
            logoutButton = CreateLogoutButton(tab.transform);
        }
        
        quitButton = CreateQuitButton(tab.transform);
        
        ParametresTab parametresTab = tab.AddComponent<ParametresTab>();
        parametresTab.soundToggle = soundSection.GetComponentInChildren<Toggle>();
        parametresTab.soundLabel = soundSection.GetComponentInChildren<TextMeshProUGUI>();
        parametresTab.quitButton = quitButton.GetComponent<Button>();
        parametresTab.logoutButton = logoutButton?.GetComponent<Button>();
        parametresTab.emailInfoText = emailInfoText;
        parametresTab.playTimeInfoText = playTimeInfoText;
        parametresTab.userInfoSection = userInfoSection;
        
        return tab;
    }

    private GameObject CreateParametresUserInfoSection(Transform parent, out TextMeshProUGUI emailTextOut, out TextMeshProUGUI playTimeTextOut)
    {
        emailTextOut = null;
        playTimeTextOut = null;

        GameObject container = new GameObject("UserInfoSection");
        container.transform.SetParent(parent, false);

        RectTransform rect = container.AddComponent<RectTransform>();
        rect.sizeDelta = new Vector2(1000, 0);

        VerticalLayoutGroup vlg = container.AddComponent<VerticalLayoutGroup>();
        vlg.padding = new RectOffset(0, 0, 0, 0);
        vlg.spacing = 8;
        vlg.childAlignment = TextAnchor.UpperCenter;
        vlg.childControlWidth = true;
        vlg.childControlHeight = true;
        vlg.childForceExpandWidth = true;
        vlg.childForceExpandHeight = false;

        ContentSizeFitter fitter = container.AddComponent<ContentSizeFitter>();
        fitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
        fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;

        TMP_FontAsset font = Resources.Load<TMP_FontAsset>("Fonts/Lato-Regular SDF") ??
                             Resources.Load<TMP_FontAsset>("Fonts/Anton-Regular SDF");

        Color labelColor = HexToColor("#64477D");

        // Email (visible uniquement si connecté, géré côté ParametresTab)
        GameObject emailObj = new GameObject("EmailInfo");
        emailObj.transform.SetParent(container.transform, false);
        var emailRect = emailObj.AddComponent<RectTransform>();
        emailRect.sizeDelta = new Vector2(1000, 28);
        TextMeshProUGUI emailTxt = emailObj.AddComponent<TextMeshProUGUI>();
        if (font != null) emailTxt.font = font;
        emailTxt.fontSize = 22;
        emailTxt.color = labelColor;
        emailTxt.alignment = TextAlignmentOptions.Center;
        emailTxt.text = "";
        emailTextOut = emailTxt;

        // Temps de jeu
        GameObject playObj = new GameObject("PlayTimeInfo");
        playObj.transform.SetParent(container.transform, false);
        var playRect = playObj.AddComponent<RectTransform>();
        playRect.sizeDelta = new Vector2(1000, 28);
        TextMeshProUGUI playTxt = playObj.AddComponent<TextMeshProUGUI>();
        if (font != null) playTxt.font = font;
        playTxt.fontSize = 22;
        playTxt.color = labelColor;
        playTxt.alignment = TextAlignmentOptions.Center;
        playTxt.text = "";
        playTimeTextOut = playTxt;

        return container;
    }
    
    GameObject CreateDebugTab(Transform parent)
    {
        GameObject tab = new GameObject("DebugTab");
        tab.transform.SetParent(parent, false);
        
        RectTransform rect = tab.AddComponent<RectTransform>();
        rect.anchorMin = Vector2.zero;
        rect.anchorMax = Vector2.one;
        rect.offsetMin = Vector2.zero;
        rect.offsetMax = Vector2.zero;
        
        // Fond beige clair
        Image bgImage = tab.AddComponent<Image>();
        bgImage.color = new Color(0.95f, 0.95f, 0.9f, 1f);
        bgImage.raycastTarget = false;
        
        // IMPORTANT : Désactiver le tab pour éviter que OnEnable soit appelé avant la configuration
        tab.SetActive(false);
        
        // Zone de contenu simple avec padding
        GameObject content = new GameObject("Content");
        content.transform.SetParent(tab.transform, false);
        RectTransform contentRect = content.AddComponent<RectTransform>();
        contentRect.anchorMin = Vector2.zero;
        contentRect.anchorMax = Vector2.one;
        contentRect.offsetMin = new Vector2(30, 30); // Padding de 30px
        contentRect.offsetMax = new Vector2(-30, -30);
        
        // Ajouter le composant DebugTab APRÈS avoir créé tout le contenu
        DebugTab debugTabComponent = tab.AddComponent<DebugTab>();
        debugTabComponent.contentContainer = content.transform;
        
        // Réactiver le tab maintenant que tout est configuré
        tab.SetActive(true);
        
        return tab;
    }
    
    GameObject CreateSoundSection(Transform parent)
    {
        GameObject section = new GameObject("SoundSection");
        section.transform.SetParent(parent, false);
        
        RectTransform rect = section.AddComponent<RectTransform>();
        rect.sizeDelta = new Vector2(300, 120); // Même largeur que les boutons
        
        LayoutElement layoutElement = section.AddComponent<LayoutElement>();
        layoutElement.preferredWidth = 300;
        layoutElement.preferredHeight = 120;
        layoutElement.flexibleWidth = 0; // Ne pas étirer horizontalement
        
        VerticalLayoutGroup layout = section.AddComponent<VerticalLayoutGroup>();
        layout.spacing = 15;
        layout.childAlignment = TextAnchor.MiddleCenter;
        
        // Label
        GameObject label = new GameObject("SoundLabel");
        label.transform.SetParent(section.transform, false);
        TextMeshProUGUI labelText = label.AddComponent<TextMeshProUGUI>();
        labelText.text = "Son activé";
        labelText.fontSize = 28;
        labelText.alignment = TextAlignmentOptions.Center;
        labelText.color = new Color(0.3f, 0.3f, 0.4f, 1f);
        
        // Toggle
        GameObject toggle = CreateToggle(section.transform);
        
        return section;
    }
    
    GameObject CreateToggle(Transform parent)
    {
        GameObject toggleObj = new GameObject("SoundToggle");
        toggleObj.transform.SetParent(parent, false);
        
        RectTransform rect = toggleObj.AddComponent<RectTransform>();
        rect.sizeDelta = new Vector2(100, 50);
        
        Toggle toggle = toggleObj.AddComponent<Toggle>();
        toggle.isOn = true;
        
        // Background
        GameObject bg = new GameObject("Background");
        bg.transform.SetParent(toggleObj.transform, false);
        RectTransform bgRect = bg.AddComponent<RectTransform>();
        bgRect.anchorMin = Vector2.zero;
        bgRect.anchorMax = Vector2.one;
        bgRect.offsetMin = Vector2.zero;
        bgRect.offsetMax = Vector2.zero;
        Image bgImage = bg.AddComponent<Image>();
        bgImage.color = new Color(0.7f, 0.7f, 0.7f, 1f);
        
        // Checkmark
        GameObject check = new GameObject("Checkmark");
        check.transform.SetParent(bg.transform, false);
        RectTransform checkRect = check.AddComponent<RectTransform>();
        checkRect.anchorMin = Vector2.zero;
        checkRect.anchorMax = Vector2.one;
        checkRect.offsetMin = new Vector2(5, 5);
        checkRect.offsetMax = new Vector2(-5, -5);
        Image checkImage = check.AddComponent<Image>();
        checkImage.color = new Color(0.4f, 0.8f, 0.4f, 1f);
        
        toggle.targetGraphic = bgImage;
        toggle.graphic = checkImage;
        
        return toggleObj;
    }
    
    GameObject CreateQuitButton(Transform parent)
    {
        return CreateStyledButton(parent, "QuitButton", "RETOUR AU MENU GÉNÉRAL", "validationDefault");
    }
    
    GameObject CreateLogoutButton(Transform parent)
    {
        // Le bouton de déconnexion utilise toujours le style validationDefault
        // car il n'est créé que si l'utilisateur est connecté
        return CreateStyledButton(parent, "LogoutButton", "SE DÉCONNECTER", "validationDefault");
    }
    
    GameObject CreateStyledButton(Transform parent, string name, string text, string styleName)
    {
        GameObject button = new GameObject(name);
        button.transform.SetParent(parent, false);
        
        // Récupérer le style depuis la config
        ButtonStyleConfig buttonStyle = null;
        float buttonWidth = 300f; // Largeur par défaut
        float buttonHeight = 80f;
        float borderRadius = 35f;
        float borderWidth = 4f;
        Color startColor = HexToColor("#CE9BFD");
        Color endColor = HexToColor("#9A2DFF");
        Color borderColor = HexToColor("#f5ece5");
        Color textColor = Color.white;
        float textFontSize = 28f;
        
        if (GeneralConfigManager.Instance != null)
        {
            buttonStyle = GeneralConfigManager.Instance.GetButtonStyle(styleName);
            if (buttonStyle != null)
            {
                buttonWidth = buttonStyle.width; // Utiliser la largeur du style
                buttonHeight = buttonStyle.height;
                borderRadius = buttonStyle.borderRadius;
                borderWidth = buttonStyle.borderWidth;
                if (buttonStyle.gradient != null && buttonStyle.gradient.enabled)
                {
                    startColor = HexToColor(buttonStyle.gradient.startColor ?? "#CE9BFD");
                    endColor = HexToColor(buttonStyle.gradient.endColor ?? "#9A2DFF");
                }
                borderColor = HexToColor(buttonStyle.borderColor ?? "#f5ece5");
                if (buttonStyle.text != null)
                {
                    textColor = HexToColor(buttonStyle.text.color ?? "#FFFFFF");
                    textFontSize = buttonStyle.text.fontSize;
                }
            }
        }
        
        RectTransform rect = button.AddComponent<RectTransform>();
        rect.sizeDelta = new Vector2(buttonWidth, buttonHeight); // Forcer la taille du style
        
        // LayoutElement avec la largeur fixe du style (pas d'étirement)
        LayoutElement layoutElement = button.AddComponent<LayoutElement>();
        layoutElement.preferredWidth = buttonWidth;
        layoutElement.preferredHeight = buttonHeight;
        layoutElement.minWidth = buttonWidth;
        layoutElement.minHeight = buttonHeight;
        layoutElement.flexibleWidth = 0; // Empêcher l'étirement horizontal
        layoutElement.flexibleHeight = 0; // Empêcher l'étirement vertical
        
        // Image du bouton avec dégradé
        Image image = button.AddComponent<Image>();
        image.sprite = CreateGradientSpriteWithBorder((int)buttonWidth, (int)buttonHeight, borderRadius, 
            startColor, endColor, borderColor, borderWidth);
        image.color = Color.white;
        image.raycastTarget = true;

        // ✅ Ombre depuis le style (ex: validationDefault) — sinon on perd le rendu "Intro"
        if (buttonStyle?.shadow != null && buttonStyle.shadow.enabled)
        {
            Shadow shadow = button.GetComponent<Shadow>();
            if (shadow == null) shadow = button.AddComponent<Shadow>();
            shadow.effectColor = HexToColor(buttonStyle.shadow.color ?? "#00000040");
            shadow.effectDistance = new Vector2(buttonStyle.shadow.offsetX, -buttonStyle.shadow.offsetY);
        }
        
        Button btn = button.AddComponent<Button>();
        btn.targetGraphic = image;
        btn.interactable = true;
        
        // Configurer les couleurs du bouton (effets hover/pressed)
        ColorBlock colors = btn.colors;
        colors.normalColor = Color.white;
        colors.highlightedColor = new Color(1.1f, 1.1f, 1.1f, 1f);
        colors.pressedColor = new Color(0.9f, 0.9f, 0.9f, 1f);
        btn.colors = colors;
        
        // Texte du bouton
        GameObject textObj = new GameObject("Text");
        textObj.transform.SetParent(button.transform, false);
        
        RectTransform textRect = textObj.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.sizeDelta = Vector2.zero;
        textRect.anchoredPosition = Vector2.zero;
        
        TextMeshProUGUI textComponent = textObj.AddComponent<TextMeshProUGUI>();
        textComponent.text = text;
        textComponent.fontSize = textFontSize;
        // Utiliser le fontWeight du style
        textComponent.fontStyle = buttonStyle?.text?.GetFontStyle() ?? FontStyles.Normal;
        textComponent.alignment = TextAlignmentOptions.Center;
        textComponent.verticalAlignment = VerticalAlignmentOptions.Middle;
        textComponent.color = textColor;
        textComponent.enableAutoSizing = false;
        textComponent.raycastTarget = false;
        
        // Charger la police Anton avec le bon chemin
        TMP_FontAsset antonFont = Resources.Load<TMP_FontAsset>("Fonts/Anton-Regular SDF");
        if (antonFont != null)
        {
            textComponent.font = antonFont;
        }
        else
        {
            Debug.LogWarning($"[SettingsPanelBuilder] Police Anton-Regular SDF non trouvée");
        }
        
        return button;
    }
    
    // Helpers pour créer des sprites
    
    Sprite CreateRoundedSprite()
    {
        Texture2D texture = new Texture2D(100, 100);
        Color[] pixels = new Color[100 * 100];
        
        for (int y = 0; y < 100; y++)
        {
            for (int x = 0; x < 100; x++)
            {
                pixels[y * 100 + x] = Color.white;
            }
        }
        
        texture.SetPixels(pixels);
        texture.Apply();
        
        resourceTracker.Track(texture);
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, 100, 100), new Vector2(0.5f, 0.5f), 100, 0, SpriteMeshType.FullRect, new Vector4(20, 20, 20, 20));
        resourceTracker.Track(sprite);
        return sprite;
    }
    
    Sprite CreateCircleSprite()
    {
        int size = 128;
        Texture2D texture = new Texture2D(size, size);
        Color[] pixels = new Color[size * size];
        
        float center = size / 2f;
        float radius = size / 2f;
        
        for (int y = 0; y < size; y++)
        {
            for (int x = 0; x < size; x++)
            {
                float distance = Vector2.Distance(new Vector2(x, y), new Vector2(center, center));
                pixels[y * size + x] = distance <= radius ? Color.white : Color.clear;
            }
        }
        
        texture.SetPixels(pixels);
        texture.Apply();
        
        resourceTracker.Track(texture);
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, size, size), new Vector2(0.5f, 0.5f));
        resourceTracker.Track(sprite);
        return sprite;
    }
    
    /// <summary>
    /// Crée un sprite avec des coins arrondis et une couleur spécifique (même méthode que LoginPopup)
    /// </summary>
    Sprite CreateRoundedColorSprite(int width, int height, float radius, Color fillColor)
    {
        Texture2D texture = new Texture2D(width, height);
        Color[] pixels = new Color[width * height];

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                float alpha = 1f;

                // Coin supérieur gauche
                if (x < radius && y > height - radius)
                {
                    float dx = radius - x;
                    float dy = (height - radius) - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius)
                        alpha = 0f;
                    else
                        alpha = 1f - Mathf.Clamp01((distance - radius + 1) / 1);
                }
                // Coin supérieur droit
                else if (x > width - radius && y > height - radius)
                {
                    float dx = x - (width - radius);
                    float dy = (height - radius) - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius)
                        alpha = 0f;
                    else
                        alpha = 1f - Mathf.Clamp01((distance - radius + 1) / 1);
                }
                // Coin inférieur gauche
                else if (x < radius && y < radius)
                {
                    float dx = radius - x;
                    float dy = radius - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius)
                        alpha = 0f;
                    else
                        alpha = 1f - Mathf.Clamp01((distance - radius + 1) / 1);
                }
                // Coin inférieur droit
                else if (x > width - radius && y < radius)
                {
                    float dx = x - (width - radius);
                    float dy = radius - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius)
                        alpha = 0f;
                    else
                        alpha = 1f - Mathf.Clamp01((distance - radius + 1) / 1);
                }

                pixels[y * width + x] = new Color(fillColor.r, fillColor.g, fillColor.b, fillColor.a * alpha);
            }
        }

        texture.SetPixels(pixels);
        texture.Apply();

        resourceTracker.Track(texture);
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f), 100f);
        resourceTracker.Track(sprite);
        return sprite;
    }
    
    /// <summary>
    /// Crée un sprite pour le header avec coins arrondis uniquement en HAUT (même approche que LoginPopup)
    /// </summary>
    Sprite CreateRoundedTopSprite(int width, int height, float radius, Color fillColor)
    {
        Texture2D texture = new Texture2D(width, height);
        Color[] pixels = new Color[width * height];

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                float alpha = 1f;

                // Seulement les coins du HAUT sont arrondis
                // Coin supérieur gauche
                if (x < radius && y > height - radius)
                {
                    float dx = radius - x;
                    float dy = (height - radius) - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius)
                        alpha = 0f;
                    else
                        alpha = 1f - Mathf.Clamp01((distance - radius + 1) / 1);
                }
                // Coin supérieur droit
                else if (x > width - radius && y > height - radius)
                {
                    float dx = x - (width - radius);
                    float dy = (height - radius) - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius)
                        alpha = 0f;
                    else
                        alpha = 1f - Mathf.Clamp01((distance - radius + 1) / 1);
                }
                // Coins inférieurs : pas arrondis (alpha reste à 1)

                pixels[y * width + x] = new Color(fillColor.r, fillColor.g, fillColor.b, fillColor.a * alpha);
            }
        }

        texture.SetPixels(pixels);
        texture.Apply();

        resourceTracker.Track(texture);
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f), 100f);
        resourceTracker.Track(sprite);
        return sprite;
    }
    
    /// <summary>
    /// Convertit une couleur hexadécimale en Color Unity
    /// </summary>
    Color HexToColor(string hex)
    {
        if (string.IsNullOrEmpty(hex)) return Color.white;
        
        // Supprimer le # si présent
        hex = hex.TrimStart('#');
        
        // Gérer "transparent"
        if (hex.ToLower() == "transparent") return Color.clear;
        
        Color color = Color.white;
        if (ColorUtility.TryParseHtmlString("#" + hex, out color))
        {
            return color;
        }
        return Color.white;
    }
    
    Sprite CreateGradientSpriteWithBorder(int width, int height, float radius, Color startColor, Color endColor, Color borderColor, float borderWidth)
    {
        Texture2D texture = new Texture2D(width, height);
        Color[] pixels = new Color[width * height];

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                float alpha = 1f;
                bool isBorder = false;
                
                // Vérifier si on est dans la bordure
                if (x < borderWidth || x >= width - borderWidth || y < borderWidth || y >= height - borderWidth)
                {
                    isBorder = true;
                }

                // Coins arrondis
                float distanceFromCorner = float.MaxValue;
                
                // Coin supérieur gauche
                if (x < radius && y > height - radius)
                {
                    float dx = radius - x;
                    float dy = (height - radius) - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }
                // Coin supérieur droit
                else if (x > width - radius && y > height - radius)
                {
                    float dx = x - (width - radius);
                    float dy = (height - radius) - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }
                // Coin inférieur gauche
                else if (x < radius && y < radius)
                {
                    float dx = radius - x;
                    float dy = radius - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }
                // Coin inférieur droit
                else if (x > width - radius && y < radius)
                {
                    float dx = x - (width - radius);
                    float dy = radius - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }

                Color pixelColor;
                if (isBorder && alpha > 0)
                {
                    pixelColor = borderColor;
                }
                else
                {
                    // Dégradé vertical (du bas vers le haut)
                    float t = (float)y / height;
                    pixelColor = Color.Lerp(endColor, startColor, t);
                }
                
                pixelColor.a *= alpha;
                pixels[y * width + x] = pixelColor;
            }
        }

        texture.SetPixels(pixels);
        texture.Apply();

        resourceTracker.Track(texture);
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f), 100f);
        resourceTracker.Track(sprite);
        return sprite;
    }
    
    void OnDestroy()
    {
        CleanupResources();
    }
    
    /// <summary>
    /// Nettoie toutes les ressources créées dynamiquement (important pour WebGL)
    /// </summary>
    public void CleanupResources()
    {
        int count = resourceTracker.Count;
        resourceTracker.Cleanup();
        Debug.Log($"[SettingsPanelBuilder] 🧹 Ressources nettoyées: {count} objets");
    }
}

/// <summary>
/// Classe helper pour stocker les données de style d'un bouton
/// </summary>
public class StyledButtonData : MonoBehaviour
{
    public float borderRadius;
    public float borderWidth;
    public Color startColor;
    public Color endColor;
    public Color borderColor;
    public float buttonHeight;
}