using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;
using UnityEngine.SceneManagement;
using TMPro;
using System.Collections;

/// <summary>
/// Écran d'introduction du jeu
/// Affiche une vidéo en background avec le titre "UN JOUR SANS ASSURANCE" 
/// qui apparaît progressivement au centre, puis un bouton COMMENCER
/// 
/// OPTIMISATION : La scène suivante est préchargée en arrière-plan pendant que la vidéo joue
/// Quand l'utilisateur clique sur COMMENCER, la scène est déjà prête et s'affiche instantanément
/// </summary>
public class IntroScreenManager : MonoBehaviour
{
    [Header("Configuration Vidéo")]
    [Tooltip("Nom de la vidéo d'intro (dans StreamingAssets/videos/)")]
    public string videoFileName = "lancement.mp4";
    
    [Tooltip("Scène à charger après l'intro")]
    public string nextSceneName = "main";
    
    [Header("Configuration du Titre")]
    [Tooltip("Taille de la police du titre")]
    public float titleFontSize = 80f;
    
    [Tooltip("Espacement entre les lignes (en pourcentage, 100 = normal)")]
    public float lineSpacing = 0f;
    
    [Tooltip("Délai avant l'apparition du titre (en secondes)")]
    public float titleAppearDelay = 1.0f;
    
    [Tooltip("Durée du fade in du titre (en secondes)")]
    public float titleFadeDuration = 2.0f;
    
    [Header("Configuration du Bouton")]
    [Tooltip("Délai avant l'apparition du bouton COMMENCER (en secondes)")]
    public float buttonAppearDelay = 3.0f;
    
    [Tooltip("Durée du fade in du bouton (en secondes)")]
    public float buttonFadeDuration = 1.0f;
    
    [Tooltip("Distance du bouton depuis le bas de l'écran")]
    public float buttonBottomMargin = 100f;
    
    [Header("Préchargement")]
    [Tooltip("Démarrer le préchargement de la scène suivante dès le début")]
    public bool preloadNextScene = true;
    
    // Composants créés dynamiquement
    private VideoPlayer videoPlayer;
    private RenderTexture renderTexture;
    private RawImage videoDisplay;
    private TextMeshProUGUI titleText;
    private CanvasGroup titleCanvasGroup;
    private Canvas mainCanvas;
    private GameObject startButton;
    private CanvasGroup buttonCanvasGroup;
    private TextMeshProUGUI loadingIndicator;
    private bool hasCompleted = false;
    private bool videoStarted = false;
    
    // Préchargement de la scène
    private AsyncOperation sceneLoadOperation;
    private bool isSceneReady = false;
    private bool userWantsToStart = false;
    
    // Logs verbeux désactivés en production
    // (static readonly pour éviter CS0162 "unreachable code detected" quand le compilateur voit une constante)
    private static readonly bool VERBOSE_DEBUG = false;
    [System.Diagnostics.Conditional("UNITY_EDITOR")]
    private void LogVerbose(string message) { if (VERBOSE_DEBUG) Debug.Log(message); }

    void Awake()
    {
        // Créer le Canvas principal
        CreateMainCanvas();
        
        // Créer le VideoPlayer et l'affichage
        CreateVideoPlayer();
        
        // Créer le titre
        CreateTitleText();
        
        // Créer le bouton COMMENCER (invisible au départ)
        CreateStartButton();
    }

    void Start()
    {
        // Lancer la préparation de la vidéo
        StartCoroutine(PrepareAndPlayVideo());
        
        // Démarrer le préchargement de la scène suivante
        if (preloadNextScene)
        {
            StartCoroutine(PreloadNextScene());
        }
    }

    /// <summary>
    /// Précharge la scène suivante en arrière-plan pendant que la vidéo joue
    /// </summary>
    IEnumerator PreloadNextScene()
    {
        LogVerbose($"[IntroScreenManager] 🔄 Début du préchargement de la scène: {nextSceneName}");
        
        // Attendre un peu pour que la vidéo démarre d'abord
        yield return new WaitForSeconds(0.5f);
        
        // Charger la scène de manière asynchrone
        sceneLoadOperation = SceneManager.LoadSceneAsync(nextSceneName);
        
        if (sceneLoadOperation == null)
        {
            Debug.LogError($"[IntroScreenManager] ❌ Impossible de charger la scène: {nextSceneName}");
            yield break;
        }
        
        // IMPORTANT : Ne pas activer la scène automatiquement
        sceneLoadOperation.allowSceneActivation = false;
        
        // Suivre la progression du chargement
        while (!sceneLoadOperation.isDone)
        {
            // La progression va de 0 à 0.9 quand allowSceneActivation = false
            float progress = Mathf.Clamp01(sceneLoadOperation.progress / 0.9f);
            
            // Log de progression (tous les 10%)
            if (progress >= 0.9f && !isSceneReady)
            {
                isSceneReady = true;
                LogVerbose($"[IntroScreenManager] ✅ Scène préchargée et prête ! (100%)");
                
                // Masquer l'indicateur de chargement si présent
                if (loadingIndicator != null)
                {
                    loadingIndicator.gameObject.SetActive(false);
                }
                
                // Si l'utilisateur a déjà cliqué sur COMMENCER, activer la scène maintenant
                if (userWantsToStart)
                {
                    ActivateScene();
                }
            }
            
            yield return null;
        }
    }
    
