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

public class MapPopup : MonoBehaviour
{
    private RectTransform rectTransform;
    private CanvasGroup canvasGroup;
    private VideoPlayer videoPlayer;
    private RenderTexture renderTexture;
    private RawImage videoDisplay;
    private TextMeshProUGUI popupText;
    private Button clickButton;
    private Image circularMask;
    private GameObject videoContainer;

    private MapZone currentZone;
    private MapManager mapManager;
    private MapPopupConfig config;

    public void Initialize(MapPopupConfig popupConfig, MapManager manager)
    {
        rectTransform = GetComponent<RectTransform>();
        canvasGroup = GetComponent<CanvasGroup>();
        config = popupConfig;
        mapManager = manager;
        canvasGroup.alpha = 0f;
        // NE PAS désactiver ici
    }

    public void SetupPopupContent(string videoUrl, string text, string levelId, bool clickable, string buttonText)
    {
        // Créer un MapZone temporaire
        currentZone = new MapZone
        {
            popupVideo = videoUrl,
            popupText = text,
            targetLevelId = levelId,
            popupClickable = clickable,
            buttonText = buttonText
        };

        // Créer le contenu directement (pas d'appel récursif)
        foreach (Transform child in transform)
        {
            Destroy(child.gameObject);
        }

        CreateCircularBackground();
        CreateVideoPlayer();
        CreateTextArea();

        if (currentZone.popupClickable)
        {
            CreatePlayButton();
        }

        else
        {
            Debug.Log($"[SetupPopupContent] Zone NON clickable, pas de bouton");
        }



    }

    public void Show()
    {
        if (currentZone == null) return;

        // Ne PAS réactiver ici, déjà actif
        StartCoroutine(ShowPopupCoroutine(Vector2.zero));
    }

    IEnumerator ShowPopupCoroutine(Vector2 screenPosition)
    {
        yield return new WaitForSeconds(config.showDelay);

        float elapsed = 0f;
        while (elapsed < config.fadeSpeed)
        {
            elapsed += Time.deltaTime;
            canvasGroup.alpha = Mathf.Lerp(0f, 1f, elapsed / config.fadeSpeed);
            yield return null;
        }
        canvasGroup.alpha = 1f;
    }





    void CreateCircularBackground()
    {
        GameObject bgObj = new GameObject("CircularBackground");
        bgObj.transform.SetParent(transform, false);

        RectTransform bgRect = bgObj.AddComponent<RectTransform>();
        bgRect.anchorMin = Vector2.zero;
        bgRect.anchorMax = Vector2.one;
        bgRect.offsetMin = Vector2.zero;
        bgRect.offsetMax = Vector2.zero;

        circularMask = bgObj.AddComponent<Image>();

        Texture2D circleTexture = CreateCircleTexture(512);
        Sprite circleSprite = Sprite.Create(circleTexture,
            new Rect(0, 0, circleTexture.width, circleTexture.height),
            new Vector2(0.5f, 0.5f));

        circularMask.sprite = circleSprite;
        circularMask.raycastTarget = false;

        if (ColorUtility.TryParseHtmlString(config.backgroundColor, out Color bgColor))
        {
            circularMask.color = bgColor;
        }

        Outline outline = bgObj.AddComponent<Outline>();
        if (ColorUtility.TryParseHtmlString(config.borderColor, out Color borderColor))
        {
            outline.effectColor = borderColor;
        }
        outline.effectDistance = new Vector2(config.borderWidth, -config.borderWidth);
    }

    Texture2D CreateCircleTexture(int size)
    {
        Texture2D texture = new Texture2D(size, size, TextureFormat.RGBA32, false);
        Color[] pixels = new Color[size * size];

        float center = size / 2f;
        float radius = size / 2f;

        for (int y = 0; y < size; y++)
        {
            for (int x = 0; x < size; x++)
            {
                float distance = Vector2.Distance(new Vector2(x, y), new Vector2(center, center));

                if (distance <= radius)
                {
                    float alpha = 1f - Mathf.Clamp01((distance - radius + 2f) / 2f);
                    pixels[y * size + x] = new Color(1f, 1f, 1f, alpha);
                }
                else
                {
                    pixels[y * size + x] = Color.clear;
                }
            }
        }

        texture.SetPixels(pixels);
        texture.Apply();
        texture.filterMode = FilterMode.Bilinear;

        return texture;
    }

