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

/// <summary>
/// Utilitaire pour appliquer le style de panel aux feedback panels
/// </summary>
public static class FeedbackPanelStyler
{
    /// <summary>
    /// Applique le style de panel configuré dans general-config.json au feedback panel
    /// Utilise questPreviewPanel pour la cohérence visuelle avec le reste du projet
    /// </summary>
    public static IEnumerator ApplyPanelStyle(GameObject panel)
    {
        if (panel == null)
        {
            Debug.LogError("[FeedbackPanelStyler] Panel est null");
            yield break;
        }

        var config = GeneralConfigManager.Instance?.GetConfig();
        if (config == null)
        {
            Debug.LogError("[FeedbackPanelStyler] GeneralConfigManager.Instance est null");
            yield break;
        }

        var feedbackConfig = config.defaultFeedbackMessages;
        
        // Récupérer le style depuis questPreviewPanel pour la cohérence visuelle
        var questPreviewConfig = config.questPreviewPanel;
        
        // Créer un panelStyleConfig à partir de questPreviewPanel
        FeedbackPanelStyleConfig panelStyleConfig;
        if (questPreviewConfig != null)
        {
            panelStyleConfig = new FeedbackPanelStyleConfig
            {
                backgroundColor = questPreviewConfig.backgroundColor ?? "#f5ece5",
                cornerRadius = questPreviewConfig.cornerRadius > 0 ? questPreviewConfig.cornerRadius : 40f
            };
            
            // Récupérer l'ombre depuis questPreviewPanel.shadow
            if (questPreviewConfig.shadow != null)
            {
                panelStyleConfig.shadow = new FeedbackPanelShadowConfig
                {
                    enabled = questPreviewConfig.shadow.enabled,
                    color = questPreviewConfig.shadow.color ?? "#dbc3b7",
                    offsetX = questPreviewConfig.shadow.offsetX,
                    offsetY = questPreviewConfig.shadow.offsetY,
                    blur = questPreviewConfig.shadow.blur
                };
                Debug.Log($"[FeedbackPanelStyler] Shadow configuré: enabled={panelStyleConfig.shadow.enabled}, color={panelStyleConfig.shadow.color}, offsetY={panelStyleConfig.shadow.offsetY}");
            }
            else
            {
                // Créer une ombre par défaut si non définie
                panelStyleConfig.shadow = new FeedbackPanelShadowConfig
                {
                    enabled = true,
                    color = "#00000040", // Noir semi-transparent plus visible
                    offsetX = 0,
                    offsetY = 10,
                    blur = 16
                };
                Debug.Log("[FeedbackPanelStyler] Shadow par défaut créé (questPreviewConfig.shadow était null)");
            }
            
            Debug.Log("[FeedbackPanelStyler] Utilisation du style questPreviewPanel");
        }
        else if (feedbackConfig?.panelStyle != null)
        {
            // Fallback vers l'ancien style si questPreviewPanel n'existe pas
            panelStyleConfig = feedbackConfig.panelStyle;
            Debug.Log("[FeedbackPanelStyler] Fallback vers defaultFeedbackMessages.panelStyle");
        }
        else
        {
            Debug.LogError("[FeedbackPanelStyler] Aucune configuration de style trouvée");
            yield break;
        }

        // Cacher tous les anciens enfants de la scène qui ne sont plus utilisés
        // (Background, ClickHintText, etc.) mais garder FeedbackText et les éléments créés dynamiquement
        string[] elementsToKeep = { "FeedbackText", "FeedbackCloseButton", "FeedbackShadow", "FeedbackPicto" };
        for (int i = 0; i < panel.transform.childCount; i++)
        {
            Transform child = panel.transform.GetChild(i);
            bool shouldKeep = false;
            foreach (string keepName in elementsToKeep)
            {
                if (child.name == keepName || child.name.StartsWith(keepName))
                {
                    shouldKeep = true;
                    break;
                }
            }
            if (!shouldKeep)
            {
                child.gameObject.SetActive(false);
                Debug.Log($"[FeedbackPanelStyler] Élément '{child.name}' caché");
            }
        }

        RectTransform panelRect = panel.GetComponent<RectTransform>();
        if (panelRect == null)
        {
            panelRect = panel.AddComponent<RectTransform>();
        }

        // Centrer le panel
        panelRect.anchorMin = new Vector2(0.5f, 0.5f);
        panelRect.anchorMax = new Vector2(0.5f, 0.5f);
        panelRect.pivot = new Vector2(0.5f, 0.5f);
        panelRect.anchoredPosition = Vector2.zero;

        // Appliquer la taille depuis la config feedback (depuis general-config.json)
        Vector2 panelSize = new Vector2(1024, 635); // Valeur par défaut
        if (feedbackConfig != null && feedbackConfig.useCustomPanelSize && feedbackConfig.panelSize != null)
        {
            panelSize = feedbackConfig.panelSize;
            Debug.Log($"[FeedbackPanelStyler] Taille panel depuis general-config.json: {panelSize.x}x{panelSize.y}");
        }
        else if (feedbackConfig != null && feedbackConfig.panelSize != null)
        {
            // Utiliser panelSize même si useCustomPanelSize est false
            panelSize = feedbackConfig.panelSize;
            Debug.Log($"[FeedbackPanelStyler] Taille panel depuis general-config.json (useCustomPanelSize=false mais panelSize défini): {panelSize.x}x{panelSize.y}");
        }
        
        panelRect.sizeDelta = panelSize;

        // Nettoyer l'image existante
        Image panelImage = panel.GetComponent<Image>();
        if (panelImage == null)
        {
            panelImage = panel.AddComponent<Image>();
        }

        // Réinitialiser l'image (ne pas détruire le sprite existant car il peut être un asset)
        panelImage.sprite = null;
        panelImage.color = Color.white;
        panelImage.raycastTarget = true;
        panelImage.type = Image.Type.Simple;

        // Créer le sprite avec coins arrondis
        Color bgColor = HexToColor(panelStyleConfig.backgroundColor);
        float radius = panelStyleConfig.cornerRadius;
        int width = (int)panelSize.x;
        int height = (int)panelSize.y;

        panelImage.sprite = CreateRoundedColorSprite(width, height, radius, bgColor);

        // SUPPRIMER le Mask existant s'il y en a un (il masque le picto)
        Mask panelMask = panel.GetComponent<Mask>();
        if (panelMask != null)
        {
            Object.Destroy(panelMask);
        }

        // Appliquer l'ombre si configurée
        if (panelStyleConfig.shadow != null && panelStyleConfig.shadow.enabled)
        {
            yield return CreateShadow(panel, panelStyleConfig.shadow, width, height, radius, panelSize);
        }

        Debug.Log($"[FeedbackPanelStyler] Style de panel feedback appliqué depuis defaultFeedbackMessages.panelStyle");
    }

