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

/// <summary>
/// Gère l'affichage d'un sprite de pistolet qui suit la souris avec un offset personnalisable
/// Intègre le système de contraintes de mouvement pour éviter que le pistolet sorte de l'écran
/// </summary>
public class GunSpriteManager : MonoBehaviour
{
    [Header("Configuration du Pistolet")]
    public Vector2 offsetFromCursor = new Vector2(-50f, -30f); // Offset par rapport au curseur (pixels)
    public float gunSize = 100f; // Taille du pistolet en pixels
    public bool flipGunHorizontally = false; // Retourner le pistolet horizontalement
    
    [Header("Rotation")]
    public bool enableRotation = false; // Activer la rotation vers la souris
    public float rotationOffset = 0f; // Offset de rotation en degrés
    public float rotationSpeed = 10f; // Vitesse de rotation (0 = instantané)
    
    [Header("Visibilité")]
    public bool alwaysVisible = true; // Toujours visible ou seulement sur les zones
    public float fadeSpeed = 5f; // Vitesse d'apparition/disparition
    public bool hideDuringFeedback = true; // Masquer pendant les panneaux de feedback
    
    [Header("Contraintes de Mouvement")]
    public bool enableBoundaryConstraints = false; // Activer les contraintes de mouvement
    public bool showBoundaryVisualization = false; // Afficher la zone de contraintes
    public Color boundaryColor = Color.yellow; // Couleur de la zone debug
    
    [Header("Debug")]
    public bool showDebugInfo = false;
    
    // Références privées
    private GameObject gunInstance;
    private Image gunImage;
    private RectTransform gunRect;
    private Canvas parentCanvas;
    private RectTransform parentCanvasRect;
    private Camera mainCamera;
    private CanvasGroup gunCanvasGroup;
    
    // État du pistolet
    // private bool isVisible = true;
    private float targetAlpha = 1f;
    
    // Contraintes de mouvement
    private Rect movementBounds;
    private GunBoundaryConfig boundaryConfig;
    
    // Références Input System
    private Mouse mouse;
    private Touchscreen touchscreen;
    
    // Référence au GameManager pour détecter les 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>();
    
    void Start()
    {
        // Récupérer les références
        mainCamera = Camera.main;
        gameManager = FindFirstObjectByType<GameManager>();
        
        if (mainCamera == null)
        {
            Debug.LogError("GunSpriteManager: Aucune caméra principale trouvée !");
            return;
        }
        
        // Vérifier si on est dans un jeu de calculatrice (qui n'a pas besoin de GunSpriteManager)
        var calculatorManager = FindFirstObjectByType<CalculatorGameManager>();
        if (calculatorManager != null)
        {
            Debug.Log("GunSpriteManager: Scène de calculatrice détectée, désactivation du pistolet et restauration du curseur système");
            Cursor.visible = true;
            Cursor.lockState = CursorLockMode.None;
            gameObject.SetActive(false); // Désactiver complètement ce script
            return;
        }
        
        if (gameManager == null && !alwaysVisible)
        {
            Debug.LogWarning("GunSpriteManager: GameManager introuvable ! Mode 'alwaysVisible' activé.");
            alwaysVisible = true;
        }
        
        // Initialiser les références Input System
        InitializeInputReferences();
        
        // Créer le sprite du pistolet
        CreateGunSprite();
    }
    
    /// <summary>
    /// Initialise les références pour le nouveau Input System
    /// </summary>
    void InitializeInputReferences()
    {
        mouse = Mouse.current;
        touchscreen = Touchscreen.current;
        
        if (showDebugInfo)
        {
            Debug.Log($"GunSpriteManager: Mouse détectée: {mouse != null}");
            Debug.Log($"GunSpriteManager: Touchscreen détecté: {touchscreen != null}");
        }
    }
    
