using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.Networking;
using UnityEngine.InputSystem;
using System.Runtime.InteropServices;

/// <summary>
/// Gère l'affichage du viseur personnalisé avec deux états visuels :
/// - Pleine taille et opaque sur les zones cibles
/// - Taille réduite et semi-transparent ailleurs
/// Compatible avec le nouveau Input System de Unity
/// </summary>
public class CrosshairManager : MonoBehaviour
{
    // ========================================
    // WEBGL CURSOR PLUGIN
    // ========================================
#if UNITY_WEBGL && !UNITY_EDITOR
    [DllImport("__Internal")]
    private static extern void HideCursor();
    
    [DllImport("__Internal")]
    private static extern void ShowCursor();
#endif
    [Header("Configuration du Viseur")]
    public float crosshairSize = 50f; // Taille du viseur en pixels
    public float minSize = 0.5f;
    public float maxSize = 3f;
    
    [Header("Configuration États Visuels")]
    [Tooltip("Taille du viseur quand on survole une zone cible (multiplier de crosshairSize)")]
    public float onTargetSizeMultiplier = 1f; // Taille normale sur zone
    [Tooltip("Taille du viseur quand on ne survole pas de zone (multiplier de crosshairSize)")]
    public float offTargetSizeMultiplier = 0.5f; // Moitié de la taille ailleurs
    [Tooltip("Opacité du viseur sur une zone cible")]
    public float onTargetAlpha = 1f; // Complètement opaque sur zone
    [Tooltip("Opacité du viseur hors zone cible")]
    public float offTargetAlpha = 0.5f; // Semi-transparent ailleurs
    
    [Header("Nouveau comportement")]
    [Tooltip("Si true, le viseur est toujours visible (deux états). Si false, ancien comportement (visible/invisible)")]
    public bool alwaysShowCrosshair = true;
    
    [Header("References")]
    public GameManager gameManagerReference; // Assignez manuellement si FindObjectOfType échoue
    
    [Header("Transition")]
    public float transitionSpeed = 10f; // Vitesse d'apparition/disparition du viseur
    public float sizeTransitionSpeed = 15f; // Vitesse de changement de taille
    public bool smoothTransition = true; // Transition smooth ou instantanée
    
    [Header("Curseur Système")]
    public bool hideSystemCursorDuringGame = true; // Masquer le curseur système pendant le jeu
    public bool showSystemCursorDuringFeedback = true; // Montrer le curseur système pendant feedback
    
    [Header("Debug")]
    public bool showDebugInfo = false;

    // Références privées
    private GameObject crosshairInstance;
    private Image crosshairImage;
    private RectTransform crosshairRect;
    private Canvas parentCanvas;
    private Camera mainCamera;
    private CanvasGroup crosshairCanvasGroup;
    private Vector2 originalSize;
    private Coroutine introCoroutine;
    private bool introAnimating = false;
    
    // État du viseur
    private bool isOverTargetZone = false;
    private bool crosshairShouldBeVisible = false;
    private float targetAlpha = 0f;
    private float targetSizeMultiplier = 1f; // NOUVEAU : multiplier de taille cible
    private float currentSizeMultiplier = 1f; // NOUVEAU : multiplier de taille actuel
    private bool feedbackPanelActive = false;
    
    // Références Input System
    private Mouse mouse;
    private Touchscreen touchscreen;
    
    // Référence au GameManager pour accéder aux zones
    private GameManager gameManager;
    
    // Listes pour tracker les ressources créées dynamiquement (nettoyage WebGL)
    private readonly System.Collections.Generic.List<Texture2D> dynamicTextures = new System.Collections.Generic.List<Texture2D>();
    private readonly System.Collections.Generic.List<Sprite> dynamicSprites = new System.Collections.Generic.List<Sprite>();
    
    // ========================================
    // MÉTHODES HELPER POUR CURSEUR (WebGL compatible)
    // ========================================
    
    /// <summary>
    /// Masque le curseur système (compatible WebGL)
    /// </summary>
    private void HideSystemCursor()
    {
#if UNITY_WEBGL && !UNITY_EDITOR
        HideCursor(); // Appel JavaScript
        Debug.Log("[CrosshairManager] 🌐 Curseur masqué via JavaScript (WebGL)");
#else
        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.Confined;
        Debug.Log("[CrosshairManager] Curseur système masqué - crosshair actif");
#endif
    }
    
    /// <summary>
    /// Affiche le curseur système (compatible WebGL)
    /// </summary>
    private void ShowSystemCursor()
    {
#if UNITY_WEBGL && !UNITY_EDITOR
        ShowCursor(); // Appel JavaScript
        Debug.Log("[CrosshairManager] 🌐 Curseur affiché via JavaScript (WebGL)");
#else
        Cursor.visible = true;
        Cursor.lockState = CursorLockMode.None;
        Debug.Log("[CrosshairManager] Curseur système affiché");
#endif
    }
    
