using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using TheIsland.Models;
using TheIsland.Network;

namespace TheIsland.UI
{
    /// <summary>
    /// Creates and manages floating UI above an agent (name, HP/Energy bars, speech bubble).
    /// Attach this to the Agent prefab - it will create all UI elements automatically.
    /// </summary>
    public class AgentUI : MonoBehaviour
    {
        #region Configuration
        [Header("UI Settings")]
        [SerializeField] private Vector3 uiOffset = new Vector3(0, 2.5f, 0);
        [SerializeField] private float uiScale = 0.01f;
        [SerializeField] private float speechDuration = 5f;

        [Header("Colors")]
        [SerializeField] private Color hpHighColor = new Color(0.3f, 0.9f, 0.3f);
        [SerializeField] private Color hpLowColor = new Color(0.9f, 0.3f, 0.3f);
        [SerializeField] private Color energyHighColor = new Color(1f, 0.8f, 0.2f);
        [SerializeField] private Color energyLowColor = new Color(1f, 0.5f, 0.1f);
        #endregion

        #region UI References
        private Canvas _canvas;
        private TextMeshProUGUI _nameLabel;
        private TextMeshProUGUI _personalityLabel;
        private Image _hpBarFill;
        private Image _energyBarFill;
        private TextMeshProUGUI _hpText;
        private TextMeshProUGUI _energyText;
        private GameObject _speechBubble;
        private TextMeshProUGUI _speechText;
        private GameObject _deathOverlay;
        #endregion

        #region State
        private int _agentId;
        private AgentData _currentData;
        private Coroutine _speechCoroutine;
        private Camera _mainCamera;
        #endregion

        #region Properties
        public int AgentId => _agentId;
        public AgentData CurrentData => _currentData;
        public bool IsAlive => _currentData?.IsAlive ?? false;
        #endregion

        #region Initialization
        private void Awake()
        {
            _mainCamera = Camera.main;
            CreateUI();
        }

        private void LateUpdate()
        {
            // Make UI face the camera (billboard effect)
            if (_canvas != null && _mainCamera != null)
            {
                _canvas.transform.LookAt(
                    _canvas.transform.position + _mainCamera.transform.rotation * Vector3.forward,
                    _mainCamera.transform.rotation * Vector3.up
                );
            }
        }

        public void Initialize(AgentData data)
        {
            _agentId = data.id;
            _currentData = data;
            gameObject.name = $"Agent_{data.id}_{data.name}";

            // Set name and personality
            if (_nameLabel != null) _nameLabel.text = data.name;
            if (_personalityLabel != null) _personalityLabel.text = $"({data.personality})";

            UpdateStats(data);
            Debug.Log($"[AgentUI] Initialized {data.name}");
        }
        #endregion

        #region UI Creation
        private void CreateUI()
        {
            // Create World Space Canvas
            var canvasObj = new GameObject("AgentCanvas");
            canvasObj.transform.SetParent(transform);
            canvasObj.transform.localPosition = uiOffset;
            canvasObj.transform.localScale = Vector3.one * uiScale;

            _canvas = canvasObj.AddComponent<Canvas>();
            _canvas.renderMode = RenderMode.WorldSpace;
            _canvas.sortingOrder = 10;

            var canvasRect = canvasObj.GetComponent<RectTransform>();
            canvasRect.sizeDelta = new Vector2(300, 200);

            // Create UI Panel
            var panel = CreatePanel(canvasObj.transform, "UIPanel", new Vector2(300, 150));

            // Name Label
            _nameLabel = CreateText(panel, "NameLabel", "Agent", 32, Color.white, FontStyles.Bold);
            SetRectPosition(_nameLabel.rectTransform, 0, 60, 280, 40);

            // Personality Label
            _personalityLabel = CreateText(panel, "PersonalityLabel", "(personality)", 18,
                new Color(0.7f, 0.7f, 0.7f), FontStyles.Italic);
            SetRectPosition(_personalityLabel.rectTransform, 0, 30, 280, 25);

            // HP Bar
            var hpBar = CreateBar(panel, "HPBar", "HP", hpHighColor, out _hpBarFill, out _hpText);
            SetRectPosition(hpBar, 0, -5, 250, 22);

            // Energy Bar
            var energyBar = CreateBar(panel, "EnergyBar", "Energy", energyHighColor, out _energyBarFill, out _energyText);
            SetRectPosition(energyBar, 0, -35, 250, 22);

            // Death Overlay
            _deathOverlay = CreateDeathOverlay(panel);

            // Speech Bubble (positioned above the main UI)
            _speechBubble = CreateSpeechBubble(canvasObj.transform);
            _speechBubble.SetActive(false);

            // Add collider for click detection if not present
            if (GetComponent<Collider>() == null)
            {
                var col = gameObject.AddComponent<CapsuleCollider>();
                col.height = 2f;
                col.radius = 0.5f;
                col.center = new Vector3(0, 1, 0);
            }
        }