    /// <summary>
    /// Crée une ombre pour le panel - MÊME SYSTÈME QUE LoginPopup
    /// </summary>
    private static IEnumerator CreateShadow(GameObject panel, FeedbackPanelShadowConfig shadowConfig, int width, int height, float radius, Vector2 panelSize)
    {
        // Chercher si une ombre existe déjà (chercher dans le parent du panel)
        Transform parentTransform = panel.transform.parent;
        if (parentTransform != null)
        {
            Transform existingShadow = parentTransform.Find("FeedbackPanelShadow");
            if (existingShadow != null)
            {
                Object.Destroy(existingShadow.gameObject);
            }
        }

        // MÊME SYSTÈME QUE LoginPopup : l'ombre est un SIBLING du panel (même parent)
        GameObject shadowObj = new GameObject("FeedbackPanelShadow");
        shadowObj.transform.SetParent(parentTransform, false);
        
        RectTransform shadowRect = shadowObj.AddComponent<RectTransform>();
        
        // Copier exactement le positionnement du panel
        RectTransform panelRect = panel.GetComponent<RectTransform>();
        shadowRect.anchorMin = panelRect.anchorMin;
        shadowRect.anchorMax = panelRect.anchorMax;
        shadowRect.pivot = panelRect.pivot;
        shadowRect.sizeDelta = panelSize;
        
        // Décaler l'ombre selon la config - EXACTEMENT COMME LoginPopup
        // offsetY positif = ombre vers le BAS, donc on utilise -offsetY
        shadowRect.anchoredPosition = new Vector2(shadowConfig.offsetX, -shadowConfig.offsetY);
        
        Debug.Log($"[FeedbackPanelStyler] Ombre positionnée (système LoginPopup) - offsetY config: {shadowConfig.offsetY}, anchoredPosition.y: {-shadowConfig.offsetY}");

        Image shadowImage = shadowObj.AddComponent<Image>();
        Color shadowColor = HexToColor(shadowConfig.color);
        shadowImage.sprite = CreateRoundedColorSprite(width, height, radius, shadowColor);
        shadowImage.color = Color.white;
        shadowImage.raycastTarget = false;
        
        // L'ombre doit être DERRIÈRE le panel - la mettre en premier dans le parent
        shadowObj.transform.SetAsFirstSibling();
        // S'assurer que le panel est DEVANT l'ombre
        panel.transform.SetAsLastSibling();

        Debug.Log($"[FeedbackPanelStyler] Ombre créée - Couleur: {shadowConfig.color}, Offset: ({shadowConfig.offsetX}, {shadowConfig.offsetY})");

        yield return null;
    }

