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

public class SceneTransitionManager : MonoBehaviour
{
    private static SceneTransitionManager instance;
    private static GameObject transitionOverlay;
    private static bool isTransitionInProgress = false;
    private static string currentTargetScene = null;
    private Coroutine activeTransitionCoroutine;

    public static bool IsTransitionInProgress => isTransitionInProgress;
    
    void Awake()
    {
        // Singleton pattern
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }
    
    public static void LoadSceneWithTransition(string sceneName)
    {
        // Anti double-clic / anti courses : une seule transition à la fois
        if (isTransitionInProgress)
        {
            Debug.LogWarning($"[SceneTransitionManager] ⚠️ Transition déjà en cours vers '{currentTargetScene}', demande ignorée vers '{sceneName}'");
            return;
        }

        // Si l'instance n'existe pas, essayer de la trouver ou la créer
        if (instance == null)
        {
            Debug.LogWarning("[SceneTransitionManager] Instance introuvable, recherche dans la scène...");
            instance = FindFirstObjectByType<SceneTransitionManager>();
            
            if (instance == null)
            {
                Debug.LogWarning("[SceneTransitionManager] Instance toujours introuvable, création d'une nouvelle instance...");
                GameObject managerObj = new GameObject("SceneTransitionManager");
                instance = managerObj.AddComponent<SceneTransitionManager>();
                DontDestroyOnLoad(managerObj);
            }
        }
        
        if (instance != null)
        {
            instance.activeTransitionCoroutine = instance.StartCoroutine(instance.TransitionToScene(sceneName));
        }
        else
        {
            // Fallback ultime : charger directement la scène sans transition
            Debug.LogError("[SceneTransitionManager] Impossible de créer une instance, chargement direct de la scène");
            SceneManager.LoadScene(sceneName);
        }
    }
    
    IEnumerator TransitionToScene(string sceneName)
    {
        isTransitionInProgress = true;
        currentTargetScene = sceneName;

        bool success = false;

        // Vérifier que la scène existe
        if (!SceneExists(sceneName))
        {
            Debug.LogError($"[SceneTransitionManager] La scène '{sceneName}' n'existe pas !");
            CleanupOverlayImmediate();
            isTransitionInProgress = false;
            currentTargetScene = null;
            yield break;
        }
        
        // Créer écran noir IMMÉDIATEMENT
        CreatePersistentOverlay();
        
        // Charger la scène de façon asynchrone
        AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
        
        if (asyncLoad == null)
        {
            Debug.LogError($"[SceneTransitionManager] Échec du chargement asynchrone de {sceneName}, tentative de chargement direct...");
            SceneManager.LoadScene(sceneName);
            CleanupOverlayImmediate();
            isTransitionInProgress = false;
            currentTargetScene = null;
            yield break;
        }
        
        // Attendre que la scène soit complètement chargée
        float timeout = 10f; // Timeout de 10 secondes
        float elapsed = 0f;
        
        while (!asyncLoad.isDone)
        {
            elapsed += Time.deltaTime;
            if (elapsed > timeout)
            {
                Debug.LogError($"[SceneTransitionManager] Timeout lors du chargement de {sceneName}, chargement direct...");
                SceneManager.LoadScene(sceneName);
                CleanupOverlayImmediate();
                isTransitionInProgress = false;
                currentTargetScene = null;
                yield break;
            }
            yield return null;
        }
        
        // Vérifier que la scène a bien été chargée
        yield return new WaitForSeconds(0.1f);
        if (SceneManager.GetActiveScene().name != sceneName)
        {
            Debug.LogWarning($"[SceneTransitionManager] La scène chargée ne correspond pas ({SceneManager.GetActiveScene().name} au lieu de {sceneName}), nouvelle tentative...");
            SceneManager.LoadScene(sceneName);
            CleanupOverlayImmediate();
            isTransitionInProgress = false;
            currentTargetScene = null;
            yield break;
        }
        
        // Attendre encore un peu pour que tout soit initialisé
        yield return new WaitForSeconds(0.5f);
        
        // Faire disparaître l'overlay
        if (transitionOverlay != null)
        {
            StartCoroutine(FadeOutOverlay());
            success = true;
        }

        // Déverrouiller (même si overlay est null)
        isTransitionInProgress = false;
        currentTargetScene = null;
        activeTransitionCoroutine = null;
    }
    
    private bool SceneExists(string sceneName)
    {
        for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++)
        {
            string scenePath = UnityEngine.SceneManagement.SceneUtility.GetScenePathByBuildIndex(i);
            string sceneNameInBuild = System.IO.Path.GetFileNameWithoutExtension(scenePath);
            if (sceneNameInBuild == sceneName)
            {
                return true;
            }
        }
        return false;
    }
    
    void CreatePersistentOverlay()
    {
        if (transitionOverlay != null)
        {
            Destroy(transitionOverlay);
        }
        
        // Créer un overlay qui survit au changement de scène
        transitionOverlay = new GameObject("SceneTransitionOverlay");
        DontDestroyOnLoad(transitionOverlay);
        
        // Utiliser un SpriteRenderer pour être indépendant des Canvas
        SpriteRenderer sr = transitionOverlay.AddComponent<SpriteRenderer>();
        
        // Texture noire
        Texture2D blackTexture = new Texture2D(1, 1);
        blackTexture.SetPixel(0, 0, Color.black);
        blackTexture.Apply();
        
        sr.sprite = Sprite.Create(blackTexture, new Rect(0, 0, 1, 1), Vector2.one * 0.5f);
        sr.sortingOrder = 32767; // Valeur maximale
        
        // Couvrir tout l'écran
        Camera mainCam = Camera.main;
        if (mainCam != null)
        {
            float height = mainCam.orthographicSize * 2f;
            float width = height * mainCam.aspect;
            transitionOverlay.transform.localScale = new Vector3(width * 2, height * 2, 1);
            transitionOverlay.transform.position = new Vector3(0, 0, -5);
        }
        
    }

    private void CleanupOverlayImmediate()
    {
        if (transitionOverlay == null) return;

        SpriteRenderer sr = transitionOverlay.GetComponent<SpriteRenderer>();
        if (sr != null && sr.sprite != null)
        {
            Texture2D tex = sr.sprite.texture;
            Destroy(sr.sprite);
            if (tex != null) Destroy(tex);
        }

        Destroy(transitionOverlay);
        transitionOverlay = null;
    }
    
    IEnumerator FadeOutOverlay()
    {
        if (transitionOverlay == null) yield break;
        SpriteRenderer sr = transitionOverlay.GetComponent<SpriteRenderer>();
        
        float fadeTime = 0.5f;
        float elapsedTime = 0f;
        
        while (elapsedTime < fadeTime)
        {
            elapsedTime += Time.deltaTime;
            float alpha = 1f - (elapsedTime / fadeTime);
            if (sr != null) sr.color = new Color(0, 0, 0, alpha);
            yield return null;
        }

        // Détruire aussi les ressources créées (sprite + texture 1x1)
        if (sr != null && sr.sprite != null)
        {
            Texture2D tex = sr.sprite.texture;
            Destroy(sr.sprite);
            if (tex != null) Destroy(tex);
        }

        Destroy(transitionOverlay);
        transitionOverlay = null;
    }
}