using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using EventsAppQuest.Application.Services;
using EventsAppQuest.Core;
using EventsAppQuest.Domain.Models;

namespace EventsAppQuest.Presentation
{
    /// <summary>
    /// Exibe o plano lógico do espaço: slots do layout e itens do showroom alocados em cada um.
    /// Permite realocação automática e mover item para outro slot compatível (preparação para MR).
    /// Usa referências explícitas a containers (sem Find por nome).
    /// </summary>
    public class SpaceLayoutView : MonoBehaviour
    {
        private const string Title = "Plano Lógico do Espaço / Layout Atual";
        private const string NenhumProjeto = "Nenhum projeto iniciado. Inicie um projeto para ver o layout.";
        private const string RealocarAutomaticamente = "Realocar automaticamente";
        private const string NaoAlocados = "Não alocados";
        private const string MoverPara = "Mover para";

        private AppSession _session;
        private ISpaceLayoutService _layoutService;
        private IShowroomService _showroomService;
        private Transform _contentRoot;
        private Transform _slotsRoot;
        private Transform _unassignedRoot;
        private Font _font;

        private void Start()
        {
            _session = ServiceRegistry.Instance.Get<AppSession>();
            _layoutService = ServiceRegistry.Instance.Get<ISpaceLayoutService>();
            _showroomService = ServiceRegistry.Instance.Get<IShowroomService>();
            if (_session != null)
                _session.OnSessionChanged += UpdateContent;

            _font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
            BuildUI();
            UpdateContent();
        }

        private void OnDestroy()
        {
            if (_session != null)
                _session.OnSessionChanged -= UpdateContent;
        }

        private void BuildUI()
        {
            var layout = gameObject.GetComponent<VerticalLayoutGroup>();
            if (layout == null)
            {
                layout = gameObject.AddComponent<VerticalLayoutGroup>();
                layout.spacing = 8;
                layout.padding = new RectOffset(12, 12, 12, 12);
                layout.childForceExpandHeight = false;
                layout.childForceExpandWidth = true;
            }

            var titleGo = new GameObject("Title");
            titleGo.transform.SetParent(transform, false);
            var titleRt = titleGo.AddComponent<RectTransform>();
            titleRt.sizeDelta = new Vector2(0, 24);
            var titleText = titleGo.AddComponent<Text>();
            titleText.text = Title;
            titleText.font = _font;
            titleText.fontSize = 18;
            titleText.fontStyle = FontStyle.Bold;

            _contentRoot = new GameObject("LayoutContentRoot").transform;
            _contentRoot.SetParent(transform, false);
            var contentLE = _contentRoot.gameObject.AddComponent<LayoutElement>();
            contentLE.preferredHeight = 260;
            contentLE.flexibleHeight = 1;
            var contentVlg = _contentRoot.gameObject.AddComponent<VerticalLayoutGroup>();
            contentVlg.spacing = 10;
            contentVlg.childForceExpandHeight = false;
            contentVlg.childForceExpandWidth = true;

            _slotsRoot = new GameObject("SlotsRoot").transform;
            _slotsRoot.SetParent(_contentRoot, false);
            var slotsLE = _slotsRoot.gameObject.AddComponent<LayoutElement>();
            slotsLE.flexibleHeight = 1;
            var slotsVlg = _slotsRoot.gameObject.AddComponent<VerticalLayoutGroup>();
            slotsVlg.spacing = 6;
            slotsVlg.childForceExpandHeight = false;
            slotsVlg.childForceExpandWidth = true;

            _unassignedRoot = new GameObject("UnassignedRoot").transform;
            _unassignedRoot.SetParent(_contentRoot, false);
            var unassignedLE = _unassignedRoot.gameObject.AddComponent<LayoutElement>();
            unassignedLE.preferredHeight = 60;
            var unassignedVlg = _unassignedRoot.gameObject.AddComponent<VerticalLayoutGroup>();
            unassignedVlg.spacing = 4;
            unassignedVlg.childForceExpandHeight = false;
            unassignedVlg.childForceExpandWidth = true;

            var buttonGo = new GameObject("ReassignButton");
            buttonGo.transform.SetParent(transform, false);
            var buttonRt = buttonGo.AddComponent<RectTransform>();
            buttonRt.sizeDelta = new Vector2(200, 32);
            var buttonLE = buttonGo.AddComponent<LayoutElement>();
            buttonLE.preferredHeight = 32;
            buttonLE.preferredWidth = 200;
            var button = buttonGo.AddComponent<Button>();
            var buttonImage = buttonGo.AddComponent<Image>();
            buttonImage.color = new Color(0.3f, 0.6f, 0.9f, 1f);
            var buttonTextGo = new GameObject("Text");
            buttonTextGo.transform.SetParent(buttonGo.transform, false);
            var buttonText = buttonTextGo.AddComponent<Text>();
            buttonText.text = RealocarAutomaticamente;
            buttonText.font = _font;
            buttonText.fontSize = 14;
            buttonText.alignment = TextAnchor.MiddleCenter;
            var textRt = buttonTextGo.GetComponent<RectTransform>();
            textRt.anchorMin = Vector2.zero;
            textRt.anchorMax = Vector2.one;
            textRt.offsetMin = Vector2.zero;
            textRt.offsetMax = Vector2.zero;
            button.onClick.AddListener(OnReassignClicked);
        }