    void CreateTextArea()
    {
        if (string.IsNullOrEmpty(currentZone.popupText))
        {
            return;
        }

        GameObject maskContainer = new GameObject("TextMaskContainer");
        maskContainer.transform.SetParent(transform, false);

        RectTransform maskRect = maskContainer.AddComponent<RectTransform>();
        maskRect.anchorMin = Vector2.zero;
        maskRect.anchorMax = Vector2.one;
        maskRect.offsetMin = Vector2.zero;
        maskRect.offsetMax = Vector2.zero;

        Mask mask = maskContainer.AddComponent<Mask>();
        mask.showMaskGraphic = false;

        Image maskImage = maskContainer.AddComponent<Image>();
        Texture2D circleTex = CreateCircleTexture(512);
        Sprite circleSprite = Sprite.Create(circleTex,
            new Rect(0, 0, circleTex.width, circleTex.height),
            new Vector2(0.5f, 0.5f));
        maskImage.sprite = circleSprite;
        maskImage.color = Color.white;

        GameObject textContainer = new GameObject("TextContainer");
        textContainer.transform.SetParent(maskContainer.transform, false);

        RectTransform textRect = textContainer.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.zero;
        textRect.pivot = new Vector2(0.5f, 1f);

        float popupSize = rectTransform.sizeDelta.x;
        float textWidth = popupSize * 0.9f;

        // NOUVEAU : Utiliser textHeight depuis config
        textRect.sizeDelta = new Vector2(textWidth, config.textHeight);
        textRect.anchoredPosition = new Vector2(popupSize * 0.5f, popupSize - 10f);

        Image textBg = textContainer.AddComponent<Image>();
        if (ColorUtility.TryParseHtmlString(config.textBackgroundColor, out Color textBgColor))
        {
            textBg.color = textBgColor;
        }

        GameObject textObj = new GameObject("PopupText");
        textObj.transform.SetParent(textContainer.transform, false);

        RectTransform textObjRect = textObj.AddComponent<RectTransform>();
        textObjRect.anchorMin = Vector2.zero;
        textObjRect.anchorMax = Vector2.one;

        // NOUVEAU : Padding configurable
        textObjRect.offsetMin = new Vector2(config.textPaddingLeft, config.textPaddingBottom);
        textObjRect.offsetMax = new Vector2(-config.textPaddingRight, -config.textPaddingTop);

        popupText = textObj.AddComponent<TextMeshProUGUI>();
        popupText.text = currentZone.popupText;
        popupText.fontSize = config.textFontSize;
        popupText.alignment = TextAlignmentOptions.Center;
        popupText.textWrappingMode = TMPro.TextWrappingModes.Normal;

        if (ColorUtility.TryParseHtmlString(config.textColor, out Color textColor))
        {
            popupText.color = textColor;
        }
    }

    void CreateVideoPlayer()
    {
        videoContainer = new GameObject("VideoContainer");
        videoContainer.transform.SetParent(transform, false);

        RectTransform videoRect = videoContainer.AddComponent<RectTransform>();
        videoRect.anchorMin = new Vector2(0.5f, 0.5f);
        videoRect.anchorMax = new Vector2(0.5f, 0.5f);
        videoRect.pivot = new Vector2(0.5f, 0.5f);

        float videoSize = rectTransform.sizeDelta.x * 1f;
        videoRect.sizeDelta = new Vector2(videoSize, videoSize);

        float yOffset = rectTransform.sizeDelta.y * 0f;
        videoRect.anchoredPosition = new Vector2(0f, yOffset);

        Mask videoMask = videoContainer.AddComponent<Mask>();
        videoMask.showMaskGraphic = false;

        Image maskImage = videoContainer.AddComponent<Image>();
        Texture2D circleTex = CreateCircleTexture(512);
        Sprite circleSprite = Sprite.Create(circleTex,
            new Rect(0, 0, circleTex.width, circleTex.height),
            new Vector2(0.5f, 0.5f));
        maskImage.sprite = circleSprite;
        maskImage.raycastTarget = false;
        maskImage.color = Color.white;

        int rtSize = 1024;
        renderTexture = new RenderTexture(rtSize, rtSize, 0);
        renderTexture.Create();

        GameObject videoPlayerObj = new GameObject("VideoPlayer");
        videoPlayerObj.transform.SetParent(videoContainer.transform, false);

        videoPlayer = videoPlayerObj.AddComponent<VideoPlayer>();
        videoPlayer.playOnAwake = false;
        videoPlayer.renderMode = VideoRenderMode.RenderTexture;
        videoPlayer.targetTexture = renderTexture;
        videoPlayer.isLooping = true;
        videoPlayer.aspectRatio = VideoAspectRatio.FitInside;
        videoPlayer.audioOutputMode = VideoAudioOutputMode.None;
        videoPlayer.url = currentZone.popupVideo;
        videoPlayer.Prepare();
        videoPlayer.prepareCompleted += OnVideoPrepared;

        GameObject rawImageObj = new GameObject("VideoDisplay");
        rawImageObj.transform.SetParent(videoContainer.transform, false);

        RectTransform rawImageRect = rawImageObj.AddComponent<RectTransform>();
        rawImageRect.anchorMin = new Vector2(0.5f, 0.5f);
        rawImageRect.anchorMax = new Vector2(0.5f, 0.5f);
        rawImageRect.pivot = new Vector2(0.5f, 0.5f);

        float displaySize = videoSize * 1.0f;
        rawImageRect.sizeDelta = new Vector2(displaySize, displaySize);
        rawImageRect.anchoredPosition = Vector2.zero;

        videoDisplay = rawImageObj.AddComponent<RawImage>();
        videoDisplay.texture = renderTexture;
    }