    /// <summary>
    /// Active la scène préchargée
    /// </summary>
    void ActivateScene()
    {
        if (sceneLoadOperation != null && !hasCompleted)
        {
            hasCompleted = true;
            
            LogVerbose($"[IntroScreenManager] 🚀 Activation de la scène: {nextSceneName}");
            
            // Arrêter la vidéo
            if (videoPlayer != null && videoPlayer.isPlaying)
            {
                videoPlayer.Stop();
            }

            // 🔧 SÉCURITÉ : si un overlay noir persistant (transition/loading) traîne, il peut masquer la scène suivante.
            CleanupPersistentOverlaysBeforeSceneChange();
            
            // Activer la scène préchargée - elle apparaîtra instantanément !
            sceneLoadOperation.allowSceneActivation = true;
        }
    }

    /// <summary>
    /// Crée le Canvas principal pour l'UI
    /// </summary>
    void CreateMainCanvas()
    {
        // Toujours créer un nouveau Canvas pour l'intro (évite les conflits)
        GameObject canvasObj = new GameObject("IntroCanvas");
        mainCanvas = canvasObj.AddComponent<Canvas>();
        mainCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
        mainCanvas.sortingOrder = 100;
        
        CanvasScaler scaler = canvasObj.AddComponent<CanvasScaler>();
        scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
        scaler.referenceResolution = new Vector2(1920, 1080);
        scaler.matchWidthOrHeight = 0.5f;
        
        canvasObj.AddComponent<GraphicRaycaster>();
        
        // S'assurer qu'il y a un EventSystem pour détecter les clics
        if (UnityEngine.EventSystems.EventSystem.current == null)
        {
            GameObject eventSystemObj = new GameObject("EventSystem");
            eventSystemObj.AddComponent<UnityEngine.EventSystems.EventSystem>();
            #if ENABLE_INPUT_SYSTEM
            eventSystemObj.AddComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
            #else
            eventSystemObj.AddComponent<UnityEngine.EventSystems.StandaloneInputModule>();
            #endif
            LogVerbose("[IntroScreenManager] ✅ EventSystem créé");
        }
    }

    /// <summary>
    /// Crée le VideoPlayer et le RawImage pour afficher la vidéo
    /// </summary>
    void CreateVideoPlayer()
    {
        // Fond noir
        GameObject bgObj = new GameObject("BlackBackground");
        bgObj.transform.SetParent(mainCanvas.transform, false);
        RectTransform bgRect = bgObj.AddComponent<RectTransform>();
        bgRect.anchorMin = Vector2.zero;
        bgRect.anchorMax = Vector2.one;
        bgRect.offsetMin = Vector2.zero;
        bgRect.offsetMax = Vector2.zero;
        Image bgImage = bgObj.AddComponent<Image>();
        bgImage.color = Color.black;
        bgImage.raycastTarget = false;

        // Créer la RenderTexture
        renderTexture = new RenderTexture(1920, 1080, 0);
        renderTexture.Create();

        // Créer le VideoPlayer
        GameObject videoPlayerObj = new GameObject("VideoPlayer");
        videoPlayerObj.transform.SetParent(transform, false);

        videoPlayer = videoPlayerObj.AddComponent<VideoPlayer>();
        videoPlayer.playOnAwake = false;
        videoPlayer.renderMode = VideoRenderMode.RenderTexture;
        videoPlayer.targetTexture = renderTexture;
        videoPlayer.isLooping = true;
        videoPlayer.aspectRatio = VideoAspectRatio.FitInside;
        
        // Configuration audio
        videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;
        videoPlayer.controlledAudioTrackCount = 1;
        
        AudioSource audioSource = videoPlayerObj.AddComponent<AudioSource>();
        audioSource.playOnAwake = false;
        audioSource.volume = 1.0f;
        audioSource.spatialBlend = 0f;
        audioSource.priority = 0;
        
        videoPlayer.EnableAudioTrack(0, true);
        videoPlayer.SetTargetAudioSource(0, audioSource);
        
        // Définir l'URL de la vidéo - IMPORTANT: Normaliser le chemin avec / pour Unity VideoPlayer sur Windows
        string videoPath = System.IO.Path.Combine(Application.streamingAssetsPath, "videos", videoFileName);
        // Remplacer tous les backslashes par des forward slashes pour Unity VideoPlayer
        videoPath = videoPath.Replace("\\", "/");
        videoPlayer.url = videoPath;
        
        LogVerbose($"[IntroScreenManager] 🎬 Vidéo configurée: {videoPath}");

        // Créer le RawImage pour afficher la vidéo
        GameObject displayObj = new GameObject("VideoDisplay");
        displayObj.transform.SetParent(mainCanvas.transform, false);
        
        RectTransform displayRect = displayObj.AddComponent<RectTransform>();
        displayRect.anchorMin = Vector2.zero;
        displayRect.anchorMax = Vector2.one;
        displayRect.offsetMin = Vector2.zero;
        displayRect.offsetMax = Vector2.zero;

        videoDisplay = displayObj.AddComponent<RawImage>();
        videoDisplay.texture = renderTexture;
        videoDisplay.color = Color.white;
        videoDisplay.raycastTarget = false;

        // Événements vidéo
        videoPlayer.loopPointReached += OnVideoFinished;
        videoPlayer.errorReceived += OnVideoError;
        videoPlayer.prepareCompleted += OnVideoPrepared;
    }

