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

/// <summary>
/// Gestionnaire commun pour créer et gérer le header dans toutes les scènes
/// </summary>
public class HeaderManager : MonoBehaviour
{
    private static HeaderManager _instance;
    public static HeaderManager Instance
    {
        get
        {
            if (_instance == null)
            {
                GameObject obj = new GameObject("HeaderManager");
                _instance = obj.AddComponent<HeaderManager>();
                DontDestroyOnLoad(obj);
            }
            return _instance;
        }
    }

    private GameObject headerPanel;
    private System.Action<string> onHeaderElementClick;

    // Cache simple des sprites du header (évite re-téléchargements + fuites en WebGL)
    private readonly Dictionary<string, Sprite> spriteCache = new Dictionary<string, Sprite>();
    private readonly Dictionary<string, Texture2D> textureCache = new Dictionary<string, Texture2D>();
    
    /// <summary>
    /// Configure le callback pour les clics sur les éléments du header (utilisé pour les headers personnalisés)
    /// </summary>
    public void SetHeaderElementClickCallback(System.Action<string> callback)
    {
        onHeaderElementClick = callback;
    }
    
    /// <summary>
    /// Masque le header (utilisé pendant les vidéos plein écran)
    /// </summary>
    public void HideHeader()
    {
        if (headerPanel != null)
        {
            headerPanel.SetActive(false);
            Debug.Log("[HeaderManager] Header masqué");
        }
    }
    
    /// <summary>
    /// Affiche le header (après une vidéo plein écran)
    /// </summary>
    public void ShowHeader()
    {
        // Ne pas réafficher le header si une vidéo plein écran est en cours
        MapManager mapManager = FindFirstObjectByType<MapManager>();
        if (mapManager != null && mapManager.IsFullscreenVideoPlaying())
        {
            Debug.Log("[HeaderManager] Tentative d'affichage du header bloquée - vidéo plein écran en cours");
            return;
        }
        
        if (headerPanel != null)
        {
            headerPanel.SetActive(true);
            Debug.Log("[HeaderManager] Header affiché");
        }
    }