    /// <summary>
    /// Crée un sprite avec des coins arrondis et une couleur spécifique
    /// </summary>
    private static Sprite CreateRoundedColorSprite(int width, int height, float radius, Color fillColor)
    {
        Texture2D texture = new Texture2D(width, height);
        Color[] pixels = new Color[width * height];

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                float alpha = 1f;

                // Coin supérieur gauche
                if (x < radius && y > height - radius)
                {
                    float dx = radius - x;
                    float dy = (height - radius) - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius)
                        alpha = 0f;
                    else
                        alpha = 1f - Mathf.Clamp01((distance - radius + 1) / 1);
                }
                // Coin supérieur droit
                else if (x > width - radius && y > height - radius)
                {
                    float dx = x - (width - radius);
                    float dy = (height - radius) - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius)
                        alpha = 0f;
                    else
                        alpha = 1f - Mathf.Clamp01((distance - radius + 1) / 1);
                }
                // Coin inférieur gauche
                else if (x < radius && y < radius)
                {
                    float dx = radius - x;
                    float dy = radius - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius)
                        alpha = 0f;
                    else
                        alpha = 1f - Mathf.Clamp01((distance - radius + 1) / 1);
                }
                // Coin inférieur droit
                else if (x > width - radius && y < radius)
                {
                    float dx = x - (width - radius);
                    float dy = radius - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius)
                        alpha = 0f;
                    else
                        alpha = 1f - Mathf.Clamp01((distance - radius + 1) / 1);
                }

                pixels[y * width + x] = new Color(fillColor.r, fillColor.g, fillColor.b, fillColor.a * alpha);
            }
        }

        texture.SetPixels(pixels);
        texture.Apply();

        return Sprite.Create(texture, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f), 100f);
    }

    /// <summary>
    /// Convertit une couleur hexadécimale en Color
    /// </summary>
    private static Color HexToColor(string hex)
    {
        if (string.IsNullOrEmpty(hex))
            return Color.white;

        if (hex.StartsWith("#"))
            hex = hex.Substring(1);

        if (hex.Length == 6)
        {
            int r = int.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
            int g = int.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
            int b = int.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
            return new Color(r / 255f, g / 255f, b / 255f, 1f);
        }
        else if (hex.Length == 8)
        {
            int r = int.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
            int g = int.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
            int b = int.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
            int a = int.Parse(hex.Substring(6, 2), System.Globalization.NumberStyles.HexNumber);
            return new Color(r / 255f, g / 255f, b / 255f, a / 255f);
        }

        return Color.white;
    }

    /// <summary>
    /// Crée et affiche le picto de bonne/mauvaise réponse
    /// </summary>
    public static IEnumerator CreateFeedbackPicto(GameObject panel, bool isCorrect)
    {
        var config = GeneralConfigManager.Instance?.GetConfig();
        if (config == null || config.defaultFeedbackMessages == null || config.defaultFeedbackMessages.picto == null)
        {
            Debug.LogWarning("[FeedbackPanelStyler] Configuration picto introuvable");
            yield break;
        }

        var pictoConfig = config.defaultFeedbackMessages.picto;
        if (!pictoConfig.show)
        {
            yield break;
        }

        // Supprimer l'ancien picto s'il existe (chercher dans le parent du panel)
        Transform parentTransform = panel.transform.parent;
        if (parentTransform != null)
        {
            Transform existingPicto = parentTransform.Find("FeedbackPicto");
            if (existingPicto != null)
            {
                Object.Destroy(existingPicto.gameObject);
            }
        }

        string pictoUrl = isCorrect ? pictoConfig.goodAnswerUrl : pictoConfig.badAnswerUrl;
        if (string.IsNullOrEmpty(pictoUrl))
        {
            Debug.LogWarning("[FeedbackPanelStyler] URL du picto vide");
            yield break;
        }

        // Construire l'URL complète depuis uiPath (les pictos sont dans le dossier UI)
        string fullImageUrl = GeneralConfigManager.Instance.GetUIUrl(pictoUrl);
        Debug.Log($"[FeedbackPanelStyler] 📸 Chargement picto depuis uiPath:");
        Debug.Log($"[FeedbackPanelStyler]   - Nom fichier: {pictoUrl}");
        Debug.Log($"[FeedbackPanelStyler]   - URL complète: {fullImageUrl}");
        
        // Si l'URL ne commence pas par http/https, essayer de la construire manuellement
        if (!fullImageUrl.StartsWith("http://") && !fullImageUrl.StartsWith("https://"))
        {
            var generalConfig = GeneralConfigManager.Instance?.GetConfig();
            if (generalConfig?.assetsPaths != null && !string.IsNullOrEmpty(generalConfig.assetsPaths.uiPath))
            {
                fullImageUrl = generalConfig.assetsPaths.uiPath + pictoUrl;
                Debug.Log($"[FeedbackPanelStyler]   - URL reconstruite: {fullImageUrl}");
            }
        }

        // Créer le picto comme ENFANT du panel (le Mask a été supprimé, pas besoin de Canvas override)
        GameObject pictoObj = new GameObject("FeedbackPicto");
        pictoObj.transform.SetParent(panel.transform, false);

        RectTransform panelRect = panel.GetComponent<RectTransform>();
        RectTransform pictoRect = pictoObj.AddComponent<RectTransform>();
        
        // Positionner le picto sur la bordure supérieure du panel
        pictoRect.anchorMin = new Vector2(0.5f, 1f); // Ancré en haut au centre
        pictoRect.anchorMax = new Vector2(0.5f, 1f);
        pictoRect.pivot = new Vector2(0.5f, 0.5f); // Pivot au centre
        pictoRect.sizeDelta = pictoConfig.size;
        
        // Position Y : 0 = centre du picto sur la bordure, positif = plus haut
        float pictoY = pictoConfig.position.y;
        pictoRect.anchoredPosition = new Vector2(pictoConfig.position.x, pictoY);
        
        Debug.Log($"[FeedbackPanelStyler] 📸 Picto positionné - Ancré en haut, Y offset: {pictoY}, Size: {pictoConfig.size}");

        Image pictoImage = pictoObj.AddComponent<Image>();
        pictoImage.raycastTarget = false;

        // Charger l'image manuellement (plus fiable que UnityWebRequestTexture pour certains serveurs)
        using (UnityWebRequest www = UnityWebRequest.Get(fullImageUrl))
        {
            www.timeout = 10; // Timeout de 10 secondes
            yield return www.SendWebRequest();

            if (www.result == UnityWebRequest.Result.Success)
            {
                // Charger la texture manuellement depuis les données binaires
                byte[] imageData = www.downloadHandler.data;
                if (imageData != null && imageData.Length > 0)
                {
                    Texture2D texture = new Texture2D(2, 2);
                    if (texture.LoadImage(imageData))
                    {
                        // S'assurer que la texture est lue correctement
                        texture.wrapMode = TextureWrapMode.Clamp;
                        texture.filterMode = FilterMode.Bilinear;
                        
                        // Créer le sprite avec les bonnes dimensions
                        Sprite sprite = Sprite.Create(texture,
                            new Rect(0, 0, texture.width, texture.height),
                            new Vector2(0.5f, 0.5f),
                            100f);
                        
                        if (sprite != null)
                        {
                            pictoImage.sprite = sprite;
                            pictoImage.preserveAspect = true;
                            pictoImage.color = Color.white; // S'assurer que la couleur est blanche (pas transparente)
                            Debug.Log($"[FeedbackPanelStyler] ✅ Picto chargé avec succès - Taille texture: {texture.width}x{texture.height}, Sprite: {sprite.name}");
                        }
                        else
                        {
                            Debug.LogError($"[FeedbackPanelStyler] ❌ Impossible de créer le sprite depuis la texture");
                        }
                    }
                    else
                    {
                        Debug.LogError($"[FeedbackPanelStyler] ❌ Impossible de décoder l'image PNG");
                    }
                }
                else
                {
                    Debug.LogError($"[FeedbackPanelStyler] ❌ Données image vides ou null");
                }
            }
            else
            {
                Debug.LogError($"[FeedbackPanelStyler] ❌ Erreur chargement picto: {www.error}");
                Debug.LogError($"[FeedbackPanelStyler] ❌ URL: {fullImageUrl}");
                Debug.LogError($"[FeedbackPanelStyler] ❌ Code HTTP: {www.responseCode}");
                Debug.LogError($"[FeedbackPanelStyler] ❌ Résultat: {www.result}");
            }
        }
    }
}