    void OnVideoPrepared(VideoPlayer source)
    {
        videoPlayer.Play();

        if (videoDisplay != null)
        {
            RectTransform rt = videoDisplay.GetComponent<RectTransform>();
            float size = rt.sizeDelta.x;
            rt.sizeDelta = new Vector2(size, size);
        }
    }

    void CreatePlayButton()
    {
        GameObject buttonObj = new GameObject("PlayButton");
        buttonObj.transform.SetParent(transform, false);

        RectTransform buttonRect = buttonObj.AddComponent<RectTransform>();
        buttonRect.anchorMin = new Vector2(0.5f, 0f);
        buttonRect.anchorMax = new Vector2(0.5f, 0f);
        buttonRect.pivot = new Vector2(0.5f, 0f);
        
        // Obtenir le style de bouton depuis general-config (obligatoire maintenant)
        ButtonStyleConfig buttonStyle = GetButtonStyleConfig();
        
        // Taille personnalisée pour les boutons des popups (plus étroit)
        float buttonWidth = 180f;   // Largeur réduite
        float buttonHeight = 50f;   // Hauteur compacte
        buttonRect.sizeDelta = new Vector2(buttonWidth, buttonHeight);
        buttonRect.anchoredPosition = new Vector2(0, config.buttonBottomMargin);

        Image buttonImage = buttonObj.AddComponent<Image>();
        
        // Créer un sprite avec dégradé et bordure arrondie (comme validationDefault)
        if (buttonStyle?.gradient != null && buttonStyle.gradient.enabled)
        {
            Color startColor = Color.white;
            Color endColor = Color.white;
            Color borderColor = Color.white;
            
            ColorUtility.TryParseHtmlString(buttonStyle.gradient.startColor ?? "#CE9BFD", out startColor);
            ColorUtility.TryParseHtmlString(buttonStyle.gradient.endColor ?? "#9A2DFF", out endColor);
            ColorUtility.TryParseHtmlString(buttonStyle.borderColor ?? "#f5ece5", out borderColor);
            
            // BorderRadius adapté à la taille du bouton (moitié de la hauteur pour un effet pilule)
            float borderRadius = buttonHeight / 2f;
            float borderWidth = 3f;
            
            // Créer le sprite avec dégradé
            buttonImage.sprite = CreateGradientButtonSprite((int)buttonWidth, (int)buttonHeight, borderRadius, startColor, endColor, borderColor, borderWidth);
            buttonImage.color = Color.white; // Le sprite contient déjà les couleurs
            buttonImage.type = Image.Type.Simple;
        }
        else
        {
            buttonImage.color = new Color(0.4f, 0.3f, 0.5f, 1f); // Fallback violet
        }
        
        // Ajouter une ombre pour le relief
        if (buttonStyle?.shadow != null && buttonStyle.shadow.enabled)
        {
            Shadow shadow = buttonObj.AddComponent<Shadow>();
            if (ColorUtility.TryParseHtmlString(buttonStyle.shadow.color ?? "#00000040", out Color shadowColor))
            {
                shadow.effectColor = shadowColor;
            }
            shadow.effectDistance = new Vector2(buttonStyle.shadow.offsetX, -buttonStyle.shadow.offsetY);
        }
        else
        {
            // Ombre par défaut
            Shadow shadow = buttonObj.AddComponent<Shadow>();
            shadow.effectColor = new Color(0, 0, 0, 0.25f);
            shadow.effectDistance = new Vector2(0, -6);
        }

        Button button = buttonObj.AddComponent<Button>();
        button.targetGraphic = buttonImage;
        button.onClick.AddListener(() =>
        {
            OnPopupClick();
        });

        GameObject textObj = new GameObject("ButtonText");
        textObj.transform.SetParent(buttonObj.transform, false);

        RectTransform textRect = textObj.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.offsetMin = Vector2.zero;
        textRect.offsetMax = Vector2.zero;

        TextMeshProUGUI buttonTextComp = textObj.AddComponent<TextMeshProUGUI>();
        
        // Texte du bouton (priorité: zone > config map > general-config > default)
        string textToDisplay = !string.IsNullOrEmpty(currentZone.buttonText) ? currentZone.buttonText : config.buttonText;
        if (string.IsNullOrEmpty(textToDisplay) && GeneralConfigManager.Instance != null)
        {
            var popupConfig = GeneralConfigManager.Instance.GetDefaultPopupConfig();
            if (popupConfig != null && !string.IsNullOrEmpty(popupConfig.buttonText))
            {
                textToDisplay = popupConfig.buttonText;
            }
        }
        if (string.IsNullOrEmpty(textToDisplay)) textToDisplay = "JOUER";
        
        buttonTextComp.text = textToDisplay;
        Debug.Log($"[CreatePlayButton] Texte affiché: '{textToDisplay}'");
        
        // Appliquer le style du texte depuis le buttonStyle
        if (buttonStyle?.text != null)
        {
            buttonTextComp.fontSize = 20f; // Taille adaptée au bouton compact
            if (ColorUtility.TryParseHtmlString(buttonStyle.text.color, out Color styleTextColor))
            {
                buttonTextComp.color = styleTextColor;
            }
            else
            {
                buttonTextComp.color = Color.white;
            }
            // Essayer de charger la police si spécifiée
            if (!string.IsNullOrEmpty(buttonStyle.text.fontFamily))
            {
                TMP_FontAsset font = Resources.Load<TMP_FontAsset>($"Fonts/{buttonStyle.text.fontFamily}");
                if (font != null)
                {
                    buttonTextComp.font = font;
                }
            }
        }
        else
        {
            buttonTextComp.fontSize = 20f;
            buttonTextComp.color = Color.white;
        }
        
        buttonTextComp.alignment = TextAlignmentOptions.Center;
        buttonTextComp.verticalAlignment = VerticalAlignmentOptions.Middle;
    }
    
