using System;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

/// <summary>
/// Classe utilitaire pour créer des panneaux stylés basés sur les configurations de general-config.json
/// </summary>
public static class StyledPanelBuilder
{
    /// <summary>
    /// Résultat de la création d'un panneau stylé
    /// </summary>
    public class StyledPanelResult
    {
        public GameObject panelObject;
        public GameObject headerObject;
        public GameObject contentContainer;
        public RectTransform panelRect;
        public RectTransform headerRect;
        public RectTransform contentRect;
        public Image panelImage;
        public Image headerImage;
    }
    
    /// <summary>
    /// Crée un panneau stylé basé sur un style de panneau configuré
    /// </summary>
    /// <param name="parent">Le transform parent</param>
    /// <param name="styleName">Le nom du style (ex: "defaultPanel", "modalDark")</param>
    /// <param name="width">Largeur du panneau</param>
    /// <param name="height">Hauteur du panneau</param>
    /// <param name="panelName">Nom du GameObject (optionnel)</param>
    /// <returns>StyledPanelResult contenant les références aux éléments créés</returns>
    public static StyledPanelResult CreateStyledPanel(Transform parent, string styleName, float width, float height, string panelName = "StyledPanel")
    {
        var config = GeneralConfigManager.Instance?.GetConfig();
        var panelStyle = config?.panelStyles?.GetStyle(styleName);
        
        if (panelStyle == null)
        {
            Debug.LogWarning($"[StyledPanelBuilder] Style '{styleName}' non trouvé, utilisation du style par défaut");
            panelStyle = config?.panelStyles?.defaultPanel;
        }
        
        if (panelStyle == null)
        {
            Debug.LogError($"[StyledPanelBuilder] Aucun style de panneau disponible");
            return null;
        }
        
        return CreatePanelFromStyle(parent, panelStyle, width, height, panelName);
    }
    
    /// <summary>
    /// Crée un panneau à partir d'un style spécifique
    /// </summary>
    public static StyledPanelResult CreatePanelFromStyle(Transform parent, PanelStyleConfig style, float width, float height, string panelName = "StyledPanel")
    {
        var result = new StyledPanelResult();
        
        // Créer le panneau principal
        result.panelObject = new GameObject(panelName);
        result.panelObject.transform.SetParent(parent, false);
        
        result.panelRect = result.panelObject.AddComponent<RectTransform>();
        result.panelRect.sizeDelta = new Vector2(width, height);
        
        // Image de fond du panneau avec coins arrondis
        result.panelImage = result.panelObject.AddComponent<Image>();
        Color bgColor = HexToColor(style.backgroundColor);
        result.panelImage.sprite = CreateRoundedSprite((int)width, (int)height, style.cornerRadius, bgColor);
        result.panelImage.color = Color.white;
        result.panelImage.type = Image.Type.Simple;
        result.panelImage.raycastTarget = true;
        
        // Ajouter l'ombre si configurée
        if (style.shadow != null && style.shadow.enabled)
        {
            Shadow shadow = result.panelObject.AddComponent<Shadow>();
            shadow.effectColor = HexToColor(style.shadow.color);
            shadow.effectDistance = new Vector2(style.shadow.offsetX, -style.shadow.offsetY);
            Debug.Log($"[StyledPanelBuilder] Ombre ajoutée: {style.shadow.color}");
        }
        
        // Ajouter la bordure si configurée (via Outline)
        if (style.border != null && style.border.enabled && style.border.width > 0)
        {
            Outline outline = result.panelObject.AddComponent<Outline>();
            outline.effectColor = HexToColor(style.border.color);
            outline.effectDistance = new Vector2(style.border.width, style.border.width);
            Debug.Log($"[StyledPanelBuilder] Bordure ajoutée: {style.border.color}");
        }
        
        float contentTopOffset = 0;
        
        // Créer le header si activé
        if (style.header != null && style.header.enabled && style.header.height > 0)
        {
            result.headerObject = new GameObject("Header");
            result.headerObject.transform.SetParent(result.panelObject.transform, false);
            
            result.headerRect = result.headerObject.AddComponent<RectTransform>();
            result.headerRect.anchorMin = new Vector2(0, 1);
            result.headerRect.anchorMax = new Vector2(1, 1);
            result.headerRect.pivot = new Vector2(0.5f, 1);
            result.headerRect.sizeDelta = new Vector2(0, style.header.height);
            result.headerRect.anchoredPosition = Vector2.zero;
            
            result.headerImage = result.headerObject.AddComponent<Image>();
            Color headerColor = HexToColor(style.header.backgroundColor);
            
            // Créer un sprite avec coins arrondis en haut seulement
            result.headerImage.sprite = CreateHeaderSprite((int)width, (int)style.header.height, style.header.cornerRadius, headerColor);
            result.headerImage.color = Color.white;
            result.headerImage.type = Image.Type.Simple;
            result.headerImage.raycastTarget = true;
            
            contentTopOffset = style.header.height;
            Debug.Log($"[StyledPanelBuilder] Header créé: height={style.header.height}, color={style.header.backgroundColor}");
        }
        
        // Créer le conteneur de contenu
        result.contentContainer = new GameObject("Content");
        result.contentContainer.transform.SetParent(result.panelObject.transform, false);
        
        result.contentRect = result.contentContainer.AddComponent<RectTransform>();
        result.contentRect.anchorMin = Vector2.zero;
        result.contentRect.anchorMax = Vector2.one;
        result.contentRect.sizeDelta = Vector2.zero;
        result.contentRect.offsetMin = new Vector2(0, 0); // Bas et gauche
        result.contentRect.offsetMax = new Vector2(0, -contentTopOffset); // Haut (moins le header) et droite
        
        Debug.Log($"[StyledPanelBuilder] Panneau créé: {width}x{height}, style={style.backgroundColor}");
        
        return result;
    }
    