        private void OnReassignClicked()
        {
            _session?.ReassignLayout();
        }

        private void UpdateContent()
        {
            ClearChildren(_slotsRoot);
            ClearChildren(_unassignedRoot);

            var project = _session?.CurrentProject;
            if (project == null)
            {
                var msg = new GameObject("Msg");
                msg.transform.SetParent(_slotsRoot, false);
                msg.AddComponent<RectTransform>().sizeDelta = new Vector2(0, 22);
                var t = msg.AddComponent<Text>();
                t.text = NenhumProjeto;
                t.font = _font;
                t.fontSize = 14;
                return;
            }

            if (_layoutService == null || _showroomService == null) return;

            var slots = _layoutService.GetBySpaceId(project.SpaceId);
            var assignments = project.ItemSlotAssignments ?? new List<ItemSlotAssignment>();
            var itemToSlot = new Dictionary<string, string>();
            foreach (var a in assignments)
                if (!string.IsNullOrEmpty(a.ShowroomItemId))
                    itemToSlot[a.ShowroomItemId] = a.SlotId;

            foreach (var slot in slots)
            {
                var itemsInSlot = new List<(ShowroomItem item, string slotId)>();
                foreach (var a in assignments)
                    if (a.SlotId == slot.Id)
                    {
                        var item = _showroomService.GetById(a.ShowroomItemId);
                        if (item != null)
                            itemsInSlot.Add((item, slot.Id));
                    }

                AppendSlotBlock(_slotsRoot, slot, itemsInSlot, project);
            }

            var unassigned = new List<ShowroomItem>();
            foreach (var itemId in project.ShowroomItemIds ?? new List<string>())
            {
                if (itemToSlot.ContainsKey(itemId)) continue;
                var item = _showroomService.GetById(itemId);
                if (item != null) unassigned.Add(item);
            }

            if (unassigned.Count > 0)
            {
                var label = new GameObject("UnassignedLabel");
                label.transform.SetParent(_unassignedRoot, false);
                label.AddComponent<RectTransform>().sizeDelta = new Vector2(0, 18);
                var labelText = label.AddComponent<Text>();
                labelText.text = NaoAlocados;
                labelText.font = _font;
                labelText.fontSize = 13;
                labelText.fontStyle = FontStyle.Bold;
                foreach (var item in unassigned)
                    AppendItemRow(_unassignedRoot, item, null, project, isUnassigned: true);
            }
        }

        private void AppendSlotBlock(Transform parent, SpaceLayoutSlot slot, List<(ShowroomItem item, string slotId)> items, EventProject project)
        {
            var block = new GameObject($"Slot_{slot.Id}");
            block.transform.SetParent(parent, false);
            var blockRt = block.AddComponent<RectTransform>();
            blockRt.sizeDelta = new Vector2(0, 0);
            var blockVlg = block.AddComponent<VerticalLayoutGroup>();
            blockVlg.spacing = 4;
            blockVlg.padding = new RectOffset(8, 4, 4, 4);
            blockVlg.childForceExpandHeight = false;
            blockVlg.childForceExpandWidth = true;

            var bg = block.AddComponent<Image>();
            bg.color = new Color(1f, 1f, 1f, 0.6f);

            var slotLabel = new GameObject("SlotLabel");
            slotLabel.transform.SetParent(block.transform, false);
            slotLabel.AddComponent<RectTransform>().sizeDelta = new Vector2(0, 20);
            var slotText = slotLabel.AddComponent<Text>();
            slotText.text = slot.Name + (slot.IsPrimary ? " (principal)" : "");
            slotText.font = _font;
            slotText.fontSize = 14;
            slotText.fontStyle = FontStyle.Bold;

            foreach (var (item, _) in items)
                AppendItemRow(block.transform, item, slot.Id, project, isUnassigned: false);
        }

