using UnityEngine;

/// <summary>
/// Reçoit les clics depuis JavaScript (WebGL) et les transmet aux scripts appropriés
/// </summary>
public class WebGLClickReceiver : MonoBehaviour
{
    // Mode debug : activer uniquement pour diagnostiquer les problèmes
    private static bool enableDebugLogs = true; // TEMPORAIRE pour debug dialogues
    
    private static WebGLClickReceiver instance;
    private static bool hasClickThisFrame = false;
    private static Vector2 lastClickPosition = Vector2.zero;
    
    // Variables pour le drag
    private static bool isDragging = false;
    private static Vector2 dragStartPosition = Vector2.zero;
    private static Vector2 dragCurrentPosition = Vector2.zero;
    
    // Variables pour le drag UI (Scrollbars, Sliders, etc.)
    private GameObject currentUIDragObject;
    private UnityEngine.EventSystems.PointerEventData currentPointerData;
    
    void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
            if (enableDebugLogs)
            {
                Debug.Log("[WebGLClickReceiver] ✅ Initialisé");
            }
        }
        else
        {
            Destroy(gameObject);
        }
    }
    
    void LateUpdate()
    {
        // Réinitialiser le flag à la fin de chaque frame
        hasClickThisFrame = false;
    }
    
    /// <summary>
    /// Appelé depuis JavaScript quand un clic est détecté
    /// Format du message: "x,y" (ex: "123.5,456.7")
    /// </summary>
    public void OnWebGLClick(string positionData)
    {
        try
        {
            string[] parts = positionData.Split(',');
            if (parts.Length == 2)
            {
                float x = float.Parse(parts[0], System.Globalization.CultureInfo.InvariantCulture);
                float y = float.Parse(parts[1], System.Globalization.CultureInfo.InvariantCulture);
                
                // Inversion Y retirée (causait des problèmes de scroll et de sélection)
                // y = Screen.height - y;
                
                lastClickPosition = new Vector2(x, y);
                hasClickThisFrame = true;
                
                if (enableDebugLogs)
                {
                    Debug.Log($"[WebGLClickReceiver] Clic: ({x:F0}, {y:F0})");
                }
                
                // Transmettre aux différents managers selon la scène active
                TransmitClickToManagers(lastClickPosition);
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"[WebGLClickReceiver] Erreur parsing position: {ex.Message}");
        }
    }
    
    void TransmitClickToManagers(Vector2 clickPosition)
    {
        // ANTI DOUBLE-CLIC : si un panneau de feedback vient JUSTE d'être fermé par un clic UI natif,
        // ce même clic peut être envoyé ensuite ici par le JS WebGL. On l'ignore pour éviter qu'il
        // ferme le panneau ET déclenche une zone de tir en dessous.
        if (GameManager.ignoreNextWebGLClickAfterFeedback)
        {
            if (enableDebugLogs)
            {
                Debug.Log("[WebGLClickReceiver] Clic WebGL ignoré juste après fermeture du feedback (anti clic traversant)");
            }
            GameManager.ignoreNextWebGLClickAfterFeedback = false;
            return;
        }

        // VÉRIFICATION PRÉCOCE : Si le panneau de feedback est actif dans les scènes shooting,
        // on doit bloquer le clic AVANT de le transmettre au GameManager (sauf si un vrai élément UI est cliqué)
        GameManager gameManager = FindFirstObjectByType<GameManager>();
        bool feedbackPanelActive = gameManager != null && gameManager.enabled && gameManager.IsFeedbackPanelActive();
        
        // D'abord, vérifier si le clic est sur un élément UI (bouton, input, etc.)
        // Cela permet aux éléments UI de fonctionner même si WebGLClickReceiver intercepte les clics
        UnityEngine.EventSystems.EventSystem eventSystem = UnityEngine.EventSystems.EventSystem.current;
        
        if (eventSystem != null)
        {
            UnityEngine.EventSystems.PointerEventData pointerData = new UnityEngine.EventSystems.PointerEventData(eventSystem);
            pointerData.position = clickPosition;
            pointerData.button = UnityEngine.EventSystems.PointerEventData.InputButton.Left;
            
            var results = new System.Collections.Generic.List<UnityEngine.EventSystems.RaycastResult>();
            eventSystem.RaycastAll(pointerData, results);
            
            // Si on a touché un élément UI, forcer le déclenchement des événements
            if (results.Count > 0)
            {
                if (enableDebugLogs)
                {
                    Debug.Log($"[WebGLClickReceiver] {results.Count} éléments UI détectés au point de clic");
                    foreach (var result in results)
                    {
                        Debug.Log($"[WebGLClickReceiver]   - {result.gameObject.name} (layer: {result.gameObject.layer})");
                    }
                }
                
                // PROTECTION IMPORTANTE : Vérifier si on clique DIRECTEMENT sur un DarkBackground (panneau modal)
                // On bloque SEULEMENT si le DarkBackground est le PREMIER élément (le plus en avant)
                // Si un autre élément UI est devant (ex: bouton d'onglet), on laisse passer
                if (results.Count > 0 && results[0].gameObject.name == "DarkBackground")
                {
                    if (enableDebugLogs)
                    {
                        Debug.Log("[WebGLClickReceiver] ⛔ Clic DIRECT sur DarkBackground - Blocage pour empêcher la traversée");
                    }
                    // Ne rien faire, juste bloquer le clic
                    return;
                }
                
                // Continuer la vérification normale des éléments UI (boutons, champs texte, etc.)
                foreach (var result in results)
                {
                    
                    // Vérifier aussi si on est dans la hiérarchie d'un LoginPopup
                    Transform parent = result.gameObject.transform;
                    while (parent != null)
                    {
                        if (parent.name.Contains("LoginPopup"))
                        {
                            if (enableDebugLogs)
                            {
                                Debug.Log($"[WebGLClickReceiver] ⛔ LoginPopup détecté - Traitement du clic sur le popup uniquement");
                            }
                            // Si c'est un clic sur le popup lui-même, on le laisse passer
                            // Mais on empêche que ça touche ce qui est en dessous
                            // On va traiter les boutons/inputs du popup dans la boucle suivante
                            break;
                        }
                        parent = parent.parent;
                    }
                }
                
                foreach (var result in results)
                {
                    GameObject targetObject = result.gameObject;
                    // Vérifier si c'est un bouton ou un input field
                    UnityEngine.UI.Button button = targetObject.GetComponent<UnityEngine.UI.Button>();
                    if (button == null)
                    {
                        button = targetObject.GetComponentInParent<UnityEngine.UI.Button>();
                    }
                    
                    TMPro.TMP_InputField inputField = targetObject.GetComponent<TMPro.TMP_InputField>();
                    if (inputField == null)
                    {
                        inputField = targetObject.GetComponentInParent<TMPro.TMP_InputField>();
                    }
                    
                    if (button != null || inputField != null)
                    {
                        if (enableDebugLogs)
                        {
                            Debug.Log($"[WebGLClickReceiver] Clic UI: {targetObject.name}");
                        }
                        
                        // Forcer le déclenchement des événements UI
                        if (button != null)
                        {
                            // Déclencher PointerDown puis PointerClick
                            UnityEngine.EventSystems.ExecuteEvents.Execute(button.gameObject, pointerData, UnityEngine.EventSystems.ExecuteEvents.pointerDownHandler);
                            UnityEngine.EventSystems.ExecuteEvents.Execute(button.gameObject, pointerData, UnityEngine.EventSystems.ExecuteEvents.pointerClickHandler);
                            UnityEngine.EventSystems.ExecuteEvents.Execute(button.gameObject, pointerData, UnityEngine.EventSystems.ExecuteEvents.pointerUpHandler);
                        }
                        
                        // Vérifier aussi s'il y a un EventTrigger sur l'objet
                        UnityEngine.EventSystems.EventTrigger eventTrigger = targetObject.GetComponent<UnityEngine.EventSystems.EventTrigger>();
                        if (eventTrigger == null)
                        {
                            eventTrigger = targetObject.GetComponentInParent<UnityEngine.EventSystems.EventTrigger>();
                        }
                        
                        if (eventTrigger != null)
                        {
                            // Déclencher les événements de l'EventTrigger
                            UnityEngine.EventSystems.ExecuteEvents.Execute(eventTrigger.gameObject, pointerData, UnityEngine.EventSystems.ExecuteEvents.pointerClickHandler);
                        }
                        
                        // Ne pas transmettre aux managers, les événements UI ont été déclenchés
                        return;
                    }
                }
            }
        }
        
        // PROTECTION CRITIQUE : Si le panneau de feedback est actif dans les scènes shooting
        // et qu'AUCUN élément UI n'a été cliqué (bouton, input, etc.), on bloque le clic.
        // Cela empêche les clics de passer à travers vers les zones de tir en dessous.
        if (feedbackPanelActive)
        {
            if (enableDebugLogs)
            {
                Debug.Log("[WebGLClickReceiver] ⛔ Panneau de feedback actif - clic hors UI bloqué (zones de tir protégées)");
            }
            return;
        }
        
        // PRIORITÉ 1 : DialoguePlayer (dialogues) - Doit être vérifié EN PREMIER car les dialogues sont au-dessus de tout
        DialoguePlayer dialoguePlayer = FindFirstObjectByType<DialoguePlayer>();
        if (enableDebugLogs)
        {
            Debug.Log($"[WebGLClickReceiver] DialoguePlayer trouvé: {dialoguePlayer != null}, isPlaying: {dialoguePlayer?.IsPlayingDialogue() ?? false}");
        }
        
        if (dialoguePlayer != null && dialoguePlayer.IsPlayingDialogue())
        {
            if (enableDebugLogs)
            {
                Debug.Log("[WebGLClickReceiver] Clic → DialoguePlayer");
            }
            dialoguePlayer.OnWebGLClick();
            return;
        }
        
        // PRIORITÉ 1B : SubtitleManager (dialogues avec vidéo HTML5)
        SubtitleManager subtitleManager = FindFirstObjectByType<SubtitleManager>();
        if (enableDebugLogs)
        {
            Debug.Log($"[WebGLClickReceiver] SubtitleManager trouvé: {subtitleManager != null}, isPlaying: {subtitleManager?.IsPlayingDialogue() ?? false}");
        }
        
        if (subtitleManager != null && subtitleManager.IsPlayingDialogue())
        {
            if (enableDebugLogs)
            {
                Debug.Log("[WebGLClickReceiver] Clic → SubtitleManager");
            }
            subtitleManager.OnWebGLClick();
            return;
        }
        
        // PRIORITÉ 2 : MapFullscreenVideo (vidéos plein écran)
        MapFullscreenVideo videoPlayer = FindFirstObjectByType<MapFullscreenVideo>();
        if (videoPlayer != null)
        {
            videoPlayer.OnWebGLClick();
            return;
        }
        
        // PRIORITÉ 3 : CalculatorGameManager (jeux de calculatrice)
        CalculatorGameManager calculatorManager = FindFirstObjectByType<CalculatorGameManager>();
        if (calculatorManager != null && calculatorManager.enabled)
        {
            if (enableDebugLogs)
            {
                Debug.Log("[WebGLClickReceiver] Clic → CalculatorGameManager");
            }
            calculatorManager.OnWebGLClick(clickPosition);
            return;
        }
        
        // PRIORITÉ 4 : GameManager (jeux shooting)
        // Réutiliser la variable gameManager déjà définie au début de la fonction
        if (gameManager != null && gameManager.enabled)
        {
            // IMPORTANT : Si le panneau de feedback est actif, ne pas transmettre le clic
            // Le clic sera géré par le système UI (bouton du panneau ou de l'overlay)
            if (gameManager.IsFeedbackPanelActive())
            {
                if (enableDebugLogs)
                {
                    Debug.Log("[WebGLClickReceiver] Panneau de feedback actif - clic non transmis au GameManager");
                }
                return;
            }
            
            // Vérifier si le GameManager a des zones de tir actives (jeu shooting en cours)
            gameManager.OnWebGLClick(clickPosition);
            return;
        }
        
        // PRIORITÉ 5 : MainSceneManager (menu principal)
        MainSceneManager mainSceneManager = FindFirstObjectByType<MainSceneManager>();
        if (mainSceneManager != null)
        {
            mainSceneManager.OnWebGLClick(clickPosition);
            return;
        }
        
        // PRIORITÉ 6 : MapManager (scène Map avec zones cliquables)
        MapManager mapManager = FindFirstObjectByType<MapManager>();
        if (mapManager != null)
        {
            mapManager.OnWebGLClick(clickPosition);
            return;
        }
        
        if (enableDebugLogs)
        {
            Debug.Log("[WebGLClickReceiver] Aucun manager trouvé pour gérer le clic");
        }
    }
    
    /// <summary>
    /// Permet aux scripts de vérifier si un clic WebGL a eu lieu cette frame
    /// </summary>
    public static bool WasClickedThisFrame()
    {
        return hasClickThisFrame;
    }
    
    /// <summary>
    /// Retourne la position du dernier clic WebGL
    /// </summary>
    public static Vector2 GetLastClickPosition()
    {
        return lastClickPosition;
    }
    
    /// <summary>
    /// Appelé depuis JavaScript quand un mousedown est détecté
    /// </summary>
    public void OnWebGLMouseDown(string positionData)
    {
        try
        {
            string[] parts = positionData.Split(',');
            if (parts.Length == 2)
            {
                float x = float.Parse(parts[0], System.Globalization.CultureInfo.InvariantCulture);
                float y = float.Parse(parts[1], System.Globalization.CultureInfo.InvariantCulture);
                
                // Inversion Y retirée
                // y = Screen.height - y;
                
                isDragging = true;
                dragStartPosition = new Vector2(x, y);
                dragCurrentPosition = dragStartPosition;
                
                if (enableDebugLogs)
                {
                    Debug.Log($"[WebGLClickReceiver] MouseDown: ({x:F0}, {y:F0})");
                }
                
                // Démarrer la simulation de drag UI
                StartUIDrag(dragStartPosition);
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"[WebGLClickReceiver] Erreur parsing mousedown: {ex.Message}");
        }
    }
    
    private void StartUIDrag(Vector2 position)
    {
        UnityEngine.EventSystems.EventSystem eventSystem = UnityEngine.EventSystems.EventSystem.current;
        if (eventSystem == null) return;

        currentPointerData = new UnityEngine.EventSystems.PointerEventData(eventSystem);
        currentPointerData.position = position;
        currentPointerData.button = UnityEngine.EventSystems.PointerEventData.InputButton.Left;
        currentPointerData.pressPosition = position;

        var results = new System.Collections.Generic.List<UnityEngine.EventSystems.RaycastResult>();
        eventSystem.RaycastAll(currentPointerData, results);

        if (results.Count > 0)
        {
            foreach(var result in results) 
            {
                GameObject go = result.gameObject;
                
                // Chercher un gestionnaire de drag ou de pointer down
                var dragHandler = UnityEngine.EventSystems.ExecuteEvents.GetEventHandler<UnityEngine.EventSystems.IDragHandler>(go);
                var pointerDownHandler = UnityEngine.EventSystems.ExecuteEvents.GetEventHandler<UnityEngine.EventSystems.IPointerDownHandler>(go);

                // Si on trouve un élément interactif
                if (dragHandler != null || pointerDownHandler != null)
                {
                    // On garde la référence sur l'objet qui gère l'événement
                    currentUIDragObject = dragHandler ?? pointerDownHandler;
                    
                    if (enableDebugLogs) Debug.Log($"[WebGLClickReceiver] 🖱️ UI Interaction Start: {currentUIDragObject.name}");
                    
                    // 1. Pointer Down
                    UnityEngine.EventSystems.ExecuteEvents.Execute(currentUIDragObject, currentPointerData, UnityEngine.EventSystems.ExecuteEvents.pointerDownHandler);
                    
                    // 2. Begin Drag (si c'est un objet draggable comme Scrollbar)
                    if (dragHandler != null)
                    {
                        UnityEngine.EventSystems.ExecuteEvents.Execute(dragHandler, currentPointerData, UnityEngine.EventSystems.ExecuteEvents.beginDragHandler);
                        currentPointerData.pointerDrag = dragHandler;
                    }
                    
                    currentPointerData.pointerPress = currentUIDragObject;
                    break; // On a trouvé notre cible UI, on arrête
                }
            }
        }
    }
    
    /// <summary>
    /// Appelé depuis JavaScript quand un mousemove est détecté pendant un drag
    /// </summary>
    public void OnWebGLMouseMove(string positionData)
    {
        if (!isDragging) return;
        
        try
        {
            string[] parts = positionData.Split(',');
            if (parts.Length == 2)
            {
                float x = float.Parse(parts[0], System.Globalization.CultureInfo.InvariantCulture);
                float y = float.Parse(parts[1], System.Globalization.CultureInfo.InvariantCulture);
                
                // Inversion Y retirée
                // y = Screen.height - y;
                
                dragCurrentPosition = new Vector2(x, y);
                
                // Mettre à jour le drag UI
                if (currentUIDragObject != null && currentPointerData != null)
                {
                    currentPointerData.position = dragCurrentPosition;
                    
                    if (currentPointerData.pointerDrag != null)
                    {
                        UnityEngine.EventSystems.ExecuteEvents.Execute(currentPointerData.pointerDrag, currentPointerData, UnityEngine.EventSystems.ExecuteEvents.dragHandler);
                    }
                }
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"[WebGLClickReceiver] Erreur parsing mousemove: {ex.Message}");
        }
    }
    
    /// <summary>
    /// Appelé depuis JavaScript quand un mouseup est détecté
    /// </summary>
    public void OnWebGLMouseUp(string positionData)
    {
        // Terminer le drag UI même si le parsing échoue (sécurité)
        if (currentUIDragObject != null && currentPointerData != null)
        {
            // Essayer de parser la position finale
            try
            {
                string[] parts = positionData.Split(',');
                if (parts.Length == 2)
                {
                    float x = float.Parse(parts[0], System.Globalization.CultureInfo.InvariantCulture);
                    float y = float.Parse(parts[1], System.Globalization.CultureInfo.InvariantCulture);
                    
                    // Inversion Y retirée
                    // y = Screen.height - y;
                    
                    currentPointerData.position = new Vector2(x, y);
                }
            }
            catch {} // On garde la dernière position connue en cas d'erreur

            if (enableDebugLogs) Debug.Log($"[WebGLClickReceiver] 🖱️ UI Interaction End: {currentUIDragObject.name}");

            // 1. End Drag
            if (currentPointerData.pointerDrag != null)
            {
                UnityEngine.EventSystems.ExecuteEvents.Execute(currentPointerData.pointerDrag, currentPointerData, UnityEngine.EventSystems.ExecuteEvents.endDragHandler);
            }
            
            // 2. Pointer Up
            UnityEngine.EventSystems.ExecuteEvents.Execute(currentUIDragObject, currentPointerData, UnityEngine.EventSystems.ExecuteEvents.pointerUpHandler);
            
            // 3. Pointer Click (optionnel, géré normalement par OnWebGLClick, mais certains éléments comme Toggle ont besoin du flux complet)
            // On ne l'appelle pas ici pour éviter les doubles clics avec OnWebGLClick
            
            currentUIDragObject = null;
            currentPointerData = null;
        }

        if (!isDragging) return;
        
        try
        {
            string[] parts = positionData.Split(',');
            if (parts.Length == 2)
            {
                float x = float.Parse(parts[0], System.Globalization.CultureInfo.InvariantCulture);
                float y = float.Parse(parts[1], System.Globalization.CultureInfo.InvariantCulture);
                
                // Inversion Y retirée
                // y = Screen.height - y;
                
                dragCurrentPosition = new Vector2(x, y);
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"[WebGLClickReceiver] Erreur parsing mouseup: {ex.Message}");
        }
        
        isDragging = false;
    }
    
    /// <summary>
    /// Vérifie si un drag est en cours
    /// </summary>
    public static bool IsDragging()
    {
        return isDragging;
    }
    
    /// <summary>
    /// Retourne la position de départ du drag
    /// </summary>
    public static Vector2 GetDragStartPosition()
    {
        return dragStartPosition;
    }
    
    /// <summary>
    /// Retourne la position actuelle du drag
    /// </summary>
    public static Vector2 GetDragCurrentPosition()
    {
        return dragCurrentPosition;
    }
    
    // MÉTHODE SUPPRIMÉE : IsModalPanelOpen() causait une NullReferenceException
    // La protection des panneaux modaux est gérée via le système UI normal (GraphicRaycaster)
    
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void CreateReceiver()
    {
        // Créer automatiquement le receiver au démarrage
        GameObject receiverObj = new GameObject("WebGLClickReceiver");
        receiverObj.AddComponent<WebGLClickReceiver>();
        DontDestroyOnLoad(receiverObj);
        
        if (enableDebugLogs)
        {
            Debug.Log("[WebGLClickReceiver] Créé automatiquement");
        }
    }
}

