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

/// <summary>
/// Gestionnaire unifié pour les transitions de scènes avec écran de chargement
/// Peut utiliser soit l'écran de chargement intégré, soit une scène dédiée
/// </summary>
public class UnifiedLoadingManager : MonoBehaviour
{
    [Header("Configuration")]
    [SerializeField] private bool useDedicatedLoadingScene = false;
    [SerializeField] private string loadingSceneName = "LoadingScene";
    [SerializeField] private float minimumLoadingTime = 1.0f;
    
    [Header("Messages par contexte")]
    [SerializeField] private string gameLoadingMessage = "Chargement du jeu...";
    [SerializeField] private string mapLoadingMessage = "Chargement de la carte...";
    [SerializeField] private string videoLoadingMessage = "Chargement de la vidéo...";
    [SerializeField] private string menuLoadingMessage = "Retour au menu...";
    
    private static UnifiedLoadingManager instance;
    private LoadingScreenManager loadingScreenManager;
    
    // Overlay noir de secours si LoadingScreenManager n'est pas disponible
    private static GameObject fallbackOverlay;
    
    public static UnifiedLoadingManager Instance => instance;
    
    void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
            
            // Trouver le LoadingScreenManager (optionnel)
            loadingScreenManager = FindFirstObjectByType<LoadingScreenManager>();
        }
        else
        {
            Destroy(gameObject);
        }
    }
    
    /// <summary>
    /// Charge une scène avec l'écran de chargement approprié
    /// </summary>
    public static void LoadScene(string sceneName, LoadingContext context = LoadingContext.General, bool useDedicatedScene = false)
    {
        if (instance != null)
        {
            instance.StartCoroutine(instance.LoadSceneCoroutine(sceneName, context, useDedicatedScene));
        }
        else
        {
            Debug.LogError("UnifiedLoadingManager instance non trouvée !");
            SceneManager.LoadScene(sceneName);
        }
    }
    
    /// <summary>
    /// Charge une scène avec un message de chargement personnalisé
    /// </summary>
    public static void LoadScene(string sceneName, string loadingMessage, bool useDedicatedScene = false)
    {
        if (instance != null)
        {
            instance.StartCoroutine(instance.LoadSceneWithMessageCoroutine(sceneName, loadingMessage, useDedicatedScene));
        }
        else
        {
            Debug.LogError("UnifiedLoadingManager instance non trouvée !");
            SceneManager.LoadScene(sceneName);
        }
    }
    
    /// <summary>
    /// Affiche l'écran de chargement pour une opération en cours
    /// </summary>
    public static void ShowLoading(string message = null, LoadingContext context = LoadingContext.General)
    {
        if (instance != null && instance.loadingScreenManager != null)
        {
            if (string.IsNullOrEmpty(message))
            {
                message = instance.GetContextMessage(context);
            }
            
            instance.loadingScreenManager.ShowLoading(message);
        }
    }
    
    /// <summary>
    /// Cache l'écran de chargement
    /// </summary>
    public static void HideLoading()
    {
        if (instance != null && instance.loadingScreenManager != null)
        {
            instance.loadingScreenManager.HideLoading();
        }
    }
    
    /// <summary>
    /// Cache l'écran de chargement après un délai
    /// </summary>
    public static void HideLoadingAfterDelay(float delay)
    {
        if (instance != null && instance.loadingScreenManager != null)
        {
            instance.loadingScreenManager.HideLoadingAfterDelay(delay);
        }
    }
    
    IEnumerator LoadSceneCoroutine(string sceneName, LoadingContext context, bool useDedicatedScene)
    {
        string loadingMessage = GetContextMessage(context);
        
        if (useDedicatedScene || useDedicatedLoadingScene)
        {
            // Utiliser la scène de chargement dédiée
            PlayerPrefs.SetString("LoadingTargetScene", sceneName);
            PlayerPrefs.SetString("LoadingMessage", loadingMessage);
            PlayerPrefs.SetFloat("MinimumLoadingTime", minimumLoadingTime);
            SceneManager.LoadScene(loadingSceneName);
        }
        else
        {
            // 🖤 NOUVEAU : Créer un overlay noir IMMÉDIATEMENT avant de charger la scène
            bool usingFallbackOverlay = false;
            if (loadingScreenManager != null)
            {
                loadingScreenManager.ShowLoading(loadingMessage, true);
            }
            else
            {
                // Créer un overlay noir de secours
                CreateFallbackOverlay();
                usingFallbackOverlay = true;
                Debug.Log("[UnifiedLoadingManager] 🖤 Overlay noir de secours créé (LoadingScreenManager non disponible)");
            }
            
            // Charger la scène de façon asynchrone
            AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
            
            // Attendre que la scène soit chargée
            while (!asyncLoad.isDone)
            {
                yield return null;
            }
            
            // Attendre un peu pour que tout soit initialisé
            yield return new WaitForSeconds(0.3f);
            
            // Masquer l'écran de chargement
            if (loadingScreenManager != null && !usingFallbackOverlay)
            {
                loadingScreenManager.HideLoading();
            }
            
            // L'overlay de secours sera masqué par la scène cible via HideFallbackOverlay()
            // ou automatiquement après un délai
            if (usingFallbackOverlay)
            {
                yield return new WaitForSeconds(0.2f);
                HideFallbackOverlayWithFade();
            }
        }
    }
    
    IEnumerator LoadSceneWithMessageCoroutine(string sceneName, string loadingMessage, bool useDedicatedScene)
    {
        if (useDedicatedScene || useDedicatedLoadingScene)
        {
            // Utiliser la scène de chargement dédiée
            PlayerPrefs.SetString("LoadingTargetScene", sceneName);
            PlayerPrefs.SetString("LoadingMessage", loadingMessage);
            PlayerPrefs.SetFloat("MinimumLoadingTime", minimumLoadingTime);
            SceneManager.LoadScene(loadingSceneName);
        }
        else
        {
            // 🖤 NOUVEAU : Créer un overlay noir IMMÉDIATEMENT avant de charger la scène
            bool usingFallbackOverlay = false;
            if (loadingScreenManager != null)
            {
                loadingScreenManager.ShowLoading(loadingMessage, true);
            }
            else
            {
                // Créer un overlay noir de secours
                CreateFallbackOverlay();
                usingFallbackOverlay = true;
                Debug.Log("[UnifiedLoadingManager] 🖤 Overlay noir de secours créé (LoadingScreenManager non disponible)");
            }
            
            // Charger la scène de façon asynchrone
            AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
            
            // Attendre que la scène soit chargée
            while (!asyncLoad.isDone)
            {
                yield return null;
            }
            
            // Attendre un peu pour que tout soit initialisé
            yield return new WaitForSeconds(0.3f);
            
            // Masquer l'écran de chargement
            if (loadingScreenManager != null && !usingFallbackOverlay)
            {
                loadingScreenManager.HideLoading();
            }
            
            // L'overlay de secours sera masqué par la scène cible via HideFallbackOverlay()
            // ou automatiquement après un délai
            if (usingFallbackOverlay)
            {
                yield return new WaitForSeconds(0.2f);
                HideFallbackOverlayWithFade();
            }
        }
    }
    
    /// <summary>
    /// Crée un overlay noir de secours qui persiste entre les scènes
    /// </summary>
    private void CreateFallbackOverlay()
    {
        // Détruire l'ancien overlay s'il existe
        if (fallbackOverlay != null)
        {
            Destroy(fallbackOverlay);
        }
        
        // Créer un Canvas overlay noir
        fallbackOverlay = new GameObject("UnifiedLoadingFallbackOverlay");
        DontDestroyOnLoad(fallbackOverlay);
        
        Canvas canvas = fallbackOverlay.AddComponent<Canvas>();
        canvas.renderMode = RenderMode.ScreenSpaceOverlay;
        canvas.sortingOrder = 32000; // Très haut pour être au-dessus de tout
        
        CanvasGroup canvasGroup = fallbackOverlay.AddComponent<CanvasGroup>();
        canvasGroup.alpha = 1f;
        canvasGroup.blocksRaycasts = true;
        
        // Créer le panneau noir
        GameObject blackPanel = new GameObject("BlackPanel");
        blackPanel.transform.SetParent(fallbackOverlay.transform, false);
        
        RectTransform rectTransform = blackPanel.AddComponent<RectTransform>();
        rectTransform.anchorMin = Vector2.zero;
        rectTransform.anchorMax = Vector2.one;
        rectTransform.sizeDelta = Vector2.zero;
        rectTransform.anchoredPosition = Vector2.zero;
        
        Image blackImage = blackPanel.AddComponent<Image>();
        blackImage.color = Color.black;
        blackImage.raycastTarget = true;
    }
    
    /// <summary>
    /// Masque l'overlay de secours avec un fade out
    /// </summary>
    private void HideFallbackOverlayWithFade()
    {
        if (fallbackOverlay != null)
        {
            StartCoroutine(FadeOutFallbackOverlay());
        }
    }
    
    private IEnumerator FadeOutFallbackOverlay()
    {
        if (fallbackOverlay == null) yield break;
        
        CanvasGroup canvasGroup = fallbackOverlay.GetComponent<CanvasGroup>();
        if (canvasGroup != null)
        {
            float fadeDuration = 0.3f;
            float elapsed = 0f;
            
            while (elapsed < fadeDuration)
            {
                elapsed += Time.deltaTime;
                canvasGroup.alpha = Mathf.Lerp(1f, 0f, elapsed / fadeDuration);
                yield return null;
            }
        }
        
        if (fallbackOverlay != null)
        {
            Destroy(fallbackOverlay);
            fallbackOverlay = null;
            Debug.Log("[UnifiedLoadingManager] ✅ Overlay noir de secours détruit");
        }
    }
    
    /// <summary>
    /// Permet aux scènes de masquer l'overlay de secours manuellement
    /// </summary>
    public static void HideFallbackOverlay()
    {
        if (instance != null)
        {
            instance.HideFallbackOverlayWithFade();
        }
        else if (fallbackOverlay != null)
        {
            Destroy(fallbackOverlay);
            fallbackOverlay = null;
        }
    }
    
    /// <summary>
    /// Vérifie si l'overlay de secours est visible
    /// </summary>
    public static bool IsFallbackOverlayVisible => fallbackOverlay != null;
    
    string GetContextMessage(LoadingContext context)
    {
        switch (context)
        {
            case LoadingContext.Game:
                return gameLoadingMessage;
            case LoadingContext.Map:
                return mapLoadingMessage;
            case LoadingContext.Video:
                return videoLoadingMessage;
            case LoadingContext.Menu:
                return menuLoadingMessage;
            default:
                return "Chargement en cours...";
        }
    }
    
    /// <summary>
    /// Méthodes de convenance pour les cas d'usage courants
    /// </summary>
    public static void LoadGameScene(string sceneName) => LoadScene(sceneName, LoadingContext.Game);
    public static void LoadMapScene(string sceneName) => LoadScene(sceneName, LoadingContext.Map);
    public static void LoadVideoScene(string sceneName) => LoadScene(sceneName, LoadingContext.Video);
    public static void LoadMenuScene(string sceneName) => LoadScene(sceneName, LoadingContext.Menu);
    
    /// <summary>
    /// Force l'utilisation de la scène de chargement dédiée pour la prochaine transition
    /// </summary>
    public static void UseDedicatedLoadingScene(bool use = true)
    {
        if (instance != null)
        {
            instance.useDedicatedLoadingScene = use;
        }
    }
}

/// <summary>
/// Contexte de chargement pour personnaliser les messages
/// </summary>
public enum LoadingContext
{
    General,
    Game,
    Map,
    Video,
    Menu
}