    void Start()
    {
        // Récupérer les références
        mainCamera = Camera.main;
        
        // Priorité à la référence manuelle, sinon essayer FindObjectOfType
        if (gameManagerReference != null)
        {
            gameManager = gameManagerReference;
        }
        else
        {
            gameManager = FindFirstObjectByType<GameManager>();
        }
        
        if (mainCamera == null)
        {
            Debug.LogError("CrosshairManager: Aucune caméra principale trouvée !");
            return;
        }
        
        if (gameManager == null)
        {
            // Vérifier si on est dans un jeu de calculatrice (qui n'a pas besoin de CrosshairManager)
            var calculatorManager = FindFirstObjectByType<CalculatorGameManager>();
            if (calculatorManager != null)
            {
                Debug.Log("CrosshairManager: Scène de calculatrice détectée, désactivation du crosshair et restauration du curseur système");
                ShowSystemCursor();
                gameObject.SetActive(false); // Désactiver complètement ce script
                return;
            }
            
            Debug.LogError("CrosshairManager: GameManager introuvable ! Assignez 'gameManagerReference' manuellement dans l'Inspector.");
            return;
        }
        else
        {
            Debug.Log("CrosshairManager: GameManager trouvé avec succès");
        }
        
        // Initialiser les références Input System
        InitializeInputReferences();
        
        // Créer le viseur (masqué par défaut)
        CreateCrosshair();
        
        // Configuration initiale selon le mode
        if (alwaysShowCrosshair)
        {
            targetAlpha = offTargetAlpha;
            targetSizeMultiplier = offTargetSizeMultiplier;
            currentSizeMultiplier = offTargetSizeMultiplier;
            crosshairShouldBeVisible = true;
        }
        else
        {
            targetAlpha = 0f;
            targetSizeMultiplier = onTargetSizeMultiplier;
            currentSizeMultiplier = onTargetSizeMultiplier;
            crosshairShouldBeVisible = false;
        }
        
        // Cacher le curseur système
        HideSystemCursor();
    }
    
    /// <summary>
    /// Initialise les références pour le nouveau Input System
    /// </summary>
    void InitializeInputReferences()
    {
        mouse = Mouse.current;
        touchscreen = Touchscreen.current;
        
        // Logs d'initialisation supprimés pour réduire le bruit en WebGL
    }
    
    void Update()
    {
        if (crosshairInstance == null) 
        {
            // Log une seule fois si le crosshair est null
            if (Time.frameCount % 300 == 0)
            {
                Debug.LogWarning("[CrosshairManager] crosshairInstance est NULL !");
            }
            return;
        }
        
        if (crosshairRect == null)
        {
            if (Time.frameCount % 300 == 0)
            {
                Debug.LogWarning("[CrosshairManager] crosshairRect est NULL !");
            }
            return;
        }
        
        // Vérifier l'état du feedback panel
        UpdateFeedbackPanelState();
        
        // Mettre à jour la position du viseur
        UpdateCrosshairPosition();
        
        // Détecter si on survole une zone cible
        DetectTargetZoneHover();
        
        // Gérer l'affichage du viseur selon l'état
        UpdateCrosshairVisibility();
        
        // NOUVEAU : Gérer les transitions de taille
        UpdateCrosshairSize();
    }
    
    /// <summary>
    /// Récupère la position actuelle de l'input (souris ou tactile)
    /// </summary>
    Vector2 GetCurrentInputPosition()
    {
        // Priorité à la souris si disponible
        if (mouse != null)
        {
            return mouse.position.ReadValue();
        }
        
        // Sinon utiliser le tactile si disponible et pressé
        if (touchscreen != null && touchscreen.primaryTouch.press.isPressed)
        {
            return touchscreen.primaryTouch.position.ReadValue();
        }
        
        // Fallback : position du milieu de l'écran
        return new Vector2(Screen.width / 2f, Screen.height / 2f);
    }
    