    void Awake()
    {
        if (_instance == null)
        {
            _instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else if (_instance != this)
        {
            Destroy(gameObject);
        }
    }

    /// <summary>
    /// Crée le header dans la scène actuelle en utilisant la configuration depuis general-config.json
    /// </summary>
    public IEnumerator CreateHeader(Canvas canvas, System.Action<string> onClickCallback = null)
    {
        if (canvas == null)
        {
            Debug.LogError("[HeaderManager] Canvas introuvable pour créer le header");
            yield break;
        }

        onHeaderElementClick = onClickCallback;

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

        // Obtenir la configuration depuis general-config.json
        DefaultHeaderConfig headerConfig = GeneralConfigManager.Instance.GetDefaultHeaderConfig();
        
        if (headerConfig == null || !headerConfig.show)
        {
            Debug.Log("[HeaderManager] Header désactivé dans la configuration");
            yield break;
        }

        // Détecter la scène actuelle
        string currentSceneName = SceneManager.GetActiveScene().name;
        Debug.Log($"[HeaderManager] Scène actuelle: {currentSceneName}");

        Debug.Log($"[HeaderManager] Création du header - Canvas: {canvas.name}");

        // Détruire l'ancien header s'il existe
        if (headerPanel != null)
        {
            Destroy(headerPanel);
        }

        headerPanel = new GameObject("HeaderPanel");
        headerPanel.transform.SetParent(canvas.transform, false);

        RectTransform headerRect = headerPanel.AddComponent<RectTransform>();
        headerRect.anchorMin = new Vector2(0f, 1f);
        headerRect.anchorMax = new Vector2(1f, 1f);
        headerRect.pivot = new Vector2(0.5f, 1f);
        headerRect.sizeDelta = new Vector2(0f, headerConfig.height);
        headerRect.anchoredPosition = Vector2.zero;

        Image headerBg = headerPanel.AddComponent<Image>();
        if (ColorUtility.TryParseHtmlString(headerConfig.backgroundColor, out Color bgColor))
        {
            headerBg.color = bgColor;
        }
        // IMPORTANT : Ne pas bloquer les raycasts sur le header background pour permettre les clics sur les éléments
        headerBg.raycastTarget = false;

        // Adapter le header selon la scène
        if (currentSceneName == "main")
        {
            // Scène main : seulement rightElement (settings)
            Debug.Log("[HeaderManager] Scène 'main' détectée - Affichage uniquement du rightElement");
            if (headerConfig.rightElement != null)
            {
                yield return StartCoroutine(CreateHeaderElement(headerConfig.rightElement, "RightElement", false));
            }
        }
        else if (currentSceneName == "Map")
        {
            // Scène Map : rightElement + leftElement avec jauge dynamique
            Debug.Log("[HeaderManager] Scène 'Map' détectée - Affichage du rightElement et leftElement avec jauge dynamique");
            
            // Créer l'élément de droite (settings)
            if (headerConfig.rightElement != null)
            {
                yield return StartCoroutine(CreateHeaderElement(headerConfig.rightElement, "RightElement", false));
            }

            // Créer l'élément de gauche avec la jauge appropriée
            if (headerConfig.leftElement != null && headerConfig.jaugePhases != null)
            {
                // Obtenir la phase de jauge depuis MapManager
                MapManager mapManager = FindFirstObjectByType<MapManager>();
                int jaugePhase = 1; // Par défaut phase 1
                
                if (mapManager != null)
                {
                    jaugePhase = mapManager.GetJaugePhase();
                    Debug.Log($"[HeaderManager] Phase de jauge calculée: {jaugePhase}");
                }
                else
                {
                    Debug.LogWarning("[HeaderManager] MapManager introuvable, utilisation de la phase 1 par défaut");
                }

                // Sélectionner l'URL de la jauge selon la phase
                string jaugeImageUrl = headerConfig.jaugePhases.phase1; // Par défaut
                if (jaugePhase == 2 && !string.IsNullOrEmpty(headerConfig.jaugePhases.phase2))
                {
                    jaugeImageUrl = headerConfig.jaugePhases.phase2;
                }
                else if (jaugePhase == 3 && !string.IsNullOrEmpty(headerConfig.jaugePhases.phase3))
                {
                    jaugeImageUrl = headerConfig.jaugePhases.phase3;
                }

                // Créer une copie de leftElement avec l'URL de jauge appropriée
                DefaultHeaderElement leftElementWithJauge = new DefaultHeaderElement
                {
                    imageUrl = jaugeImageUrl,
                    position = headerConfig.leftElement.position,
                    size = headerConfig.leftElement.size,
                    clickable = headerConfig.leftElement.clickable,
                    targetAction = headerConfig.leftElement.targetAction
                };

                yield return StartCoroutine(CreateHeaderElement(leftElementWithJauge, "LeftElement", true));
            }
            else if (headerConfig.leftElement != null)
            {
                // Fallback si jaugePhases n'est pas configuré
                yield return StartCoroutine(CreateHeaderElement(headerConfig.leftElement, "LeftElement", true));
            }
        }
        else
        {
            // Autres scènes : comportement par défaut (leftElement + rightElement)
            Debug.Log($"[HeaderManager] Scène '{currentSceneName}' - Comportement par défaut");

        // Créer l'élément de gauche
        if (headerConfig.leftElement != null)
        {
            yield return StartCoroutine(CreateHeaderElement(headerConfig.leftElement, "LeftElement", true));
        }

        // Créer l'élément de droite
        if (headerConfig.rightElement != null)
        {
            yield return StartCoroutine(CreateHeaderElement(headerConfig.rightElement, "RightElement", false));
            }
        }

        Debug.Log("[HeaderManager] Header créé avec succès");
        
        // Si une vidéo plein écran est en cours, masquer le header immédiatement
        MapManager videoCheckManager = FindFirstObjectByType<MapManager>();
        if (videoCheckManager != null && videoCheckManager.IsFullscreenVideoPlaying())
        {
            Debug.Log("[HeaderManager] Vidéo plein écran détectée - Masquage du header après création");
            HideHeader();
        }
    }

    IEnumerator CreateHeaderElement(DefaultHeaderElement elementData, string name, bool isLeft)
    {
        GameObject elementObj = new GameObject(name);
        elementObj.transform.SetParent(headerPanel.transform, false);

        RectTransform rt = elementObj.AddComponent<RectTransform>();

        if (isLeft)
        {
            rt.anchorMin = new Vector2(0f, 1f);
            rt.anchorMax = new Vector2(0f, 1f);
            rt.pivot = new Vector2(0f, 1f);
        }
        else
        {
            rt.anchorMin = new Vector2(1f, 1f);
            rt.anchorMax = new Vector2(1f, 1f);
            rt.pivot = new Vector2(1f, 1f);
        }

        rt.anchoredPosition = elementData.position;
        rt.sizeDelta = elementData.size;

        Image img = elementObj.AddComponent<Image>();
        img.raycastTarget = elementData.clickable;

        // S'assurer que le Canvas parent a un GraphicRaycaster
        Canvas parentCanvas = headerPanel.GetComponentInParent<Canvas>();
        if (parentCanvas != null && parentCanvas.GetComponent<GraphicRaycaster>() == null)
        {
            parentCanvas.gameObject.AddComponent<GraphicRaycaster>();
            Debug.Log("[HeaderManager] GraphicRaycaster ajouté au Canvas");
        }

        HeaderElementUI headerElement = elementObj.AddComponent<HeaderElementUI>();
        headerElement.Initialize(elementData, this);

        if (!string.IsNullOrEmpty(elementData.imageUrl))
        {
            yield return StartCoroutine(LoadOrGetHeaderSprite(elementData.imageUrl, (sprite) =>
            {
                headerElement.SetSprite(sprite);
                Debug.Log($"[HeaderManager] ✅ Image header assignée: {elementData.imageUrl}");
            }));
        }
    }

    /// <summary>
    /// Met à jour la jauge (LeftElement) dans la scène Map selon l'avancement courant.
    /// Appelée par MapManager lors des changements de step.
    /// </summary>
    public void RefreshMapJauge()
    {
        if (headerPanel == null) return;
        if (SceneManager.GetActiveScene().name != "Map") return;

        DefaultHeaderConfig headerConfig = GeneralConfigManager.Instance.GetDefaultHeaderConfig();
        if (headerConfig?.jaugePhases == null) return;

        MapManager mapManager = FindFirstObjectByType<MapManager>();
        int phase = 1;
        if (mapManager != null)
        {
            int computed = mapManager.GetJaugePhase();
            if (computed >= 1 && computed <= 3) phase = computed;
        }

        string imageUrl = headerConfig.jaugePhases.phase1;
        if (phase == 2 && !string.IsNullOrEmpty(headerConfig.jaugePhases.phase2)) imageUrl = headerConfig.jaugePhases.phase2;
        if (phase == 3 && !string.IsNullOrEmpty(headerConfig.jaugePhases.phase3)) imageUrl = headerConfig.jaugePhases.phase3;

        Transform left = headerPanel.transform.Find("LeftElement");
        if (left == null) return;

        HeaderElementUI ui = left.GetComponent<HeaderElementUI>();
        if (ui == null) return;

        StartCoroutine(LoadOrGetHeaderSprite(imageUrl, (sprite) =>
        {
            ui.SetSprite(sprite);
        }));
    }

    private IEnumerator LoadOrGetHeaderSprite(string imageUrl, System.Action<Sprite> onLoaded)
    {
        if (string.IsNullOrEmpty(imageUrl))
        {
            onLoaded?.Invoke(null);
            yield break;
        }

        if (spriteCache.TryGetValue(imageUrl, out Sprite cached) && cached != null)
        {
            onLoaded?.Invoke(cached);
            yield break;
        }

        string fullImageUrl = GeneralConfigManager.Instance.GetUIUrl(imageUrl);
        Debug.Log($"[HeaderManager] Chargement image header (cache miss): {fullImageUrl}");

        using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(fullImageUrl))
        {
            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));