    void Update()
    {
        if (gunInstance == null) return;
        
        // Mettre à jour la position du pistolet
        UpdateGunPosition();
        
        // Gérer la visibilité selon le mode
        UpdateGunVisibility();
        
        // Mettre à jour l'alpha
        UpdateGunAlpha();
        
        // Gérer la rotation si activée
        if (enableRotation)
        {
            UpdateGunRotation();
        }
    }
    
    /// <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);
    }

    bool TryConvertScreenPointToCanvasPosition(Vector2 screenPoint, out Vector2 canvasPosition)
    {
        canvasPosition = screenPoint;
        if (parentCanvas == null)
            return false;

        if (parentCanvasRect == null)
            parentCanvasRect = parentCanvas.GetComponent<RectTransform>();

        if (parentCanvasRect == null)
            return false;

        Camera canvasCamera = parentCanvas.renderMode == RenderMode.ScreenSpaceOverlay
            ? null
            : parentCanvas.worldCamera;

        Vector2 localPoint;
        bool result = RectTransformUtility.ScreenPointToLocalPointInRectangle(
            parentCanvasRect,
            screenPoint,
            canvasCamera,
            out localPoint
        );

        if (result)
        {
            // Convertir de coordonnées centrées vers coordonnées bas-gauche
            // (pour être cohérent avec anchorMin = anchorMax = Vector2.zero)
            Vector2 canvasSize = parentCanvasRect.rect.size;
            canvasPosition = localPoint + canvasSize * 0.5f;
        }
        else
        {
            canvasPosition = localPoint;
        }
        
        return result;
    }

    Vector2 GetCanvasReferenceSize()
    {
        if (parentCanvasRect != null)
        {
            return parentCanvasRect.rect.size;
        }

        return new Vector2(Screen.width, Screen.height);
    }
    
    /// <summary>
    /// Crée le GameObject du sprite de pistolet
    /// </summary>
    void CreateGunSprite()
    {
        // Trouver le Canvas principal
        parentCanvas = FindFirstObjectByType<Canvas>();
        if (parentCanvas == null)
        {
            Debug.LogError("GunSpriteManager: Aucun Canvas trouvé !");
            return;
        }
        parentCanvasRect = parentCanvas.GetComponent<RectTransform>();
        if (parentCanvasRect == null)
        {
            Debug.LogError("GunSpriteManager: RectTransform du Canvas introuvable !");
            return;
        }
        
        // Créer le GameObject du pistolet
        gunInstance = new GameObject("GunSprite");
        gunInstance.transform.SetParent(parentCanvas.transform, false);
        
        // Ajouter CanvasGroup pour les transitions
        gunCanvasGroup = gunInstance.AddComponent<CanvasGroup>();
        gunCanvasGroup.alpha = 1f; // VISIBLE par défaut
        gunCanvasGroup.blocksRaycasts = false; // Ne pas bloquer les clics
        
        // Initialiser targetAlpha pour qu'il soit visible
        targetAlpha = 1f;
        
        // Ajouter le composant Image
        gunImage = gunInstance.AddComponent<Image>();
        gunImage.raycastTarget = false; // Important : ne pas bloquer les raycast
        
        // Configuration du RectTransform
        gunRect = gunInstance.GetComponent<RectTransform>();
        gunRect.sizeDelta = new Vector2(gunSize, gunSize);
        gunRect.anchorMin = Vector2.zero;
        gunRect.anchorMax = Vector2.zero;
        gunRect.pivot = new Vector2(0.5f, 0.5f);
        
        // Mettre le pistolet dans un ordre de rendu approprié (DERRIÈRE le viseur)
        gunInstance.transform.SetSiblingIndex(0); // Premier enfant = arrière-plan
        
        // Couleur par défaut
        gunImage.color = Color.white;
        
        // Appliquer le flip horizontal si nécessaire
        if (flipGunHorizontally)
        {
            gunRect.localScale = new Vector3(-1, 1, 1);
        }
        
        Debug.Log("GunSpriteManager: Sprite de pistolet créé avec succès");
    }
    
    /// <summary>
    /// Met à jour la position du pistolet selon la position de l'input + offset + contraintes
    /// </summary>
    void UpdateGunPosition()
    {
        // Récupérer la position de l'input (écran -> coordonnées canvas)
        Vector2 inputPosition = GetCurrentInputPosition();
        Vector2 canvasInputPosition;
        if (!TryConvertScreenPointToCanvasPosition(inputPosition, out canvasInputPosition))
        {
            canvasInputPosition = inputPosition;
        }
        
        // NOUVEAU : Si on est dans la scène shooting avec ShootingGameLayout,
        // convertir les coordonnées pour être relatives à la zone de jeu
        ShootingGameLayout layout = ShootingGameLayout.Instance;
        if (layout == null)
        {
            layout = FindFirstObjectByType<ShootingGameLayout>();
        }
        
        // Appliquer l'offset dans l'espace canvas
        Vector2 gunPosition = canvasInputPosition + offsetFromCursor;
        
        // NOUVEAU : Si on est dans la scène shooting avec ShootingGameLayout,
        // les contraintes sont déjà calculées pour la zone de jeu dans UpdateMovementBounds()
        // On applique simplement les contraintes
        if (enableBoundaryConstraints)
        {
            gunPosition = ApplyBoundaryConstraints(gunPosition);
        }
        
        gunRect.anchoredPosition = gunPosition;
        
        if (showDebugInfo)
        {
            Debug.Log($"Gun - Input: {inputPosition}, Offset: {offsetFromCursor}, Final: {gunRect.anchoredPosition}");
        }
    }
    
    // <summary>