    /// <summary>
    /// Crée le texte du titre avec la police Anton-Regular SDF
    /// </summary>
    void CreateTitleText()
    {
        // Container pour le titre
        GameObject titleContainer = new GameObject("TitleContainer");
        titleContainer.transform.SetParent(mainCanvas.transform, false);
        
        RectTransform containerRect = titleContainer.AddComponent<RectTransform>();
        containerRect.anchorMin = new Vector2(0.5f, 0.5f);
        containerRect.anchorMax = new Vector2(0.5f, 0.5f);
        containerRect.pivot = new Vector2(0.5f, 0.5f);
        containerRect.sizeDelta = new Vector2(1000, 400);
        containerRect.anchoredPosition = Vector2.zero;
        
        // CanvasGroup pour le fade
        titleCanvasGroup = titleContainer.AddComponent<CanvasGroup>();
        titleCanvasGroup.alpha = 0f; // Commence invisible
        
        // Charger la police Anton-Regular SDF depuis Resources
        TMP_FontAsset antonFont = Resources.Load<TMP_FontAsset>("Fonts/Anton-Regular SDF");
        
        // OMBRE : Texte dupliqué derrière avec décalage (Shadow ne fonctionne pas avec TMP)
        GameObject shadowObj = new GameObject("TitleShadow");
        shadowObj.transform.SetParent(titleContainer.transform, false);
        
        RectTransform shadowRect = shadowObj.AddComponent<RectTransform>();
        shadowRect.anchorMin = Vector2.zero;
        shadowRect.anchorMax = Vector2.one;
        shadowRect.offsetMin = Vector2.zero;
        shadowRect.offsetMax = Vector2.zero;
        shadowRect.anchoredPosition = new Vector2(10, -10); // Décalage 10px droite, 10px bas
        
        TextMeshProUGUI shadowText = shadowObj.AddComponent<TextMeshProUGUI>();
        shadowText.text = "UN JOUR SANS\nASSURANCE";
        shadowText.fontSize = titleFontSize;
        shadowText.lineSpacing = lineSpacing;
        shadowText.color = new Color(0.4f, 0.4f, 0.4f, 0.6f); // Gris moyen semi-transparent
        shadowText.alignment = TextAlignmentOptions.Center;
        shadowText.fontStyle = FontStyles.Normal;
        if (antonFont != null) shadowText.font = antonFont;
        shadowText.textWrappingMode = TMPro.TextWrappingModes.Normal;
        shadowText.overflowMode = TextOverflowModes.Overflow;
        
        // Texte du titre (au-dessus de l'ombre)
        GameObject titleObj = new GameObject("TitleText");
        titleObj.transform.SetParent(titleContainer.transform, false);
        
        RectTransform titleRect = titleObj.AddComponent<RectTransform>();
        titleRect.anchorMin = Vector2.zero;
        titleRect.anchorMax = Vector2.one;
        titleRect.offsetMin = Vector2.zero;
        titleRect.offsetMax = Vector2.zero;
        
        titleText = titleObj.AddComponent<TextMeshProUGUI>();
        titleText.text = "UN JOUR SANS\nASSURANCE";
        titleText.fontSize = titleFontSize;
        titleText.lineSpacing = lineSpacing;
        titleText.color = Color.white;
        titleText.alignment = TextAlignmentOptions.Center;
        titleText.fontStyle = FontStyles.Normal;
        
        if (antonFont != null)
        {
            titleText.font = antonFont;
            LogVerbose("[IntroScreenManager] ✅ Police Anton-Regular SDF chargée");
        }
        else
        {
            Debug.LogWarning("[IntroScreenManager] ⚠️ Police Anton-Regular SDF non trouvée dans Resources/Fonts/");
        }
        
        titleText.textWrappingMode = TMPro.TextWrappingModes.Normal;
        titleText.overflowMode = TextOverflowModes.Overflow;
    }