    ButtonStyleConfig GetButtonStyleConfig()
    {
        // Utiliser le buttonStyle depuis la config (défini dans general-config.json defaultPopupConfig)
        string styleName = !string.IsNullOrEmpty(config?.buttonStyle) ? config.buttonStyle : "validationDefault";
        
        if (GeneralConfigManager.Instance != null)
        {
            ButtonStyleConfig style = GeneralConfigManager.Instance.GetButtonStyle(styleName);
            if (style != null)
            {
                return style;
            }
        }
        
        return null;
    }
    void OnPopupClick()
    {
        if (mapManager != null && currentZone != null)
        {
            Destroy(gameObject);
            mapManager.LaunchLevel(currentZone.targetLevelId);
        }
    }

    public void Hide()
    {
        if (!gameObject.activeInHierarchy)
        {
            return;
        }

        StartCoroutine(HidePopupCoroutine());
    }

    IEnumerator HidePopupCoroutine()
    {
        float elapsed = 0f;
        while (elapsed < config.fadeSpeed)
        {
            elapsed += Time.deltaTime;
            canvasGroup.alpha = Mathf.Lerp(1f, 0f, elapsed / config.fadeSpeed);
            yield return null;
        }
        canvasGroup.alpha = 0f;

        if (videoPlayer != null)
        {
            videoPlayer.Stop();
        }

        gameObject.SetActive(false);
    }

    void OnDestroy()
    {
        if (renderTexture != null)
        {
            renderTexture.Release();
            Destroy(renderTexture);
        }
    }
    
    /// <summary>
    /// Crée un sprite avec dégradé et bordure arrondie pour le bouton
    /// </summary>
    Sprite CreateGradientButtonSprite(int width, int height, float radius, Color startColor, Color endColor, Color borderColor, float borderWidth)
    {
        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;
                bool isBorder = false;
                
                // Vérifier si on est dans la bordure
                if (x < borderWidth || x >= width - borderWidth || y < borderWidth || y >= height - borderWidth)
                {
                    isBorder = true;
                }

                // Coins arrondis
                float distanceFromCorner = float.MaxValue;
                
                // Coin supérieur gauche
                if (x < radius && y > height - radius)
                {
                    float dx = radius - x;
                    float dy = (height - radius) - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }
                // Coin supérieur droit
                else if (x > width - radius && y > height - radius)
                {
                    float dx = x - (width - radius);
                    float dy = (height - radius) - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }
                // Coin inférieur gauche
                else if (x < radius && y < radius)
                {
                    float dx = radius - x;
                    float dy = radius - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }
                // Coin inférieur droit
                else if (x > width - radius && y < radius)
                {
                    float dx = x - (width - radius);
                    float dy = radius - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }

                Color pixelColor;
                if (isBorder && alpha > 0)
                {
                    pixelColor = borderColor;
                }
                else
                {
                    // Dégradé vertical (du bas vers le haut)
                    float t = (float)y / height;
                    pixelColor = Color.Lerp(endColor, startColor, t);
                }
                
                pixelColor.a *= alpha;
                pixels[y * width + x] = pixelColor;
            }
        }

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

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