                textureCache[imageUrl] = texture;
                spriteCache[imageUrl] = sprite;
                onLoaded?.Invoke(sprite);
            }
            else
            {
                Debug.LogError($"[HeaderManager] ❌ Erreur chargement image header: {www.error} (URL: {fullImageUrl})");
                onLoaded?.Invoke(null);
            }
        }
    }

    /// <summary>
    /// Appelé quand un élément du header est cliqué
    /// </summary>
    public void OnHeaderElementClick(string action)
    {
        Debug.Log($"[HeaderManager] OnHeaderElementClick appelé avec action: {action}");
        Debug.Log($"[HeaderManager] Callback disponible: {onHeaderElementClick != null}");
        
        if (onHeaderElementClick != null)
        {
            onHeaderElementClick.Invoke(action);
        }
        else
        {
            Debug.LogError("[HeaderManager] Aucun callback défini pour OnHeaderElementClick !");
        }
    }

    /// <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("[HeaderManager] ✅ 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("[HeaderManager] ✅ Nouvel EventSystem créé");
            }
        }
        else
        {
            Debug.Log("[HeaderManager] ✅ 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("[HeaderManager] ⚠️ StandaloneInputModule supprimé");
                }
                
                // Ajouter InputSystemUIInputModule
                eventSystem.gameObject.AddComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
                Debug.Log("[HeaderManager] ✅ InputSystemUIInputModule ajouté");
            }
            else
            {
                Debug.Log("[HeaderManager] ✅ InputSystemUIInputModule déjà présent");
            }
            
            // Vérifier que l'EventSystem est bien actif
            Debug.Log($"[HeaderManager] EventSystem status - enabled: {eventSystem.enabled}, gameObject.activeInHierarchy: {eventSystem.gameObject.activeInHierarchy}");
        }
        else
        {
            Debug.LogError("[HeaderManager] ❌ EventSystem est null après création !");
        }
    }

    /// <summary>
    /// Détruit le header actuel
    /// </summary>
    public void DestroyHeader()
    {
        if (headerPanel != null)
        {
            Destroy(headerPanel);
            headerPanel = null;
        }
    }
}