    /// <summary>
    /// Crée le bouton COMMENCER avec le style validationDefault
    /// </summary>
    void CreateStartButton()
    {
        // Container pour le bouton
        startButton = new GameObject("StartButtonContainer");
        startButton.transform.SetParent(mainCanvas.transform, false);
        
        RectTransform buttonContainerRect = startButton.AddComponent<RectTransform>();
        buttonContainerRect.anchorMin = new Vector2(0.5f, 0f);
        buttonContainerRect.anchorMax = new Vector2(0.5f, 0f);
        buttonContainerRect.pivot = new Vector2(0.5f, 0f);
        buttonContainerRect.anchoredPosition = new Vector2(0, buttonBottomMargin);
        
        // CanvasGroup pour le fade
        buttonCanvasGroup = startButton.AddComponent<CanvasGroup>();
        buttonCanvasGroup.alpha = 0f; // Commence invisible
        buttonCanvasGroup.interactable = false;
        buttonCanvasGroup.blocksRaycasts = false;
        
        // Récupérer le style validationDefault depuis GeneralConfigManager
        ButtonStyleConfig buttonStyle = null;
        float buttonWidth = 300f;
        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;
        
        // Essayer de charger depuis GeneralConfigManager
        if (GeneralConfigManager.Instance != null)
        {
            var config = GeneralConfigManager.Instance.GetConfig();
            if (config?.buttonStyles != null)
            {
                buttonStyle = config.buttonStyles.GetStyle("validationDefault");
                if (buttonStyle != null)
                {
                    buttonWidth = buttonStyle.width;
                    buttonHeight = buttonStyle.height;
                    borderRadius = buttonStyle.borderRadius;
                    borderWidth = buttonStyle.borderWidth;
                    if (buttonStyle.gradient != null)
                    {
                        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;
                    }
                    LogVerbose("[IntroScreenManager] ✅ Style validationDefault chargé depuis config");
                }
            }
        }
        
        buttonContainerRect.sizeDelta = new Vector2(buttonWidth, buttonHeight);
        
        // Créer le bouton
        GameObject buttonObj = new GameObject("StartButton");
        buttonObj.transform.SetParent(startButton.transform, false);
        
        RectTransform buttonRect = buttonObj.AddComponent<RectTransform>();
        buttonRect.anchorMin = Vector2.zero;
        buttonRect.anchorMax = Vector2.one;
        buttonRect.offsetMin = Vector2.zero;
        buttonRect.offsetMax = Vector2.zero;
        
        // Image du bouton avec dégradé
        Image buttonImage = buttonObj.AddComponent<Image>();
        buttonImage.sprite = CreateGradientSpriteWithBorder((int)buttonWidth, (int)buttonHeight, borderRadius, startColor, endColor, borderColor, borderWidth);
        buttonImage.color = Color.white;
        buttonImage.type = Image.Type.Simple;
        buttonImage.raycastTarget = true;
        
        // Ajouter l'ombre (priorité à la config validationDefault, fallback sur l'ombre "historique" si absent)
        if (buttonStyle?.shadow != null && buttonStyle.shadow.enabled)
        {
            Shadow shadowComponent = buttonObj.AddComponent<Shadow>();
            shadowComponent.effectColor = HexToColor(buttonStyle.shadow.color ?? "#00000040");
            shadowComponent.effectDistance = new Vector2(buttonStyle.shadow.offsetX, -buttonStyle.shadow.offsetY);
        }
        else
        {
            Shadow shadowComponent = buttonObj.AddComponent<Shadow>();
            shadowComponent.effectColor = new Color(0, 0, 0, 0.25f);
            shadowComponent.effectDistance = new Vector2(0, -6);
        }
        
        // Bouton interactif
        Button button = buttonObj.AddComponent<Button>();
        button.targetGraphic = buttonImage;
        button.onClick.AddListener(OnStartButtonClicked);
        
        LogVerbose("[IntroScreenManager] ✅ Bouton COMMENCER créé avec listener attaché");
        
        // Configurer les couleurs du bouton
        ColorBlock colors = button.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);
        button.colors = colors;
        
        // Texte du bouton
        GameObject textObj = new GameObject("ButtonText");
        textObj.transform.SetParent(buttonObj.transform, false);
        
        RectTransform textRect = textObj.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.offsetMin = Vector2.zero;
        textRect.offsetMax = Vector2.zero;
        
        TextMeshProUGUI buttonText = textObj.AddComponent<TextMeshProUGUI>();
        buttonText.text = "COMMENCER";
        buttonText.fontSize = textFontSize;
        buttonText.color = textColor;
        buttonText.alignment = TextAlignmentOptions.Center;
        // Utiliser le fontWeight de la config (normal par défaut pour validationDefault)
        buttonText.fontStyle = buttonStyle?.text?.GetFontStyle() ?? FontStyles.Normal;
        