    /// <summary>
    /// Crée le GameObject du viseur avec un Canvas dédié
    /// </summary>
    private void CreateCrosshair()
    {
        // Créer un Canvas dédié au crosshair
        GameObject crosshairCanvasObj = new GameObject("CrosshairCanvas");
        parentCanvas = crosshairCanvasObj.AddComponent<Canvas>();
        parentCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
        parentCanvas.sortingOrder = 1000;
        
        // CanvasScaler avec résolution de référence 1920x1080
        CanvasScaler scaler = crosshairCanvasObj.AddComponent<CanvasScaler>();
        scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
        scaler.referenceResolution = new Vector2(1920, 1080);
        scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
        scaler.matchWidthOrHeight = 0.5f;
        
        crosshairCanvasObj.AddComponent<GraphicRaycaster>();
        
        // Créer le GameObject du viseur
        crosshairInstance = new GameObject("Crosshair");
        crosshairInstance.transform.SetParent(crosshairCanvasObj.transform, false);
        
        // Ajouter CanvasGroup pour les transitions smooth
        crosshairCanvasGroup = crosshairInstance.AddComponent<CanvasGroup>();
        crosshairCanvasGroup.alpha = 0f;
        crosshairCanvasGroup.blocksRaycasts = false;
        
        // Ajouter le composant Image (DISABLED jusqu'à ce que le sprite soit prêt)
        crosshairImage = crosshairInstance.AddComponent<Image>();
        crosshairImage.raycastTarget = false;
        crosshairImage.preserveAspect = true;
        crosshairImage.color = Color.white;
        crosshairImage.enabled = false; // Restera disabled jusqu'au chargement du sprite
        
        // Configuration du RectTransform
        crosshairRect = crosshairInstance.GetComponent<RectTransform>();
        crosshairRect.sizeDelta = new Vector2(crosshairSize, crosshairSize);
        crosshairRect.anchorMin = new Vector2(0.5f, 0.5f);
        crosshairRect.anchorMax = new Vector2(0.5f, 0.5f);
        crosshairRect.pivot = new Vector2(0.5f, 0.5f); // Centre sur le curseur
        
        originalSize = crosshairRect.sizeDelta;
        crosshairRect.localScale = Vector3.one;
        
        Debug.Log("[CrosshairManager] Crosshair créé avec Canvas dédié");
    }
    
    /// <summary>
    /// Gestion de l'état du feedback panel
    /// </summary>
    void UpdateFeedbackPanelState()
    {
        if (gameManager == null) return;
        
        bool currentFeedbackState = gameManager.IsFeedbackPanelActive();
        
        // Si l'état du feedback a changé
        if (currentFeedbackState != feedbackPanelActive)
        {
            feedbackPanelActive = currentFeedbackState;
            
            if (feedbackPanelActive)
            {
                // Feedback affiché : montrer le curseur système
                OnFeedbackPanelShown();
            }
            else
            {
                // Feedback masqué : retour au mode jeu
                OnFeedbackPanelHidden();
            }
        }
        
        // IMPORTANT: Forcer le curseur visible à chaque frame si le feedback est actif
        // pour éviter qu'il disparaisse quand on bouge la souris
        if (feedbackPanelActive && showSystemCursorDuringFeedback)
        {
            ShowSystemCursor();
        }
    }
    
    /// <summary>
    /// Quand le feedback s'affiche
    /// </summary>
    void OnFeedbackPanelShown()
    {
        if (showSystemCursorDuringFeedback)
        {
            ShowSystemCursor();
        }
        
        // Masquer le viseur pendant le feedback
        if (crosshairInstance != null)
        {
            crosshairInstance.SetActive(false);
        }
    }
    
    /// <summary>
    /// Quand le feedback se cache
    /// </summary>
    void OnFeedbackPanelHidden()
    {
        // Cacher le curseur système - le crosshair reprend le contrôle
        HideSystemCursor();
        
        // Réactiver le crosshair
        if (crosshairInstance != null)
        {
            crosshairInstance.SetActive(true);
        }
    }
    
    /// <summary>
    /// Détecte si la position actuelle survole une zone cible
    /// </summary>
    void DetectTargetZoneHover()
    {
        Vector2 inputPosition = GetCurrentInputPosition();
        bool wasOverTargetZone = isOverTargetZone;
        isOverTargetZone = false;
        
        // Utiliser la méthode du GameManager pour détecter les zones
        if (gameManager != null)
        {
            isOverTargetZone = gameManager.IsPointOverTargetZone(inputPosition);
        }
        else
        {
            if (showDebugInfo)
            {
                Debug.LogError("CrosshairManager: GameManager reference manquante !");
            }
        }
        
        // Si l'état a changé
        if (isOverTargetZone != wasOverTargetZone)
        {
            OnTargetZoneHoverChanged(isOverTargetZone);
        }
        
        if (showDebugInfo)
        {
            // Log supprimé (trop verbeux)
        }
    }
    
    /// <summary>
    /// Appelé quand l'état de survol des zones cibles change
    /// </summary>
    void OnTargetZoneHoverChanged(bool overTargetZone)
    {
        if (alwaysShowCrosshair)
        {
            // NOUVEAU MODE : Toujours visible, mais changer d'état visuel
            crosshairShouldBeVisible = true; // Toujours visible
            
            if (overTargetZone)
            {
                // Sur zone : pleine taille et opaque
                targetAlpha = onTargetAlpha;
                targetSizeMultiplier = onTargetSizeMultiplier;
            }
            else
            {
                // Hors zone : taille réduite et semi-transparent
                targetAlpha = offTargetAlpha;
                targetSizeMultiplier = offTargetSizeMultiplier;
            }
        }
        else
        {
            // ANCIEN MODE : Visible/invisible selon la zone
            crosshairShouldBeVisible = overTargetZone;
            targetAlpha = crosshairShouldBeVisible ? onTargetAlpha : 0f;
            targetSizeMultiplier = onTargetSizeMultiplier; // Toujours pleine taille quand visible
        }
        
        // Cacher le curseur système - le crosshair est visible
        HideSystemCursor();
        
        if (showDebugInfo)
        {
            // Log supprimé (trop verbeux)
        }
    }
    