/// Applique les contraintes de mouvement à une position donnée
/// </summary>
Vector2 ApplyBoundaryConstraints(Vector2 position)
{
    Vector2 constrainedPosition = position;
    
    // Debug pour voir les valeurs
    if (showDebugInfo)
    {
        Debug.Log($"[CONSTRAINT] Position d'entrée: {position}");
        Debug.Log($"[CONSTRAINT] Bounds: {movementBounds}");
    }
    
    // CONTRAINTES HORIZONTALES (X)
    if (constrainedPosition.x < movementBounds.xMin)
    {
        constrainedPosition.x = movementBounds.xMin;
        if (showDebugInfo) Debug.Log($"[CONSTRAINT] X limité à xMin: {movementBounds.xMin}");
    }
    else if (constrainedPosition.x > movementBounds.xMax)
    {
        constrainedPosition.x = movementBounds.xMax;
        if (showDebugInfo) Debug.Log($"[CONSTRAINT] X limité à xMax: {movementBounds.xMax}");
    }
    
    // CONTRAINTES VERTICALES (Y)  
    if (constrainedPosition.y < movementBounds.yMin)
    {
        constrainedPosition.y = movementBounds.yMin;
        if (showDebugInfo) Debug.Log($"[CONSTRAINT] Y limité à yMin: {movementBounds.yMin}");
    }
    else if (constrainedPosition.y > movementBounds.yMax)
    {
        constrainedPosition.y = movementBounds.yMax;
        if (showDebugInfo) Debug.Log($"[CONSTRAINT] Y limité à yMax: {movementBounds.yMax}");
    }
    
    if (showDebugInfo)
    {
        Debug.Log($"[CONSTRAINT] Position de sortie: {constrainedPosition}");
    }
    
    return constrainedPosition;
}
    
    /// <summary>
    /// Met à jour la rotation du pistolet vers la souris
    /// </summary>
    void UpdateGunRotation()
    {
        Vector2 inputPosition = GetCurrentInputPosition();
        Vector2 gunPosition = gunRect.position;
        
        // Calculer l'angle vers la souris
        Vector2 direction = inputPosition - gunPosition;
        float targetAngle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg + rotationOffset;
        
        // Appliquer la rotation (avec ou sans interpolation)
        if (rotationSpeed > 0)
        {
            float currentAngle = gunRect.eulerAngles.z;
            float newAngle = Mathf.LerpAngle(currentAngle, targetAngle, rotationSpeed * Time.deltaTime);
            gunRect.rotation = Quaternion.Euler(0, 0, newAngle);
        }
        else
        {
            gunRect.rotation = Quaternion.Euler(0, 0, targetAngle);
        }
    }
    
    /// <summary>
    /// Met à jour la visibilité du pistolet selon le contexte
    /// Le gun est TOUJOURS visible à 100%, sauf pendant le feedback
    /// </summary>
    void UpdateGunVisibility()
    {
        // Masquer uniquement pendant le feedback
        if (hideDuringFeedback && gameManager != null)
        {
            bool feedbackActive = gameManager.IsFeedbackPanelActive();
            if (feedbackActive)
            {
                targetAlpha = 0f; // Masquer pendant le feedback
                return;
            }
        }
        
        // Le gun est TOUJOURS visible à 100% (pas de changement de transparence selon les zones)
        targetAlpha = 1f;
    }
    
    /// <summary>
    /// Met à jour l'alpha du pistolet
    /// Le gun est TOUJOURS à 100% d'opacité sauf pendant le feedback
    /// </summary>
    void UpdateGunAlpha()
    {
        if (gunCanvasGroup == null) return;
        
        // Pendant le feedback, masquer progressivement
        if (targetAlpha == 0f)
        {
            float newAlpha = Mathf.MoveTowards(gunCanvasGroup.alpha, 0f, fadeSpeed * Time.deltaTime);
            gunCanvasGroup.alpha = newAlpha;
        }
        else
        {
            // Sinon, toujours 100% visible (pas de transition)
            gunCanvasGroup.alpha = 1f;
        }
    }
    
    /// <summary>
    /// Charge le sprite du pistolet depuis une URL ou le cache
    /// </summary>
    public void LoadGunFromURL(string url)
    {
        if (gunImage == null)
        {
            Debug.LogError("GunSpriteManager: Image du pistolet non initialisée !");
            return;
        }
        
        // 🚀 NOUVEAU : Vérifier d'abord le cache de GameDataManager
        if (GameDataManager.Instance != null)
        {
            Sprite cachedSprite = GameDataManager.Instance.GetCachedSprite("gun");
            if (cachedSprite != null)
            {
                Debug.Log($"[GunSpriteManager] ⚡ Gun chargé instantanément depuis le cache !");
                ApplyGunSprite(cachedSprite);
                return;
            }
            
            // Essayer aussi avec la texture
            Texture2D cachedTexture = GameDataManager.Instance.GetCachedTexture("gun");
            if (cachedTexture != null)
            {
                Debug.Log($"[GunSpriteManager] ⚡ Gun 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);
                ApplyGunSprite(sprite);
                return;
            }
        }
        
        StartCoroutine(DownloadGunSprite(url));
    }
    
    /// <summary>
    /// Applique un sprite au gun et configure l'affichage
    /// </summary>
    private void ApplyGunSprite(Sprite sprite)
    {
        if (sprite == null || gunImage == null) return;
        
        gunImage.sprite = sprite;
        
        // S'assurer qu'il est visible
        if (gunImage.color.a < 0.01f)
        {
            gunImage.color = Color.white;
        }
        
        Debug.Log("[GunSpriteManager] ✅ Sprite du pistolet appliqué et visible");
    }
    
    /// <summary>
    /// Coroutine pour télécharger le sprite du pistolet
    /// </summary>
    IEnumerator DownloadGunSprite(string url)
    {
        Debug.Log($"[GunSpriteManager] 📥 Téléchargement du pistolet depuis {url}");
        Debug.Log($"[GunSpriteManager] 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($"[GunSpriteManager] ✅ Texture reçue: {texture.width}x{texture.height}");
            
            try
            {
                // Créer le sprite
                Sprite gunSprite = 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
                ApplyGunSprite(gunSprite);
            }
            catch (System.Exception e)
            {
                Debug.LogError($"[GunSpriteManager] ❌ Erreur création sprite: {e.Message}");
                CreateFallbackGun();
            }
        }
        else
        {
            Debug.LogError($"[GunSpriteManager] ❌ Échec téléchargement: {error}");
            Debug.LogError($"[GunSpriteManager] URL: {url}");
            
            #if UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
            Debug.LogError("[GunSpriteManager] 🍎 PROBLÈME MAC - Création du fallback...");
            #endif
            
            // Fallback : créer un pistolet simple
            CreateFallbackGun();
        }
    }
    
    /// <summary>
    /// Crée un sprite de pistolet de fallback simple
    /// </summary>
    void CreateFallbackGun()
    {
        // Créer une texture simple pour le pistolet
        Texture2D fallbackTexture = new Texture2D(64, 32);
        Color[] pixels = new Color[64 * 32];
        
        // Remplir avec transparence
        for (int i = 0; i < pixels.Length; i++)
        {
            pixels[i] = Color.clear;
        }
        
        // Dessiner un pistolet simple (rectangles)
        for (int x = 0; x < 64; x++)
        {
            for (int y = 0; y < 32; y++)
            {
                // Canon
                if (x >= 40 && x <= 60 && y >= 12 && y <= 20)
                {
                    pixels[y * 64 + x] = Color.gray;
                }
                // Corps
                if (x >= 20 && x <= 45 && y >= 8 && y <= 24)
                {
                    pixels[y * 64 + x] = Color.gray;
                }
                // Poignée
                if (x >= 25 && x <= 35 && y >= 0 && y <= 15)
                {
                    pixels[y * 64 + x] = Color.gray;
                }
            }
        }
        
        fallbackTexture.SetPixels(pixels);
        fallbackTexture.Apply();
        dynamicTextures.Add(fallbackTexture);
        
        // Créer le sprite
        Sprite fallbackSprite = Sprite.Create(
            fallbackTexture,
            new Rect(0, 0, 64, 32),
            new Vector2(0.5f, 0.5f),
            100f
        );
        dynamicSprites.Add(fallbackSprite);
        
        gunImage.sprite = fallbackSprite;
        
        Debug.Log("GunSpriteManager: Pistolet de fallback créé");
    }
    
    // ========================================
    // MÉTHODES PUBLIQUES DE CONFIGURATION
    // ========================================
    
    /// <summary>
    /// Configure l'offset du pistolet par rapport au curseur
    /// </summary>
    public void SetGunOffset(Vector2 newOffset)
    {
        offsetFromCursor = newOffset;
        
        if (showDebugInfo)
        {
            Debug.Log($"GunSpriteManager: Offset mis à jour: {newOffset}");
        }
    }
    
    /// <summary>
    /// Configure la taille du pistolet (carré)
    /// </summary>
    public void SetGunSize(float newSize)
    {
        gunSize = newSize;
        
        if (gunRect != null)
        {
            gunRect.sizeDelta = new Vector2(newSize, newSize);
            
            // Recalculer les contraintes si config existe
            if (boundaryConfig != null)
            {
                UpdateMovementBounds();
            }
        }
    }
    
    /// <summary>
    /// Configure la taille du pistolet avec largeur et hauteur séparées
    /// </summary>
    public void SetGunSize(Vector2 newSize)
    {
        if (gunRect != null)
        {
            gunRect.sizeDelta = newSize;
            
            Debug.Log($"SetGunSize appelé avec: {newSize}");
            Debug.Log($"sizeDelta appliqué: {gunRect.sizeDelta}");
            
            // Recalculer les contraintes si config existe
            if (boundaryConfig != null)
            {
                UpdateMovementBounds();
            }
        }
    }
    
    /// <summary>
    /// Configure la taille du pistolet avec largeur et hauteur séparées
    /// </summary>
    public void SetGunSize(float width, float height)
    {
        SetGunSize(new Vector2(width, height));
    }
    
    /// <summary>
    /// Active/désactive la rotation du pistolet
    /// </summary>
    public void SetRotationEnabled(bool enabled)
    {
        enableRotation = enabled;
        
        if (!enabled && gunRect != null)
        {
            gunRect.rotation = Quaternion.identity;
        }
    }
    
    /// <summary>
    /// Configure le mode de visibilité (ignoré - le gun est toujours visible)
    /// </summary>
    public void SetAlwaysVisible(bool always)
    {
        // Le gun est TOUJOURS visible à 100%, cette option est ignorée
        // Seul le crosshair change de transparence selon les zones
        alwaysVisible = true;
        targetAlpha = 1f;
    }
    
    /// <summary>
    /// Change la couleur du pistolet
    /// </summary>
    public void SetGunColor(Color color)
    {
        if (gunImage != null)
        {
            gunImage.color = color;
        }
    }
    
    /// <summary>
    /// Vérifie si le pistolet est actuellement visible
    /// </summary>
    public bool IsVisible()
    {
        return gunCanvasGroup != null && gunCanvasGroup.alpha > 0f;
    }
    
    // ========================================
    // MÉTHODES DE CONTRAINTES DE MOUVEMENT
    // ========================================
    
    /// <summary>
    /// Configure les contraintes de mouvement depuis la configuration JSON
    /// </summary>
    public void SetBoundaryConfiguration(GunBoundaryConfig config)
    {
        boundaryConfig = config;
        UpdateMovementBounds();
        
        Debug.Log($"Configuration contraintes pistolet mise à jour");
    }
    
    /// <summary>
    /// Met à jour les limites de mouvement basées sur la configuration actuelle
    /// </summary>
    void UpdateMovementBounds()
    {
        if (boundaryConfig == null || gunRect == null)
        {
            enableBoundaryConstraints = false;
            Debug.Log("[BOUNDARY] Contraintes désactivées - config ou gunRect null");
            return;
        }
        
        Vector2 gunSize = gunRect.sizeDelta;
        Vector2 screenSize = GetCanvasReferenceSize();
        
        movementBounds = boundaryConfig.GetConstrainedRect(gunSize, screenSize);
        enableBoundaryConstraints = boundaryConfig.enableBoundaryConstraints;
        
        Debug.Log($"[BOUNDARY] === UPDATE BOUNDS ===");
        Debug.Log($"[BOUNDARY] Écran: {screenSize}, Pistolet: {gunSize}");
        Debug.Log($"[BOUNDARY] Limites: {movementBounds}");
        Debug.Log($"[BOUNDARY] xMin={movementBounds.xMin}, xMax={movementBounds.xMax}");
        Debug.Log($"[BOUNDARY] yMin={movementBounds.yMin}, yMax={movementBounds.yMax}");
        Debug.Log($"[BOUNDARY] Contraintes actives: {enableBoundaryConstraints}");
        Debug.Log($"[BOUNDARY] === FIN UPDATE ===");
    }
    


    public void TestBoundaryDirections()
{
    if (!enableBoundaryConstraints)
    {
        Debug.Log("[TEST] Contraintes désactivées");
        return;
    }
    
    Vector2 canvasSize = GetCanvasReferenceSize();
    Vector2 center = new Vector2(canvasSize.x / 2f, canvasSize.y / 2f);
    
    Debug.Log("[TEST] === TEST DES 4 DIRECTIONS ===");
    
    // Test GAUCHE
    Vector2 testLeft = new Vector2(0, center.y);
    Vector2 constrainedLeft = ApplyBoundaryConstraints(testLeft);
    Debug.Log($"[TEST] GAUCHE: {testLeft} → {constrainedLeft} (doit être >= {movementBounds.xMin})");
    
    // Test DROITE  
    Vector2 testRight = new Vector2(canvasSize.x, center.y);
    Vector2 constrainedRight = ApplyBoundaryConstraints(testRight);
    Debug.Log($"[TEST] DROITE: {testRight} → {constrainedRight} (doit être <= {movementBounds.xMax})");
    
    // Test HAUT
    Vector2 testTop = new Vector2(center.x, canvasSize.y);
    Vector2 constrainedTop = ApplyBoundaryConstraints(testTop);
    Debug.Log($"[TEST] HAUT: {testTop} → {constrainedTop} (doit être <= {movementBounds.yMax})");
    
    // Test BAS
    Vector2 testBottom = new Vector2(center.x, 0);
    Vector2 constrainedBottom = ApplyBoundaryConstraints(testBottom);
    Debug.Log($"[TEST] BAS: {testBottom} → {constrainedBottom} (doit être >= {movementBounds.yMin})");
    
    Debug.Log("[TEST] === FIN TEST ===");
}



    /// <summary>
    /// Active/désactive les contraintes de mouvement
    /// </summary>
    public void SetBoundaryConstraintsEnabled(bool enabled)
    {
        enableBoundaryConstraints = enabled;
        Debug.Log($"Contraintes pistolet: {(enabled ? "ACTIVÉES" : "DÉSACTIVÉES")}");
    }
    
    /// <summary>
    /// Définit une zone de contraintes personnalisée
    /// </summary>
    public void SetCustomBoundary(Rect customBounds)
    {
        movementBounds = customBounds;
        enableBoundaryConstraints = true;
        Debug.Log($"Contraintes personnalisées définies: {customBounds}");
    }
    
    /// <summary>
    /// Obtient les limites actuelles de mouvement
    /// </summary>
    public Rect GetMovementBounds()
    {
        return movementBounds;
    }
    
    /// <summary>
    /// Vérifie si les contraintes de mouvement sont actives
    /// </summary>
    public bool AreBoundaryConstraintsEnabled()
    {
        return enableBoundaryConstraints;
    }


    
    // ========================================
    // MÉTHODES DE DEBUG
    // ========================================
    
    /// <summary>
    /// Debug complet du système de visibilité du pistolet
    /// </summary>
    public void DebugGunVisibility()
    {
        Debug.Log("=== DEBUG PISTOLET ===");
        Debug.Log($"alwaysVisible: {alwaysVisible}");
        Debug.Log($"hideDuringFeedback: {hideDuringFeedback}");
        Debug.Log($"targetAlpha: {targetAlpha}");
        Debug.Log($"currentAlpha: {(gunCanvasGroup != null ? gunCanvasGroup.alpha : -1f)}");
        Debug.Log($"feedbackActive: {(gameManager != null ? gameManager.IsFeedbackPanelActive() : "GameManager null")}");
        
        // Debug des contraintes
        Debug.Log($"Contraintes activées: {enableBoundaryConstraints}");
        if (enableBoundaryConstraints)
        {
            Debug.Log($"Limites: {movementBounds}");
            if (boundaryConfig != null)
            {
                Vector2 screenSize = GetCanvasReferenceSize();
                Vector2 gunSize = gunRect != null ? gunRect.sizeDelta : Vector2.zero;
                Debug.Log($"Config: enableBoundaryConstraints={boundaryConfig.enableBoundaryConstraints}, useAutomaticMargins={boundaryConfig.useAutomaticMargins}");
                Debug.Log($"Écran: {screenSize}, Pistolet: {gunSize}");
            }
        }
        Debug.Log("=====================");
    }
    
    void OnDestroy()
    {
        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("[GunSpriteManager] 🧹 Ressources dynamiques nettoyées");
    }
}