/// <summary>
/// Composant UI pour un élément du header
/// </summary>
public class HeaderElementUI : MonoBehaviour
{
    private DefaultHeaderElement elementData;
    private HeaderManager headerManager;
    private RectTransform rectTransform;
    private Image image;
    private Button button;

    public void Initialize(DefaultHeaderElement data, HeaderManager manager)
    {
        elementData = data;
        headerManager = manager;
        rectTransform = GetComponent<RectTransform>();
        image = GetComponent<Image>();

        if (data.clickable)
        {
            // S'assurer que l'image peut recevoir les raycasts
            if (image != null)
            {
                image.raycastTarget = true;
            }

            // Ajouter un Button
            button = gameObject.AddComponent<Button>();
            button.transition = Selectable.Transition.ColorTint;
            button.targetGraphic = image;
            button.interactable = true;

            ColorBlock colors = button.colors;
            colors.normalColor = Color.white;
            colors.highlightedColor = new Color(0.9f, 0.9f, 0.9f, 1f);
            colors.pressedColor = new Color(0.7f, 0.7f, 0.7f, 1f);
            button.colors = colors;

            button.onClick.AddListener(OnClick);
            Debug.Log($"[HeaderElementUI] Button créé pour action: {data.targetAction}");

            // Ajouter aussi un EventTrigger comme fallback
            UnityEngine.EventSystems.EventTrigger eventTrigger = gameObject.GetComponent<UnityEngine.EventSystems.EventTrigger>();
            if (eventTrigger == null)
            {
                eventTrigger = gameObject.AddComponent<UnityEngine.EventSystems.EventTrigger>();
            }

            // Ajouter un listener pour PointerClick
            UnityEngine.EventSystems.EventTrigger.Entry clickEntry = new UnityEngine.EventSystems.EventTrigger.Entry();
            clickEntry.eventID = UnityEngine.EventSystems.EventTriggerType.PointerClick;
            clickEntry.callback.AddListener((eventData) => {
                Debug.Log($"[HeaderElementUI] EventTrigger PointerClick détecté pour action: {data.targetAction}");
                OnClick();
            });
            eventTrigger.triggers.Add(clickEntry);

            Debug.Log($"[HeaderElementUI] EventTrigger ajouté comme fallback pour action: {data.targetAction}");
        }
    }

    void OnClick()
    {
        Debug.Log($"[HeaderElementUI] OnClick appelé - action: {elementData?.targetAction}");
        if (headerManager != null && elementData != null)
        {
            headerManager.OnHeaderElementClick(elementData.targetAction);
        }
        else
        {
            Debug.LogError($"[HeaderElementUI] headerManager ou elementData est null - headerManager: {headerManager != null}, elementData: {elementData != null}");
        }
    }

    public void SetSprite(Sprite sprite)
    {
        if (image != null)
        {
            image.sprite = sprite;
        }
    }
}