    /// <summary>
    /// Met à jour la visibilité du viseur avec transition smooth
    /// </summary>
    void UpdateCrosshairVisibility()
    {
        if (crosshairCanvasGroup == null || gameManager == null) return;
        if (introAnimating) return;
        
        // Ne pas afficher le viseur pendant le feedback
        if (feedbackPanelActive)
        {
            crosshairCanvasGroup.alpha = 0f;
            return;
        }
        
        if (smoothTransition)
        {
            // Transition smooth
            float currentAlpha = crosshairCanvasGroup.alpha;
            float newAlpha = Mathf.MoveTowards(currentAlpha, targetAlpha, transitionSpeed * Time.deltaTime);
            crosshairCanvasGroup.alpha = newAlpha;
        }
        else
        {
            // Transition instantanée
            crosshairCanvasGroup.alpha = targetAlpha;
        }
    }
    
    /// <summary>
    /// NOUVEAU : Met à jour la taille du viseur avec transition smooth
    /// </summary>
    void UpdateCrosshairSize()
    {
        if (crosshairRect == null || originalSize == Vector2.zero) return;
        
        // Ne pas changer la taille pendant le feedback
        if (feedbackPanelActive) return;
        
        if (smoothTransition)
        {
            // Transition smooth de la taille
            currentSizeMultiplier = Mathf.MoveTowards(currentSizeMultiplier, targetSizeMultiplier, sizeTransitionSpeed * Time.deltaTime);
        }
        else
        {
            // Transition instantanée
            currentSizeMultiplier = targetSizeMultiplier;
        }
        
        // Appliquer la nouvelle taille
        Vector2 newSize = originalSize * currentSizeMultiplier;
        crosshairRect.sizeDelta = newSize;
        
        if (showDebugInfo && Mathf.Abs(currentSizeMultiplier - targetSizeMultiplier) > 0.01f)
        {
            // Log supprimé (trop verbeux)
        }
    }
    
    /// <summary>
    /// Met à jour la position du viseur selon la position de l'input
    /// </summary>
    private void UpdateCrosshairPosition()
    {
        // Récupérer la position de l'input en coordonnées écran
        Vector2 screenPosition = GetCurrentInputPosition();
        
        // Utiliser la résolution de référence du CanvasScaler (1920x1080)
        CanvasScaler scaler = parentCanvas.GetComponent<CanvasScaler>();
        Vector2 referenceResolution;
        
        if (scaler != null && scaler.uiScaleMode == CanvasScaler.ScaleMode.ScaleWithScreenSize)
        {
            referenceResolution = scaler.referenceResolution;
        }
        else
        {
            // Fallback : utiliser la taille de l'écran
            referenceResolution = new Vector2(Screen.width, Screen.height);
        }
        
        // Convertir la position écran (0 à Screen.width/height) vers l'espace Canvas de référence
        // Le crosshair a des ancres au centre (0.5, 0.5), donc (0,0) = centre du Canvas
        float canvasX = (screenPosition.x / Screen.width - 0.5f) * referenceResolution.x;
        float canvasY = (screenPosition.y / Screen.height - 0.5f) * referenceResolution.y;
        
        crosshairRect.anchoredPosition = new Vector2(canvasX, canvasY);
    }
    
    /// <summary>
    /// Charge le sprite du viseur depuis une URL ou le cache
    /// </summary>
    /// <param name="url">URL du sprite du viseur</param>
    public void LoadCrosshairFromURL(string url)
    {
        if (crosshairImage == null)
        {
            Debug.LogError("CrosshairManager: Image du viseur non initialisée !");
            return;
        }
        
        if (string.IsNullOrEmpty(url))
        {
            Debug.LogError($"[CrosshairManager] ❌ URL vide passée à LoadCrosshairFromURL() !");
            CreateFallbackCrosshair();
            RevealWithIntro();
            return;
        }
        
        // 🚀 NOUVEAU : Vérifier d'abord le cache de GameDataManager
        if (GameDataManager.Instance != null)
        {
            Sprite cachedSprite = GameDataManager.Instance.GetCachedSprite("crosshair");
            if (cachedSprite != null)
            {
                Debug.Log($"[CrosshairManager] ⚡ Crosshair chargé instantanément depuis le cache !");
                ApplyCrosshairSprite(cachedSprite);
                return;
            }
            
            // Essayer aussi avec la texture
            Texture2D cachedTexture = GameDataManager.Instance.GetCachedTexture("crosshair");
            if (cachedTexture != null)
            {
                Debug.Log($"[CrosshairManager] ⚡ Crosshair créé instantanément depuis texture en cache !");
                Sprite sprite = Sprite.Create(cachedTexture, new Rect(0, 0, cachedTexture.width, cachedTexture.height), new Vector2(0.5f, 0.5f), 100f);
                ApplyCrosshairSprite(sprite);
                return;
            }
        }
        
        Debug.Log($"[CrosshairManager] ✅ Chargement crosshair depuis URL: '{url}'");
        StartCoroutine(DownloadCrosshairSprite(url));
    }
    