        private GameObject CreatePanel(Transform parent, string name, Vector2 size)
        {
            var panel = new GameObject(name);
            panel.transform.SetParent(parent);
            panel.transform.localPosition = Vector3.zero;
            panel.transform.localRotation = Quaternion.identity;
            panel.transform.localScale = Vector3.one;

            var rect = panel.AddComponent<RectTransform>();
            rect.sizeDelta = size;
            rect.anchoredPosition = Vector2.zero;

            // Semi-transparent background
            var bg = panel.AddComponent<Image>();
            bg.color = new Color(0, 0, 0, 0.5f);

            return panel;
        }

        private TextMeshProUGUI CreateText(GameObject parent, string name, string text,
            float fontSize, Color color, FontStyles style = FontStyles.Normal)
        {
            var textObj = new GameObject(name);
            textObj.transform.SetParent(parent.transform);
            textObj.transform.localPosition = Vector3.zero;
            textObj.transform.localRotation = Quaternion.identity;
            textObj.transform.localScale = Vector3.one;

            var tmp = textObj.AddComponent<TextMeshProUGUI>();
            tmp.text = text;
            tmp.fontSize = fontSize;
            tmp.color = color;
            tmp.fontStyle = style;
            tmp.alignment = TextAlignmentOptions.Center;

            return tmp;
        }

        private RectTransform CreateBar(GameObject parent, string name, string label,
            Color fillColor, out Image fillImage, out TextMeshProUGUI valueText)
        {
            var barContainer = new GameObject(name);
            barContainer.transform.SetParent(parent.transform);
            barContainer.transform.localPosition = Vector3.zero;
            barContainer.transform.localRotation = Quaternion.identity;
            barContainer.transform.localScale = Vector3.one;

            var containerRect = barContainer.AddComponent<RectTransform>();

            // Background
            var bg = new GameObject("Background");
            bg.transform.SetParent(barContainer.transform);
            var bgImg = bg.AddComponent<Image>();
            bgImg.color = new Color(0.2f, 0.2f, 0.2f, 0.8f);
            var bgRect = bg.GetComponent<RectTransform>();
            bgRect.anchorMin = Vector2.zero;
            bgRect.anchorMax = Vector2.one;
            bgRect.offsetMin = Vector2.zero;
            bgRect.offsetMax = Vector2.zero;

            // Fill
            var fill = new GameObject("Fill");
            fill.transform.SetParent(barContainer.transform);
            fillImage = fill.AddComponent<Image>();
            fillImage.color = fillColor;
            var fillRect = fill.GetComponent<RectTransform>();
            fillRect.anchorMin = Vector2.zero;
            fillRect.anchorMax = new Vector2(1, 1);
            fillRect.pivot = new Vector2(0, 0.5f);
            fillRect.offsetMin = new Vector2(2, 2);
            fillRect.offsetMax = new Vector2(-2, -2);

            // Label + Value Text
            valueText = CreateText(barContainer, "Text", $"{label}: 100", 14, Color.white);
            var textRect = valueText.rectTransform;
            textRect.anchorMin = Vector2.zero;
            textRect.anchorMax = Vector2.one;
            textRect.offsetMin = Vector2.zero;
            textRect.offsetMax = Vector2.zero;

            return containerRect;
        }

        private GameObject CreateDeathOverlay(GameObject parent)
        {
            var overlay = new GameObject("DeathOverlay");
            overlay.transform.SetParent(parent.transform);
            overlay.transform.localPosition = Vector3.zero;
            overlay.transform.localRotation = Quaternion.identity;
            overlay.transform.localScale = Vector3.one;

            var rect = overlay.AddComponent<RectTransform>();
            rect.anchorMin = Vector2.zero;
            rect.anchorMax = Vector2.one;
            rect.offsetMin = Vector2.zero;
            rect.offsetMax = Vector2.zero;

            var img = overlay.AddComponent<Image>();
            img.color = new Color(0.3f, 0f, 0f, 0.7f);

            var deathText = CreateText(overlay, "DeathText", "DEAD", 28, Color.red, FontStyles.Bold);
            deathText.rectTransform.anchorMin = Vector2.zero;
            deathText.rectTransform.anchorMax = Vector2.one;
            deathText.rectTransform.offsetMin = Vector2.zero;
            deathText.rectTransform.offsetMax = Vector2.zero;

            overlay.SetActive(false);
            return overlay;
        }