        // Charger la police Anton-Regular SDF
        TMP_FontAsset antonFont = Resources.Load<TMP_FontAsset>("Fonts/Anton-Regular SDF");
        if (antonFont != null)
        {
            buttonText.font = antonFont;
        }
    }

    /// <summary>
    /// Prépare et joue la vidéo
    /// </summary>
    IEnumerator PrepareAndPlayVideo()
    {
        // Attendre que GeneralConfigManager soit prêt (pour le style du bouton)
        if (GeneralConfigManager.Instance != null)
        {
            yield return GeneralConfigManager.Instance.WaitForConfigLoaded();
            // Recréer le bouton avec le bon style maintenant que la config est chargée
            if (startButton != null)
            {
                Destroy(startButton);
            }
            CreateStartButton();
        }
        
        videoPlayer.Prepare();
        
        float timeout = 10f;
        float elapsed = 0f;

        while (!videoPlayer.isPrepared && elapsed < timeout)
        {
            elapsed += Time.deltaTime;
            yield return null;
        }

        if (!videoPlayer.isPrepared)
        {
            Debug.LogError("[IntroScreenManager] ❌ Timeout préparation vidéo!");
            // Même en cas d'échec, afficher le titre et le bouton
            StartCoroutine(ShowTitleAndButton());
            yield break;
        }

        // Vérifier AudioListener
        AudioListener listener = FindFirstObjectByType<AudioListener>();
        if (listener == null)
        {
            Camera cam = Camera.main;
            if (cam != null)
            {
                cam.gameObject.AddComponent<AudioListener>();
            }
            else
            {
                GameObject audioListenerObj = new GameObject("AudioListener");
                audioListenerObj.AddComponent<AudioListener>();
            }
        }

        videoPlayer.Play();
        videoStarted = true;
        
        LogVerbose("[IntroScreenManager] ▶️ Vidéo en lecture");
        
        // Lancer l'animation du titre après un délai
        StartCoroutine(AnimateTitleFadeIn());
        
        // Lancer l'animation du bouton après un autre délai
        StartCoroutine(AnimateButtonFadeIn());
    }

    /// <summary>
    /// Animation de fade in du titre
    /// </summary>
    IEnumerator AnimateTitleFadeIn()
    {
        // Attendre avant d'afficher le titre
        yield return new WaitForSeconds(titleAppearDelay);
        
        // Fade in progressif
        float elapsed = 0f;
        
        while (elapsed < titleFadeDuration)
        {
            elapsed += Time.deltaTime;
            float progress = elapsed / titleFadeDuration;
            
            // Courbe d'easing pour un effet plus doux
            float easedProgress = EaseOutCubic(progress);
            titleCanvasGroup.alpha = easedProgress;
            
            yield return null;
        }
        
        titleCanvasGroup.alpha = 1f;
        LogVerbose("[IntroScreenManager] ✅ Titre affiché");
    }
    
    /// <summary>
    /// Animation de fade in du bouton COMMENCER
    /// </summary>
    IEnumerator AnimateButtonFadeIn()
    {
        // Attendre avant d'afficher le bouton
        yield return new WaitForSeconds(buttonAppearDelay);
        
        // Activer l'interactivité
        buttonCanvasGroup.interactable = true;
        buttonCanvasGroup.blocksRaycasts = true;
        
        // Fade in progressif
        float elapsed = 0f;
        
        while (elapsed < buttonFadeDuration)
        {
            elapsed += Time.deltaTime;
            float progress = elapsed / buttonFadeDuration;
            
            float easedProgress = EaseOutCubic(progress);
            buttonCanvasGroup.alpha = easedProgress;
            
            yield return null;
        }
        
        buttonCanvasGroup.alpha = 1f;
        LogVerbose("[IntroScreenManager] ✅ Bouton COMMENCER affiché");
        
        // Afficher l'état du préchargement
        if (!isSceneReady)
        {
            LogVerbose("[IntroScreenManager] ⏳ En attente du préchargement de la scène...");
        }
    }
    
    /// <summary>
    /// Fonction d'easing pour une animation plus fluide
    /// </summary>
    float EaseOutCubic(float t)
    {
        return 1f - Mathf.Pow(1f - t, 3f);
    }

    /// <summary>
    /// Affiche le titre puis le bouton (fallback si vidéo échoue)
    /// </summary>
    IEnumerator ShowTitleAndButton()
    {
        // Animation du titre
        StartCoroutine(AnimateTitleFadeIn());
        
        // Animation du bouton
        yield return StartCoroutine(AnimateButtonFadeIn());
    }

    void OnVideoPrepared(VideoPlayer vp)
    {
        LogVerbose($"[IntroScreenManager] ✅ Vidéo préparée - Durée: {vp.length:F2}s");
        
        if (vp.audioTrackCount == 0)
        {
            Debug.LogWarning("[IntroScreenManager] ⚠️ Cette vidéo n'a pas de piste audio");
        }
    }

    void OnVideoError(VideoPlayer vp, string message)
    {
        Debug.LogError($"[IntroScreenManager] ❌ Erreur vidéo: {message}");
        Debug.LogError($"[IntroScreenManager] URL: {vp.url}");
        
        // En cas d'erreur, afficher le titre et le bouton
        if (!hasCompleted)
        {
            StartCoroutine(ShowTitleAndButton());
        }
    }

    void OnVideoFinished(VideoPlayer vp)
    {
        LogVerbose("[IntroScreenManager] 🏁 Vidéo terminée");
        // La vidéo se termine mais on attend le clic sur COMMENCER
    }
    
    /// <summary>
    /// Appelé quand on clique sur le bouton COMMENCER
    /// </summary>
    void OnStartButtonClicked()
    {
        if (hasCompleted) return;
        
        LogVerbose("[IntroScreenManager] 🖱️ Bouton COMMENCER cliqué");
        
        userWantsToStart = true;
        
        // Lancer le processus de transition (avec attente de la config)
        StartCoroutine(HandleTransition());
    }
    
    /// <summary>
    /// Gère la transition après le clic sur COMMENCER (attend que la config soit chargée)
    /// </summary>
    IEnumerator HandleTransition()
    {
        Debug.Log("[IntroScreenManager] ⏳ Attente du chargement de GeneralConfigManager...");
        
        // Créer GeneralConfigManager s'il n'existe pas
        if (GeneralConfigManager.Instance == null)
        {
            GameObject configManagerObj = new GameObject("GeneralConfigManager");
            configManagerObj.AddComponent<GeneralConfigManager>();
            Debug.Log("[IntroScreenManager] GeneralConfigManager créé automatiquement");
        }
        
        // Attendre que la configuration soit chargée
        while (GeneralConfigManager.Instance == null || !GeneralConfigManager.Instance.IsConfigLoaded())
        {
            yield return null;
        }
        
        Debug.Log("[IntroScreenManager] ✅ GeneralConfigManager chargé");
        
        // Vérifier s'il y a une vidéo de transition à jouer
        string transitionVideoUrl = GetTransitionVideoUrl();
        
        if (!string.IsNullOrEmpty(transitionVideoUrl))
        {
            Debug.Log("[IntroScreenManager] 🎬 Vidéo de transition configurée, lancement...");
            yield return StartCoroutine(PlayTransitionVideo(transitionVideoUrl));
        }
        else
        {
            Debug.Log("[IntroScreenManager] ⏭️ Pas de vidéo de transition, passage direct à la scène suivante");
            // Pas de vidéo de transition, passage direct
            ProceedToNextScene();
        }
    }
    
    /// <summary>
    /// Récupère l'URL de la vidéo de transition depuis la configuration
    /// </summary>
    string GetTransitionVideoUrl()
    {
        Debug.Log("[IntroScreenManager] 🔍 Vérification de la vidéo de transition...");
        
        if (GeneralConfigManager.Instance == null)
        {
            Debug.LogWarning("[IntroScreenManager] ⚠️ GeneralConfigManager.Instance est NULL");
            return null;
        }
        
        var config = GeneralConfigManager.Instance.GetConfig();
        if (config == null)
        {
            Debug.LogWarning("[IntroScreenManager] ⚠️ GeneralConfig est NULL");
            return null;
        }
        
        if (config.introScene == null)
        {
            Debug.LogWarning("[IntroScreenManager] ⚠️ config.introScene est NULL - La section 'introScene' n'existe pas dans general-config.json");
            return null;
        }
        
        if (string.IsNullOrEmpty(config.introScene.transitionVideoUrl))
        {
            Debug.LogWarning("[IntroScreenManager] ⚠️ transitionVideoUrl est vide ou null");
            return null;
        }
        
        Debug.Log($"[IntroScreenManager] ✅ Vidéo de transition trouvée: {config.introScene.transitionVideoUrl}");
        return config.introScene.transitionVideoUrl;
    }
    
    /// <summary>
    /// Passe à la scène suivante
    /// </summary>
    void ProceedToNextScene()
    {
        // Si la scène est déjà prête, l'activer immédiatement
        if (isSceneReady && sceneLoadOperation != null)
        {
            LogVerbose("[IntroScreenManager] ✅ Scène déjà prête - Activation immédiate !");
            ActivateScene();
        }
        else if (sceneLoadOperation != null)
        {
            // La scène n'est pas encore prête, afficher un indicateur
            LogVerbose("[IntroScreenManager] ⏳ Scène pas encore prête - En attente...");
            ShowLoadingIndicator();
        }
        else
        {
            // Pas de préchargement, charger normalement
            LogVerbose("[IntroScreenManager] 📦 Pas de préchargement - Chargement direct");
            GoToNextSceneDirect();
        }
    }
    
    /// <summary>
    /// Affiche un indicateur de chargement si la scène n'est pas encore prête
    /// </summary>
    void ShowLoadingIndicator()
    {
        if (loadingIndicator != null) return;
        
        // Créer un indicateur de chargement sous le bouton
        GameObject loadingObj = new GameObject("LoadingIndicator");
        loadingObj.transform.SetParent(mainCanvas.transform, false);
        
        RectTransform loadingRect = loadingObj.AddComponent<RectTransform>();
        loadingRect.anchorMin = new Vector2(0.5f, 0f);
        loadingRect.anchorMax = new Vector2(0.5f, 0f);
        loadingRect.pivot = new Vector2(0.5f, 0f);
        loadingRect.sizeDelta = new Vector2(400, 40);
        loadingRect.anchoredPosition = new Vector2(0, buttonBottomMargin - 50);
        
        loadingIndicator = loadingObj.AddComponent<TextMeshProUGUI>();
        loadingIndicator.text = "Chargement...";
        loadingIndicator.fontSize = 24;
        loadingIndicator.color = Color.white;
        loadingIndicator.alignment = TextAlignmentOptions.Center;
        
        TMP_FontAsset antonFont = Resources.Load<TMP_FontAsset>("Fonts/Anton-Regular SDF");
        if (antonFont != null)
        {
            loadingIndicator.font = antonFont;
        }
    }

    void Update()
    {
        // Le passage à la scène suivante se fait exclusivement via le bouton COMMENCER
        // Pas de détection de clic global
    }

    /// <summary>
    /// Chargement direct de la scène (fallback si pas de préchargement)
    /// </summary>
    void GoToNextSceneDirect()
    {
        if (hasCompleted) return;
        hasCompleted = true;
        
        LogVerbose($"[IntroScreenManager] 🚀 Chargement direct de la scène: {nextSceneName}");
        
        // Arrêter la vidéo si elle joue encore
        if (videoPlayer != null && videoPlayer.isPlaying)
        {
            videoPlayer.Stop();
        }

        // 🔧 SÉCURITÉ : masquer tout overlay noir persistant avant le changement de scène
        CleanupPersistentOverlaysBeforeSceneChange();
        
        // Charger la scène directement
        SceneManager.LoadScene(nextSceneName);
    }

    /// <summary>
    /// Nettoie les overlays persistants (transition/loading) qui peuvent rester au-dessus de la scène suivante.
    /// </summary>
    private void CleanupPersistentOverlaysBeforeSceneChange()
    {
        // Remettre un timeScale normal au cas où (certains flows mettent en pause)
        Time.timeScale = 1f;

        // Overlay de transition (SceneTransitionManager)
        try { SceneTransitionManager.HideTransitionOverlayImmediate(); } catch { }

        // Overlay de secours (UnifiedLoadingManager)
        try { UnifiedLoadingManager.HideFallbackOverlay(); } catch { }

        // Nettoyage défensif si jamais un overlay a été instancié mais les singletons ne sont pas accessibles
        var transition = GameObject.Find("SceneTransitionOverlay");
        if (transition != null) Destroy(transition);
        var fallback = GameObject.Find("UnifiedLoadingFallbackOverlay");
        if (fallback != null) Destroy(fallback);
    }

    void OnDestroy()
    {
        // Nettoyer la RenderTexture
        if (renderTexture != null)
        {
            renderTexture.Release();
            Destroy(renderTexture);
        }
    }
    
    // ========== Vidéo de transition ==========
    
    /// <summary>
    /// Joue la vidéo de transition en plein écran avec bouton "PASSER"
    /// </summary>
    IEnumerator PlayTransitionVideo(string videoUrl)
    {
        LogVerbose($"[IntroScreenManager] 🎬 Lecture de la vidéo de transition: {videoUrl}");
        
        // Récupérer la configuration
        bool skipable = true;
        bool autoAdvance = true;
        string skipButtonText = "PASSER";
        
        if (GeneralConfigManager.Instance != null)
        {
            var config = GeneralConfigManager.Instance.GetConfig();
            if (config?.introScene != null)
            {
                skipable = config.introScene.transitionVideoSkipable;
                autoAdvance = config.introScene.transitionVideoAutoAdvance;
                if (!string.IsNullOrEmpty(config.introScene.skipButtonText))
                {
                    skipButtonText = config.introScene.skipButtonText;
                }
            }
        }
        
        // Masquer le contenu actuel (titre et bouton)
        if (titleCanvasGroup != null) titleCanvasGroup.alpha = 0f;
        if (buttonCanvasGroup != null) buttonCanvasGroup.alpha = 0f;
        
        // Créer un nouveau Canvas pour la vidéo de transition
        GameObject transitionCanvasObj = new GameObject("TransitionVideoCanvas");
        Canvas transitionCanvas = transitionCanvasObj.AddComponent<Canvas>();
        transitionCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
        transitionCanvas.sortingOrder = 200; // Au-dessus de tout
        
        CanvasScaler scaler = transitionCanvasObj.AddComponent<CanvasScaler>();
        scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
        scaler.referenceResolution = new Vector2(1920, 1080);
        scaler.matchWidthOrHeight = 0.5f;
        
        transitionCanvasObj.AddComponent<GraphicRaycaster>();
        
        // Fond noir
        GameObject bgObj = new GameObject("BlackBackground");
        bgObj.transform.SetParent(transitionCanvas.transform, false);
        RectTransform bgRect = bgObj.AddComponent<RectTransform>();
        bgRect.anchorMin = Vector2.zero;
        bgRect.anchorMax = Vector2.one;
        bgRect.offsetMin = Vector2.zero;
        bgRect.offsetMax = Vector2.zero;
        Image bgImage = bgObj.AddComponent<Image>();
        bgImage.color = Color.black;
        
        // Créer un CanvasGroup pour le fade
        CanvasGroup videoCanvasGroup = transitionCanvasObj.AddComponent<CanvasGroup>();
        videoCanvasGroup.alpha = 0f;
        
        // Créer la RenderTexture pour la vidéo
        RenderTexture transitionRT = new RenderTexture(1920, 1080, 0);
        transitionRT.Create();
        
        // Créer le VideoPlayer
        GameObject videoPlayerObj = new GameObject("TransitionVideoPlayer");
        VideoPlayer transitionVP = videoPlayerObj.AddComponent<VideoPlayer>();
        transitionVP.playOnAwake = false;
        transitionVP.renderMode = VideoRenderMode.RenderTexture;
        transitionVP.targetTexture = transitionRT;
        transitionVP.isLooping = false;
        transitionVP.aspectRatio = VideoAspectRatio.FitInside;
        transitionVP.url = videoUrl;
        
        // Configuration audio
        transitionVP.audioOutputMode = VideoAudioOutputMode.AudioSource;
        transitionVP.controlledAudioTrackCount = 1;
        
        AudioSource audioSource = videoPlayerObj.AddComponent<AudioSource>();
        audioSource.playOnAwake = false;
        audioSource.volume = 1.0f;
        audioSource.spatialBlend = 0f;
        
        transitionVP.EnableAudioTrack(0, true);
        transitionVP.SetTargetAudioSource(0, audioSource);
        
        // Créer le RawImage pour afficher la vidéo
        GameObject displayObj = new GameObject("VideoDisplay");
        displayObj.transform.SetParent(transitionCanvas.transform, false);
        
        RectTransform displayRect = displayObj.AddComponent<RectTransform>();
        displayRect.anchorMin = Vector2.zero;
        displayRect.anchorMax = Vector2.one;
        displayRect.offsetMin = Vector2.zero;
        displayRect.offsetMax = Vector2.zero;
        
        RawImage videoDisplay = displayObj.AddComponent<RawImage>();
        videoDisplay.texture = transitionRT;
        videoDisplay.color = Color.white;
        
        // Variables de contrôle
        bool videoFinished = false;
        bool userSkipped = false;
        bool canSkip = false;
        
        // Callback quand la vidéo se termine
        transitionVP.loopPointReached += (vp) =>
        {
            LogVerbose("[IntroScreenManager] 🏁 Vidéo de transition terminée");
            if (autoAdvance && !videoFinished)
            {
                videoFinished = true;
            }
        };
        
        // Créer le bouton "PASSER" si skipable
        GameObject skipButton = null;
        if (skipable)
        {
            skipButton = new GameObject("SkipButton");
            skipButton.transform.SetParent(transitionCanvas.transform, false);
            
            RectTransform skipRect = skipButton.AddComponent<RectTransform>();
            skipRect.anchorMin = new Vector2(1f, 0f);
            skipRect.anchorMax = new Vector2(1f, 0f);
            skipRect.pivot = new Vector2(1f, 0f);
            skipRect.sizeDelta = new Vector2(200f, 60f);
            skipRect.anchoredPosition = new Vector2(-30f, 30f);
            
            Image skipBg = skipButton.AddComponent<Image>();
            skipBg.color = new Color(0f, 0f, 0f, 0.7f);
            
            Button btn = skipButton.AddComponent<Button>();
            btn.targetGraphic = skipBg;
            btn.onClick.AddListener(() =>
            {
                if (canSkip)
                {
                    LogVerbose("[IntroScreenManager] ⏭️ Vidéo de transition skippée");
                    userSkipped = true;
                }
            });
            
            GameObject textObj = new GameObject("Text");
            textObj.transform.SetParent(skipButton.transform, false);
            
            RectTransform textRect = textObj.AddComponent<RectTransform>();
            textRect.anchorMin = Vector2.zero;
            textRect.anchorMax = Vector2.one;
            textRect.offsetMin = Vector2.zero;
            textRect.offsetMax = Vector2.zero;
            
            TextMeshProUGUI skipText = textObj.AddComponent<TextMeshProUGUI>();
            skipText.text = skipButtonText;
            skipText.fontSize = 20;
            skipText.alignment = TextAlignmentOptions.Center;
            skipText.color = Color.white;
        }
        
        // Préparer et jouer la vidéo
        transitionVP.Prepare();
        
        float timeout = 10f;
        float elapsed = 0f;
        while (!transitionVP.isPrepared && elapsed < timeout)
        {
            elapsed += Time.deltaTime;
            yield return null;
        }
        
        if (!transitionVP.isPrepared)
        {
            Debug.LogError("[IntroScreenManager] ❌ Timeout préparation vidéo de transition!");
            Destroy(transitionCanvasObj);
            transitionRT.Release();
            Destroy(transitionRT);
            ProceedToNextScene();
            yield break;
        }
        
        // Fade in
        transitionVP.Play();
        float fadeInTime = 0.5f;
        elapsed = 0f;
        while (elapsed < fadeInTime)
        {
            elapsed += Time.deltaTime;
            videoCanvasGroup.alpha = Mathf.Lerp(0f, 1f, elapsed / fadeInTime);
            yield return null;
        }
        videoCanvasGroup.alpha = 1f;
        canSkip = true;
        
        // Attendre la fin de la vidéo ou le skip
        while (!videoFinished && !userSkipped)
        {
            yield return null;
        }
        
        // Fade out
        canSkip = false;
        float fadeOutTime = 0.5f;
        elapsed = 0f;
        while (elapsed < fadeOutTime)
        {
            elapsed += Time.deltaTime;
            videoCanvasGroup.alpha = Mathf.Lerp(1f, 0f, elapsed / fadeOutTime);
            yield return null;
        }
        
        // Nettoyer
        if (transitionVP.isPlaying) transitionVP.Stop();
        Destroy(transitionCanvasObj);
        transitionRT.Release();
        Destroy(transitionRT);
        Destroy(videoPlayerObj);
        
        // Passer à la scène suivante
        ProceedToNextScene();
    }
    
    // ========== Utilitaires pour créer le sprite du bouton ==========
    
    /// <summary>
    /// Convertit une couleur hexadécimale en Color
    /// </summary>
    Color HexToColor(string hex)
    {
        if (string.IsNullOrEmpty(hex)) return Color.white;
        
        hex = hex.TrimStart('#');
        
        if (hex.Length == 6)
        {
            byte r = byte.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
            byte g = byte.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
            byte b = byte.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
            return new Color32(r, g, b, 255);
        }
        else if (hex.Length == 8)
        {
            byte r = byte.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
            byte g = byte.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
            byte b = byte.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
            byte a = byte.Parse(hex.Substring(6, 2), System.Globalization.NumberStyles.HexNumber);
            return new Color32(r, g, b, a);
        }
        
        return Color.white;
    }
    
    /// <summary>
    /// Crée un sprite avec dégradé et bordure arrondie
    /// </summary>
    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();

        return Sprite.Create(texture, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f), 100f);
    }
}