    /// <summary>
    /// Applique un sprite au crosshair et configure l'affichage
    /// </summary>
    private void ApplyCrosshairSprite(Sprite sprite)
    {
        if (sprite == null || crosshairImage == null) return;
        
        crosshairImage.sprite = sprite;
        
        float aspectRatio = (float)sprite.texture.width / sprite.texture.height;
        originalSize = new Vector2(crosshairSize * aspectRatio, crosshairSize);
        
        UpdateCrosshairSizeWithAspect();
        
        Debug.Log($"[CrosshairManager] ✅ Sprite appliqué");

        RevealWithIntro();
    }
    
    /// <summary>
    /// Coroutine pour télécharger le sprite du viseur
    /// </summary>
    private IEnumerator DownloadCrosshairSprite(string url)
    {
        Debug.Log($"[CrosshairManager] 📥 Téléchargement du viseur depuis {url}");
        Debug.Log($"[CrosshairManager] Platform: {Application.platform}");
        
        // CORRECTION MAC : Utiliser MacImageLoader au lieu de UnityWebRequest direct
        bool success = false;
        Texture2D texture = null;
        string error = null;
        
        yield return MacImageLoader.LoadTexture(url,
            (loadedTexture) => {
                success = true;
                texture = loadedTexture;
            },
            (errorMsg) => {
                success = false;
                error = errorMsg;
            }
        );
        
        if (success && texture != null)
        {
            Debug.Log($"[CrosshairManager] ✅ Texture reçue: {texture.width}x{texture.height}");
            
            try
            {
                Sprite crosshairSprite = Sprite.Create(
                    texture,
                    new Rect(0, 0, texture.width, texture.height),
                    new Vector2(0.5f, 0.5f),
                    100f
                );
                
                // Utiliser la nouvelle méthode centralisée
                ApplyCrosshairSprite(crosshairSprite);
            }
            catch (System.Exception e)
            {
                Debug.LogError($"[CrosshairManager] ❌ Erreur création sprite: {e.Message}");
                CreateFallbackCrosshair();
                RevealWithIntro();
            }
        }
        else
        {
            Debug.LogError($"[CrosshairManager] ❌ Échec téléchargement: {error}");
            Debug.LogError($"[CrosshairManager] URL: {url}");
            
            #if UNITY_WEBGL && !UNITY_EDITOR
            Debug.LogError("[CrosshairManager] 🌐 PROBLÈME WEBGL DÉTECTÉ");
            Debug.LogError("[CrosshairManager] Cause probable: CORS ou headers interdits");
            Debug.LogError("[CrosshairManager] Vérifiez que le serveur CloudFront envoie:");
            Debug.LogError("[CrosshairManager]   Access-Control-Allow-Origin: *");
            Debug.LogError("[CrosshairManager] Utilisez CrosshairDebugTester pour diagnostiquer");
            #elif UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
            Debug.LogError("[CrosshairManager] 🍎 PROBLÈME MAC - Création du fallback...");
            #endif
            
            Debug.LogWarning("[CrosshairManager] ⚠️ Création du crosshair de fallback (croix visible)");
            CreateFallbackCrosshair();
            RevealWithIntro();
        }
    }

    /// <summary>
    /// Effet d'apparition (fade in + scale 2x → 1x) sans flash blanc.
    /// On le déclenche dès que le sprite est prêt (download/cache/fallback).
    /// </summary>
    private void RevealWithIntro()
    {
        if (crosshairInstance == null || crosshairCanvasGroup == null || crosshairRect == null) return;
        if (feedbackPanelActive) return;

        // Si l'image n'est pas prête, ne rien faire
        if (crosshairImage == null || crosshairImage.sprite == null)
            return;

        if (introCoroutine != null)
            StopCoroutine(introCoroutine);

        introCoroutine = StartCoroutine(AnimateCrosshairIntro());
    }