        private void AppendItemRow(Transform parent, ShowroomItem item, string currentSlotId, EventProject project, bool isUnassigned)
        {
            var row = new GameObject($"Item_{item.Id}");
            row.transform.SetParent(parent, false);
            var rowRt = row.AddComponent<RectTransform>();
            rowRt.sizeDelta = new Vector2(0, 24);
            var rowHLg = row.AddComponent<HorizontalLayoutGroup>();
            rowHLg.spacing = 8;
            rowHLg.childForceExpandWidth = false;
            rowHLg.childForceExpandHeight = true;

            var nameLabel = new GameObject("Name");
            nameLabel.transform.SetParent(row.transform, false);
            nameLabel.AddComponent<RectTransform>().sizeDelta = new Vector2(200, 22);
            var nameLE = nameLabel.AddComponent<LayoutElement>();
            nameLE.preferredWidth = 200;
            nameLE.flexibleWidth = 1;
            var nameText = nameLabel.AddComponent<Text>();
            nameText.text = item.Name;
            nameText.font = _font;
            nameText.fontSize = 13;

            if (_layoutService != null && !string.IsNullOrEmpty(project.SpaceId))
            {
                var compatible = _layoutService.GetCompatibleSlots(project.SpaceId, item.PlacementZone, item.SpatialAnchorType);
                if (compatible == null || compatible.Count == 0)
                    compatible = _layoutService.GetCompatibleSlots(project.SpaceId, item.PlacementZone, null);
                if (compatible != null && compatible.Count > 0)
                {
                    var moveBtn = new GameObject("MoverBtn");
                    moveBtn.transform.SetParent(row.transform, false);
                    moveBtn.AddComponent<RectTransform>().sizeDelta = new Vector2(90, 22);
                    var moveLE = moveBtn.AddComponent<LayoutElement>();
                    moveLE.preferredWidth = 90;
                    moveLE.preferredHeight = 22;
                    var moveButton = moveBtn.AddComponent<Button>();
                    moveBtn.AddComponent<Image>().color = new Color(0.85f, 0.88f, 0.92f, 1f);
                    var moveTextGo = new GameObject("Text");
                    moveTextGo.transform.SetParent(moveBtn.transform, false);
                    var moveTextRt = moveTextGo.AddComponent<RectTransform>();
                    moveTextRt.anchorMin = Vector2.zero;
                    moveTextRt.anchorMax = Vector2.one;
                    moveTextRt.offsetMin = Vector2.zero;
                    moveTextRt.offsetMax = Vector2.zero;
                    var moveText = moveTextGo.AddComponent<Text>();
                    moveText.text = MoverPara;
                    moveText.font = _font;
                    moveText.fontSize = 11;
                    moveText.alignment = TextAnchor.MiddleCenter;

                    var slotIds = new List<string>();
                    foreach (var s in compatible) slotIds.Add(s.Id);
                    var itemIdCapture = item.Id;
                    var currentIdx = currentSlotId != null ? slotIds.IndexOf(currentSlotId) : -1;
                    moveButton.onClick.AddListener(() =>
                    {
                        if (slotIds.Count == 0) return;
                        var nextIdx = currentIdx < 0 ? 0 : (currentIdx + 1) % slotIds.Count;
                        var newSlotId = slotIds[nextIdx];
                        _session?.AssignItemToSlot(itemIdCapture, newSlotId);
                    });
                }
            }
        }

        private static void ClearChildren(Transform root)
        {
            if (root == null) return;
            for (var i = root.childCount - 1; i >= 0; i--)
                Object.Destroy(root.GetChild(i).gameObject);
        }
    }
}