    /// <summary>
    /// Crée un sprite arrondi avec une couleur
    /// </summary>
    private static Sprite CreateRoundedSprite(int width, int height, float borderRadius, Color color)
    {
        Texture2D texture = new Texture2D(width, height);
        texture.filterMode = FilterMode.Bilinear;
        
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                float distFromEdge = CalculateDistanceFromRoundedEdge(x, y, width, height, borderRadius);
                
                if (distFromEdge < 0)
                {
                    texture.SetPixel(x, y, Color.clear);
                }
                else
                {
                    texture.SetPixel(x, y, color);
                }
            }
        }
        
        texture.Apply();
        return Sprite.Create(texture, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f), 100f);
    }
    
    /// <summary>
    /// Crée un sprite pour le header (coins arrondis en haut seulement)
    /// </summary>
    private static Sprite CreateHeaderSprite(int width, int height, float borderRadius, Color color)
    {
        Texture2D texture = new Texture2D(width, height);
        texture.filterMode = FilterMode.Bilinear;
        
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                // Coins arrondis uniquement en haut
                bool isTransparent = false;
                
                // Coin haut-gauche
                if (x < borderRadius && y > height - 1 - borderRadius)
                {
                    float dx = borderRadius - x;
                    float dy = y - (height - 1 - borderRadius);
                    float dist = Mathf.Sqrt(dx * dx + dy * dy);
                    if (dist > borderRadius) isTransparent = true;
                }
                // Coin haut-droit
                else if (x > width - 1 - borderRadius && y > height - 1 - borderRadius)
                {
                    float dx = x - (width - 1 - borderRadius);
                    float dy = y - (height - 1 - borderRadius);
                    float dist = Mathf.Sqrt(dx * dx + dy * dy);
                    if (dist > borderRadius) isTransparent = true;
                }
                
                texture.SetPixel(x, y, isTransparent ? Color.clear : color);
            }
        }
        
        texture.Apply();
        return Sprite.Create(texture, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f), 100f);
    }
    
    /// <summary>
    /// Calcule la distance depuis le bord arrondi
    /// </summary>
    private static float CalculateDistanceFromRoundedEdge(int x, int y, int width, int height, float radius)
    {
        float distLeft = x;
        float distRight = width - 1 - x;
        float distBottom = y;
        float distTop = height - 1 - y;
        
        // Coin bas-gauche
        if (x < radius && y < radius)
        {
            float dx = radius - x;
            float dy = radius - y;
            return radius - Mathf.Sqrt(dx * dx + dy * dy);
        }
        // Coin bas-droit
        if (x > width - 1 - radius && y < radius)
        {
            float dx = x - (width - 1 - radius);
            float dy = radius - y;
            return radius - Mathf.Sqrt(dx * dx + dy * dy);
        }
        // Coin haut-gauche
        if (x < radius && y > height - 1 - radius)
        {
            float dx = radius - x;
            float dy = y - (height - 1 - radius);
            return radius - Mathf.Sqrt(dx * dx + dy * dy);
        }
        // Coin haut-droit
        if (x > width - 1 - radius && y > height - 1 - radius)
        {
            float dx = x - (width - 1 - radius);
            float dy = y - (height - 1 - radius);
            return radius - Mathf.Sqrt(dx * dx + dy * dy);
        }
        
        return Mathf.Min(distLeft, Mathf.Min(distRight, Mathf.Min(distBottom, distTop)));
    }
    
    /// <summary>
    /// Convertit une couleur hexadécimale en Color Unity
    /// </summary>
    private static Color HexToColor(string hex)
    {
        if (string.IsNullOrEmpty(hex)) return Color.white;
        
        hex = hex.TrimStart('#');
        
        if (hex.Length == 6)
        {
            hex += "FF";
        }
        
        if (hex.Length == 8)
        {
            byte r = Convert.ToByte(hex.Substring(0, 2), 16);
            byte g = Convert.ToByte(hex.Substring(2, 2), 16);
            byte b = Convert.ToByte(hex.Substring(4, 2), 16);
            byte a = Convert.ToByte(hex.Substring(6, 2), 16);
            return new Color(r / 255f, g / 255f, b / 255f, a / 255f);
        }
        
        return Color.white;
    }
    
    /// <summary>
    /// Ajoute un titre au header d'un panneau stylé
    /// </summary>
    public static TextMeshProUGUI AddHeaderTitle(StyledPanelResult panel, string title, float fontSize = 24, string colorHex = "#FFFFFF")
    {
        if (panel.headerObject == null)
        {
            Debug.LogWarning("[StyledPanelBuilder] Pas de header pour ajouter un titre");
            return null;
        }
        
        GameObject titleObj = new GameObject("Title");
        titleObj.transform.SetParent(panel.headerObject.transform, false);
        
        RectTransform titleRect = titleObj.AddComponent<RectTransform>();
        titleRect.anchorMin = Vector2.zero;
        titleRect.anchorMax = Vector2.one;
        titleRect.sizeDelta = Vector2.zero;
        titleRect.offsetMin = new Vector2(20, 0);
        titleRect.offsetMax = new Vector2(-20, 0);
        
        TextMeshProUGUI titleText = titleObj.AddComponent<TextMeshProUGUI>();
        titleText.text = title;
        titleText.fontSize = fontSize;
        titleText.color = HexToColor(colorHex);
        titleText.alignment = TextAlignmentOptions.Center;
        titleText.fontStyle = FontStyles.Bold;
        titleText.raycastTarget = false;
        
        // Essayer de charger la police Anton
        TMP_FontAsset antonFont = Resources.Load<TMP_FontAsset>("Fonts/Anton-Regular SDF");
        if (antonFont != null)
        {
            titleText.font = antonFont;
        }
        
        return titleText;
    }
    
    /// <summary>
    /// Ajoute un bouton de fermeture au header
    /// </summary>
    public static Button AddCloseButton(StyledPanelResult panel, Action onClose, float size = 40)
    {
        if (panel.headerObject == null)
        {
            Debug.LogWarning("[StyledPanelBuilder] Pas de header pour ajouter un bouton de fermeture");
            return null;
        }
        
        GameObject closeObj = new GameObject("CloseButton");
        closeObj.transform.SetParent(panel.headerObject.transform, false);
        
        RectTransform closeRect = closeObj.AddComponent<RectTransform>();
        closeRect.anchorMin = new Vector2(1, 0.5f);
        closeRect.anchorMax = new Vector2(1, 0.5f);
        closeRect.pivot = new Vector2(1, 0.5f);
        closeRect.sizeDelta = new Vector2(size, size);
        closeRect.anchoredPosition = new Vector2(-15, 0);
        
        Image closeImage = closeObj.AddComponent<Image>();
        closeImage.color = new Color(1, 1, 1, 0.8f);
        closeImage.raycastTarget = true;
        
        // Texte X
        GameObject xObj = new GameObject("X");
        xObj.transform.SetParent(closeObj.transform, false);
        RectTransform xRect = xObj.AddComponent<RectTransform>();
        xRect.anchorMin = Vector2.zero;
        xRect.anchorMax = Vector2.one;
        xRect.sizeDelta = Vector2.zero;
        
        TextMeshProUGUI xText = xObj.AddComponent<TextMeshProUGUI>();
        xText.text = "✕";
        xText.fontSize = size * 0.6f;
        xText.color = Color.white;
        xText.alignment = TextAlignmentOptions.Center;
        xText.raycastTarget = false;
        
        Button closeButton = closeObj.AddComponent<Button>();
        closeButton.targetGraphic = closeImage;
        closeButton.onClick.AddListener(() => onClose?.Invoke());
        
        return closeButton;
    }
}