    private IEnumerator AnimateCrosshairIntro()
    {
        introAnimating = true;

        crosshairCanvasGroup.alpha = 0f;
        crosshairRect.localScale = Vector3.one * 2f;
        
        // Activer l'image MAINTENANT (alpha = 0, donc invisible)
        if (crosshairImage != null)
            crosshairImage.enabled = true;

        float duration = 0.5f;
        float elapsed = 0f;

        while (elapsed < duration)
        {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / duration);

            // Fade vers l'alpha cible actuel (peut changer en fonction du hover)
            float desiredAlpha = targetAlpha;
            crosshairCanvasGroup.alpha = Mathf.Lerp(0f, desiredAlpha, t);

            // Scale down
            crosshairRect.localScale = Vector3.Lerp(Vector3.one * 2f, Vector3.one, t);

            yield return null;
        }

        crosshairCanvasGroup.alpha = targetAlpha;
        crosshairRect.localScale = Vector3.one;

        introAnimating = false;
        introCoroutine = null;
    }

    /// <summary>
    /// Met à jour la taille du crosshair en respectant les proportions
    /// </summary>
    private void UpdateCrosshairSizeWithAspect()
    {
        if (crosshairRect != null && originalSize != Vector2.zero)
        {
            float scale = crosshairSize / 50f; // 50f est la taille de référence
            Vector2 newSize = originalSize * scale * currentSizeMultiplier; // MODIFIÉ : inclure le multiplier actuel
            crosshairRect.sizeDelta = newSize;
            
            Debug.Log($"Crosshair redimensionné: {newSize} (échelle: {scale:F2}, multiplier: {currentSizeMultiplier:F2})");
        }
    }
    
    /// <summary>
    /// Crée un viseur de fallback simple - VISIBLE avec contour noir
    /// </summary>
    private void CreateFallbackCrosshair()
    {
        // Créer une texture simple pour le viseur
        Texture2D fallbackTexture = new Texture2D(64, 64);
        Color[] pixels = new Color[64 * 64];
        
        // Remplir avec transparence
        for (int i = 0; i < pixels.Length; i++)
        {
            pixels[i] = Color.clear;
        }
        
        // Dessiner une croix avec contour noir pour meilleure visibilité
        for (int x = 0; x < 64; x++)
        {
            for (int y = 0; y < 64; y++)
            {
                // Contour noir horizontal
                if (y >= 28 && y <= 36 && (x < 26 || x > 38))
                {
                    pixels[y * 64 + x] = new Color(0f, 0f, 0f, 1f); // Noir opaque
                }
                // Contour noir vertical
                if (x >= 28 && x <= 36 && (y < 26 || y > 38))
                {
                    pixels[y * 64 + x] = new Color(0f, 0f, 0f, 1f); // Noir opaque
                }
                
                // Ligne blanche horizontale (intérieur)
                if (y >= 30 && y <= 34 && (x < 28 || x > 36))
                {
                    pixels[y * 64 + x] = new Color(1f, 1f, 1f, 1f); // Blanc opaque
                }
                // Ligne blanche verticale (intérieur)
                if (x >= 30 && x <= 34 && (y < 28 || y > 36))
                {
                    pixels[y * 64 + x] = new Color(1f, 1f, 1f, 1f); // Blanc opaque
                }
                
                // Centre rouge vif
                if ((x >= 28 && x <= 36) && (y >= 28 && y <= 36))
                {
                    pixels[y * 64 + x] = new Color(1f, 0f, 0f, 1f); // Rouge opaque
                }
            }
        }
        
        fallbackTexture.SetPixels(pixels);
        fallbackTexture.Apply();
        dynamicTextures.Add(fallbackTexture);
        
        Sprite fallbackSprite = Sprite.Create(
            fallbackTexture,
            new Rect(0, 0, 64, 64),
            new Vector2(0.5f, 0.5f),
            100f
        );
        dynamicSprites.Add(fallbackSprite);
        
        crosshairImage.sprite = fallbackSprite;
        crosshairImage.color = Color.white;
        
        Debug.Log("CrosshairManager: Viseur de fallback créé");
    }
    
    // ========================================
    // MÉTHODES PUBLIQUES
    // ========================================
    
    /// <summary>
    /// Change la taille du viseur
    /// </summary>
    public void SetCrosshairSize(float newSize)
    {
        crosshairSize = Mathf.Clamp(newSize, minSize, maxSize);
        
        // Mettre à jour la taille en respectant les proportions
        UpdateCrosshairSizeWithAspect();
    }
    
    /// <summary>
    /// Change la couleur du viseur
    /// </summary>
    public void SetCrosshairColor(Color color)
    {
        if (crosshairImage != null)
        {
            crosshairImage.color = color;
        }
    }
    
    /// <summary>
    /// Active/désactive les transitions smooth
    /// </summary>
    public void SetSmoothTransition(bool smooth)
    {
        smoothTransition = smooth;
    }
    
    /// <summary>
    /// Change la vitesse de transition d'alpha
    /// </summary>
    public void SetTransitionSpeed(float speed)
    {
        transitionSpeed = speed;
    }
    
    /// <summary>
    /// NOUVEAU : Change la vitesse de transition de taille
    /// </summary>
    public void SetSizeTransitionSpeed(float speed)
    {
        sizeTransitionSpeed = speed;
    }
    
    /// <summary>
    /// NOUVEAU : Configure les multiplieurs de taille
    /// </summary>
    public void SetSizeMultipliers(float onTarget, float offTarget)
    {
        onTargetSizeMultiplier = onTarget;
        offTargetSizeMultiplier = offTarget;
        
        // Mettre à jour l'état actuel si nécessaire
        if (isOverTargetZone)
        {
            targetSizeMultiplier = onTargetSizeMultiplier;
        }
        else
        {
            targetSizeMultiplier = offTargetSizeMultiplier;
        }
        
        Debug.Log($"Multiplieurs de taille mis à jour: Sur zone={onTarget}, Hors zone={offTarget}");
    }
    
    /// <summary>
    /// NOUVEAU : Configure les valeurs d'alpha
    /// </summary>
    public void SetAlphaValues(float onTarget, float offTarget)
    {
        onTargetAlpha = onTarget;
        offTargetAlpha = offTarget;
        
        // Mettre à jour l'état actuel si nécessaire
        if (alwaysShowCrosshair)
        {
            if (isOverTargetZone)
            {
                targetAlpha = onTargetAlpha;
            }
            else
            {
                targetAlpha = offTargetAlpha;
            }
        }
        
        Debug.Log($"Valeurs alpha mises à jour: Sur zone={onTarget}, Hors zone={offTarget}");
    }
    
    /// <summary>
    /// NOUVEAU : Active/désactive le mode double état
    /// </summary>
    public void SetAlwaysShowCrosshair(bool alwaysShow)
    {
        bool wasAlwaysShow = alwaysShowCrosshair;
        alwaysShowCrosshair = alwaysShow;
        
        if (wasAlwaysShow != alwaysShow)
        {
            // Réappliquer l'état selon le nouveau mode
            OnTargetZoneHoverChanged(isOverTargetZone);
            
            Debug.Log($"Mode viseur changé: {(alwaysShow ? "Double état (toujours visible)" : "Conditionnel (visible/invisible)")}");
        }
    }
    
    /// <summary>
    /// Force l'affichage ou le masquage du viseur (pour debug)
    /// </summary>
    public void ForceVisibility(bool visible)
    {
        crosshairShouldBeVisible = visible;
        targetAlpha = visible ? onTargetAlpha : 0f;
        
        if (showDebugInfo)
        {
            Debug.Log($"Viseur forcé: {(visible ? "VISIBLE" : "MASQUÉ")}");
        }
    }
    
    /// <summary>
    /// Vérifie si le viseur est actuellement visible
    /// </summary>
    public bool IsVisible()
    {
        return crosshairCanvasGroup != null && crosshairCanvasGroup.alpha > 0f;
    }
    
    /// <summary>
    /// Vérifie si on survole actuellement une zone cible
    /// </summary>
    public bool IsOverTargetZone()
    {
        return isOverTargetZone;
    }
    
    /// <summary>
    /// Force l'état du curseur système
    /// </summary>
    public void SetSystemCursorVisible(bool visible)
    {
        if (visible)
        {
            ShowSystemCursor();
        }
        else
        {
            HideSystemCursor();
        }
    }
    
    /// <summary>
    /// Debug complet de l'état du curseur
    /// </summary>
    public void DebugCursorState()
    {
        Debug.Log("=== DEBUG CURSEUR ===");
        Debug.Log($"Mode: {(alwaysShowCrosshair ? "Double état" : "Conditionnel")}");
#if UNITY_WEBGL && !UNITY_EDITOR
        Debug.Log($"Curseur système: Géré via JavaScript (WebGL)");
#else
        Debug.Log($"Curseur système visible: {Cursor.visible}");
#endif
        Debug.Log($"Feedback panel actif: {feedbackPanelActive}");
        Debug.Log($"Viseur actif: {(crosshairImage != null ? crosshairImage.gameObject.activeInHierarchy : false)}");
        Debug.Log($"Viseur alpha: {(crosshairCanvasGroup != null ? crosshairCanvasGroup.alpha : -1f)} (cible: {targetAlpha})");
        Debug.Log($"Viseur taille multiplier: {currentSizeMultiplier:F2} (cible: {targetSizeMultiplier:F2})");
        Debug.Log($"Sur zone cible: {isOverTargetZone}");
        Debug.Log($"Multipliers: Sur zone={onTargetSizeMultiplier}, Hors zone={offTargetSizeMultiplier}");
        Debug.Log($"Alpha: Sur zone={onTargetAlpha}, Hors zone={offTargetAlpha}");
        Debug.Log("====================");
    }
    
    void OnDestroy()
    {
        // Restaurer le curseur système
        ShowSystemCursor();
        
        // Nettoyage des ressources dynamiques (important pour WebGL)
        CleanupDynamicResources();
    }
    
    /// <summary>
    /// Nettoie toutes les ressources créées dynamiquement (important pour WebGL)
    /// </summary>
    void CleanupDynamicResources()
    {
        foreach (var sprite in dynamicSprites)
        {
            if (sprite != null) Destroy(sprite);
        }
        dynamicSprites.Clear();
        
        foreach (var texture in dynamicTextures)
        {
            if (texture != null) Destroy(texture);
        }
        dynamicTextures.Clear();
        
        Debug.Log("[CrosshairManager] 🧹 Ressources dynamiques nettoyées");
    }
    
    void OnApplicationFocus(bool hasFocus)
    {
        // Restaurer le curseur système si on perd le focus
        if (!hasFocus)
        {
            ShowSystemCursor();
        }
    }

    /// <summary>
    /// Configure le viseur selon les paramètres JSON (compatible avec CrosshairConfig existant)
    /// </summary>
    public void ApplyCrosshairConfig(CrosshairConfig config)
    {
        if (config == null) 
        {
            Debug.LogWarning("Configuration crosshair nulle, utilisation des valeurs par défaut");
            return;
        }
        
        Debug.Log($"=== APPLICATION CONFIG CROSSHAIR ===");
        
        // 1. APPLIQUER LES PROPRIÉTÉS DE BASE (toujours présentes)
        minSize = config.minSize;
        maxSize = config.maxSize;
        SetCrosshairSize(config.defaultSize);
        
        // 2. UTILISER LA RÉFLEXION POUR LES NOUVELLES PROPRIÉTÉS
        System.Type configType = config.GetType();
        
        // Mode d'affichage
        bool useAlwaysShow = GetFieldValue<bool>(config, configType, "alwaysShowCrosshair", true);
        SetAlwaysShowCrosshair(useAlwaysShow);
        
        // Multipliers de taille
        float onTargetSize = GetFieldValue<float>(config, configType, "onTargetSizeMultiplier", 1.0f);
        float offTargetSize = GetFieldValue<float>(config, configType, "offTargetSizeMultiplier", 0.5f);
        SetSizeMultipliers(onTargetSize, offTargetSize);
        
        // Valeurs d'alpha
        float onTargetAlphaValue = GetFieldValue<float>(config, configType, "onTargetAlpha", 1.0f);
        float offTargetAlphaValue = GetFieldValue<float>(config, configType, "offTargetAlpha", 0.6f);
        SetAlphaValues(onTargetAlphaValue, offTargetAlphaValue);
        
        // Vitesses de transition
        float alphaSpeed = GetFieldValue<float>(config, configType, "alphaTransitionSpeed", 10f);
        float sizeSpeed = GetFieldValue<float>(config, configType, "sizeTransitionSpeed", 15f);
        SetTransitionSpeed(alphaSpeed);
        SetSizeTransitionSpeed(sizeSpeed);
        
        // Transitions smooth
        bool smoothTrans = GetFieldValue<bool>(config, configType, "smoothTransitions", true);
        SetSmoothTransition(smoothTrans);
        
        Debug.Log($"Configuration appliquée avec succès :");
        Debug.Log($"  Mode: {(alwaysShowCrosshair ? "Double état" : "Classique")}");
        Debug.Log($"  Taille: {crosshairSize}px (min: {minSize}, max: {maxSize})");
        Debug.Log($"  Multipliers: Sur zone x{onTargetSizeMultiplier:F1}, Hors zone x{offTargetSizeMultiplier:F1}");
        Debug.Log($"  Alpha: Sur zone {onTargetAlpha:F1}, Hors zone {offTargetAlpha:F1}");
        Debug.Log($"  Vitesses: Taille {sizeTransitionSpeed}, Alpha {transitionSpeed}");
        Debug.Log($"=== FIN APPLICATION CONFIG ===");
    }

    /// <summary>
    /// Récupère la valeur d'un champ avec fallback si il n'existe pas
    /// </summary>
    private T GetFieldValue<T>(object obj, System.Type objType, string fieldName, T defaultValue)
    {
        try
        {
            var field = objType.GetField(fieldName);
            if (field != null && field.FieldType == typeof(T))
            {
                T value = (T)field.GetValue(obj);
                Debug.Log($"Propriété {fieldName} trouvée: {value}");
                return value;
            }
            else
            {
                Debug.Log($"Propriété {fieldName} non trouvée, utilisation valeur par défaut: {defaultValue}");
                return defaultValue;
            }
        }
        catch (System.Exception e)
        {
            Debug.LogWarning($"Erreur lecture propriété {fieldName}: {e.Message}. Utilisation valeur par défaut: {defaultValue}");
            return defaultValue;
        }
    }
}