        private GameObject CreateSpeechBubble(Transform parent)
        {
            var bubble = new GameObject("SpeechBubble");
            bubble.transform.SetParent(parent);
            bubble.transform.localPosition = new Vector3(0, 100, 0); // Above main UI
            bubble.transform.localRotation = Quaternion.identity;
            bubble.transform.localScale = Vector3.one;

            var rect = bubble.AddComponent<RectTransform>();
            rect.sizeDelta = new Vector2(350, 80);

            // Bubble background
            var bg = bubble.AddComponent<Image>();
            bg.color = new Color(1f, 1f, 1f, 0.95f);

            // Speech text
            _speechText = CreateText(bubble, "SpeechText", "", 20, new Color(0.2f, 0.2f, 0.2f));
            _speechText.alignment = TextAlignmentOptions.Center;
            _speechText.textWrappingMode = TextWrappingModes.Normal;
            var textRect = _speechText.rectTransform;
            textRect.anchorMin = Vector2.zero;
            textRect.anchorMax = Vector2.one;
            textRect.offsetMin = new Vector2(15, 10);
            textRect.offsetMax = new Vector2(-15, -10);

            // Bubble tail (triangle pointing down)
            var tail = new GameObject("Tail");
            tail.transform.SetParent(bubble.transform);
            var tailRect = tail.AddComponent<RectTransform>();
            tailRect.anchoredPosition = new Vector2(0, -35);
            tailRect.sizeDelta = new Vector2(20, 15);

            return bubble;
        }

        private void SetRectPosition(RectTransform rect, float x, float y, float width, float height)
        {
            rect.anchoredPosition = new Vector2(x, y);
            rect.sizeDelta = new Vector2(width, height);
        }
        #endregion

        #region Stats Update
        public void UpdateStats(AgentData data)
        {
            _currentData = data;

            // Update HP
            float hpPercent = data.hp / 100f;
            if (_hpBarFill != null)
            {
                _hpBarFill.rectTransform.anchorMax = new Vector2(hpPercent, 1);
                _hpBarFill.color = Color.Lerp(hpLowColor, hpHighColor, hpPercent);
            }
            if (_hpText != null)
            {
                _hpText.text = $"HP: {data.hp}";
            }

            // Update Energy
            float energyPercent = data.energy / 100f;
            if (_energyBarFill != null)
            {
                _energyBarFill.rectTransform.anchorMax = new Vector2(energyPercent, 1);
                _energyBarFill.color = Color.Lerp(energyLowColor, energyHighColor, energyPercent);
            }
            if (_energyText != null)
            {
                _energyText.text = $"Energy: {data.energy}";
            }

            // Update death state
            if (!data.IsAlive)
            {
                OnDeath();
            }
            else
            {
                OnAlive();
            }
        }

        private void OnDeath()
        {
            if (_deathOverlay != null) _deathOverlay.SetActive(true);
            HideSpeech();

            // Gray out the character
            var renderers = GetComponentsInChildren<Renderer>();
            foreach (var r in renderers)
            {
                if (r.material != null)
                {
                    r.material.color = new Color(0.3f, 0.3f, 0.3f);
                }
            }
        }

        private void OnAlive()
        {
            if (_deathOverlay != null) _deathOverlay.SetActive(false);

            // Restore color
            var renderers = GetComponentsInChildren<Renderer>();
            foreach (var r in renderers)
            {
                if (r.material != null)
                {
                    r.material.color = Color.white;
                }
            }
        }
        #endregion

        #region Speech Bubble
        public void ShowSpeech(string text)
        {
            if (_speechBubble == null || !IsAlive) return;

            if (_speechCoroutine != null)
            {
                StopCoroutine(_speechCoroutine);
            }

            _speechText.text = text;
            _speechBubble.SetActive(true);

            _speechCoroutine = StartCoroutine(HideSpeechAfterDelay());
            Debug.Log($"[AgentUI] {_currentData?.name} says: \"{text}\"");
        }

        private IEnumerator HideSpeechAfterDelay()
        {
            yield return new WaitForSeconds(speechDuration);
            HideSpeech();
        }

        public void HideSpeech()
        {
            if (_speechBubble != null)
            {
                _speechBubble.SetActive(false);
            }
        }
        #endregion

        #region Interaction
        private void OnMouseDown()
        {
            if (!IsAlive)
            {
                Debug.Log($"[AgentUI] Cannot feed dead agent: {_currentData?.name}");
                return;
            }

            NetworkManager.Instance.FeedAgent(_currentData.name);
            Debug.Log($"[AgentUI] Clicked to feed: {_currentData?.name}");
        }
        #endregion
    }
}
