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

namespace EventsAppQuest.Presentation
{
    /// <summary>
    /// Exibe itens do showroom/proposta agrupados por tipo (Decoração, Buffet, Iluminação, etc.).
    /// Permite adicionar e remover itens. Usa referencias explicitas a containers (sem Find por nome).
    /// </summary>
    public class ShowroomView : MonoBehaviour
    {
        private const string Title = "Showroom / Proposta Atual";
        private const string NenhumProjeto = "Nenhum projeto iniciado.";
        private const string ItensAtuais = "Itens na proposta";
        private const string ItensDisponiveis = "Itens opcionais disponíveis";
        private const string Padrao = " (padrão)";
        private const string Remover = "Remover";
        private const string Add = "Adicionar";

        private static readonly ShowroomItemType[] TypeOrder = { ShowroomItemType.Decoration, ShowroomItemType.Buffet, ShowroomItemType.Lighting, ShowroomItemType.Furniture, ShowroomItemType.Stage, ShowroomItemType.Other };
        private static readonly PlacementZoneType[] ZoneOrder = { PlacementZoneType.Entrance, PlacementZoneType.Center, PlacementZoneType.StageArea, PlacementZoneType.DiningArea, PlacementZoneType.LoungeArea, PlacementZoneType.WallArea, PlacementZoneType.Other };

        private AppSession _session;
        private Transform _currentItemsRoot;
        private Transform _availableItemsRoot;
        private Transform _byZoneRoot;
        private Font _font;

        private void Start()
        {
            _session = ServiceRegistry.Instance.Get<AppSession>();
            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 = 10;
                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;

            var currentLabel = new GameObject("CurrentLabel");
            currentLabel.transform.SetParent(transform, false);
            var currentLabelRt = currentLabel.AddComponent<RectTransform>();
            currentLabelRt.sizeDelta = new Vector2(0, 20);
            var currentLabelText = currentLabel.AddComponent<Text>();
            currentLabelText.text = ItensAtuais;
            currentLabelText.font = _font;
            currentLabelText.fontSize = 14;
            currentLabelText.fontStyle = FontStyle.Bold;

            var currentRoot = new GameObject("CurrentItemsRoot");
            currentRoot.transform.SetParent(transform, false);
            var currentRootRt = currentRoot.AddComponent<RectTransform>();
            currentRootRt.sizeDelta = new Vector2(0, 200);
            var currentRootLayout = currentRoot.AddComponent<VerticalLayoutGroup>();
            currentRootLayout.spacing = 6;
            currentRootLayout.childForceExpandHeight = false;
            currentRootLayout.childForceExpandWidth = true;
            var currentRootLE = currentRoot.AddComponent<LayoutElement>();
            currentRootLE.preferredHeight = 200;
            _currentItemsRoot = currentRoot.transform;

            var availableLabel = new GameObject("AvailableLabel");
            availableLabel.transform.SetParent(transform, false);
            var availableLabelRt = availableLabel.AddComponent<RectTransform>();
            availableLabelRt.sizeDelta = new Vector2(0, 20);
            var availableLabelText = availableLabel.AddComponent<Text>();
            availableLabelText.text = ItensDisponiveis;
            availableLabelText.font = _font;
            availableLabelText.fontSize = 14;
            availableLabelText.fontStyle = FontStyle.Bold;

            var availableRoot = new GameObject("AvailableItemsRoot");
            availableRoot.transform.SetParent(transform, false);
            var availableRootRt = availableRoot.AddComponent<RectTransform>();
            availableRootRt.sizeDelta = new Vector2(0, 120);
            var availableRootLayout = availableRoot.AddComponent<VerticalLayoutGroup>();
            availableRootLayout.spacing = 6;
            availableRootLayout.childForceExpandHeight = false;
            availableRootLayout.childForceExpandWidth = true;
            var availableRootLE = availableRoot.AddComponent<LayoutElement>();
            availableRootLE.preferredHeight = 120;
            _availableItemsRoot = availableRoot.transform;

            var byZoneLabel = new GameObject("ByZoneLabel");
            byZoneLabel.transform.SetParent(transform, false);
            var byZoneLabelRt = byZoneLabel.AddComponent<RectTransform>();
            byZoneLabelRt.sizeDelta = new Vector2(0, 20);
            var byZoneLabelText = byZoneLabel.AddComponent<Text>();
            byZoneLabelText.text = "Por zona lógica";
            byZoneLabelText.font = _font;
            byZoneLabelText.fontSize = 14;
            byZoneLabelText.fontStyle = FontStyle.Bold;

            var byZoneRoot = new GameObject("ByZoneRoot");
            byZoneRoot.transform.SetParent(transform, false);
            var byZoneRootRt = byZoneRoot.AddComponent<RectTransform>();
            byZoneRootRt.sizeDelta = new Vector2(0, 140);
            var byZoneRootLayout = byZoneRoot.AddComponent<VerticalLayoutGroup>();
            byZoneRootLayout.spacing = 6;
            byZoneRootLayout.childForceExpandHeight = false;
            byZoneRootLayout.childForceExpandWidth = true;
            var byZoneRootLE = byZoneRoot.AddComponent<LayoutElement>();
            byZoneRootLE.preferredHeight = 140;
            _byZoneRoot = byZoneRoot.transform;
        }

        private void UpdateContent()
        {
            ClearChildren(_currentItemsRoot);
            ClearChildren(_availableItemsRoot);
            if (_byZoneRoot != null) ClearChildren(_byZoneRoot);

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

            var showroomService = ServiceRegistry.Instance.Get<IShowroomService>();
            var supplierService = ServiceRegistry.Instance.Get<ISupplierService>();
            if (showroomService == null) return;

            var currentItems = new List<ShowroomItem>();
            foreach (var id in project.ShowroomItemIds ?? new List<string>())
            {
                var item = showroomService.GetById(id);
                if (item != null) currentItems.Add(item);
            }

            var currentByType = GroupByType(currentItems);
            foreach (var type in TypeOrder)
                if (currentByType.TryGetValue(type, out var list) && list.Count > 0)
                    AppendGroupSection(_currentItemsRoot, TypeDisplayName(type), list, true, supplierService);

            var availableItems = showroomService.GetAvailableItemsToAdd(project);
            var availableByType = GroupByType(new List<ShowroomItem>(availableItems));
            foreach (var type in TypeOrder)
                if (availableByType.TryGetValue(type, out var list) && list.Count > 0)
                    AppendGroupSection(_availableItemsRoot, TypeDisplayName(type), list, false, supplierService);

            var currentByZone = GroupByZone(currentItems);
            if (_byZoneRoot != null)
                foreach (var zone in ZoneOrder)
                    if (currentByZone.TryGetValue(zone, out var list) && list.Count > 0)
                    {
                        list.Sort((a, b) => a.DisplayOrder.CompareTo(b.DisplayOrder));
                        AppendGroupSection(_byZoneRoot, ZoneDisplayName(zone), list, true, supplierService);
                    }
        }

        private static Dictionary<ShowroomItemType, List<ShowroomItem>> GroupByType(List<ShowroomItem> items)
        {
            var dict = new Dictionary<ShowroomItemType, List<ShowroomItem>>();
            foreach (var item in items)
            {
                if (!dict.ContainsKey(item.Type))
                    dict[item.Type] = new List<ShowroomItem>();
                dict[item.Type].Add(item);
            }
            return dict;
        }

        private static Dictionary<PlacementZoneType, List<ShowroomItem>> GroupByZone(List<ShowroomItem> items)
        {
            var dict = new Dictionary<PlacementZoneType, List<ShowroomItem>>();
            foreach (var item in items)
            {
                if (!dict.ContainsKey(item.PlacementZone))
                    dict[item.PlacementZone] = new List<ShowroomItem>();
                dict[item.PlacementZone].Add(item);
            }
            return dict;
        }

        private static string ZoneDisplayName(PlacementZoneType zone)
        {
            switch (zone)
            {
                case PlacementZoneType.Entrance: return "Entrada";
                case PlacementZoneType.Center: return "Centro";
                case PlacementZoneType.StageArea: return "Palco / Área de cerimônia";
                case PlacementZoneType.DiningArea: return "Área de refeição";
                case PlacementZoneType.LoungeArea: return "Área de convivência";
                case PlacementZoneType.WallArea: return "Parede / Área de apoio";
                default: return "Outra zona";
            }
        }

        private static string AnchorDisplayName(SpatialAnchorType anchor)
        {
            switch (anchor)
            {
                case SpatialAnchorType.Floor: return "Chão";
                case SpatialAnchorType.Wall: return "Parede";
                case SpatialAnchorType.Ceiling: return "Teto";
                case SpatialAnchorType.Freestanding: return "Autônomo";
                case SpatialAnchorType.Tabletop: return "Mesa";
                default: return "—";
            }
        }

        private void AppendGroupSection(Transform parent, string groupTitle, List<ShowroomItem> items, bool isCurrent, ISupplierService supplierService)
        {
            var groupGo = new GameObject("Group_" + groupTitle);
            groupGo.transform.SetParent(parent, false);
            var groupRt = groupGo.AddComponent<RectTransform>();
            groupRt.sizeDelta = new Vector2(0, 0);
            var groupLayout = groupGo.AddComponent<VerticalLayoutGroup>();
            groupLayout.spacing = 2;
            groupLayout.padding = new RectOffset(8, 0, 0, 0);
            groupLayout.childForceExpandHeight = false;
            groupLayout.childForceExpandWidth = true;

            var headerGo = new GameObject("Header");
            headerGo.transform.SetParent(groupGo.transform, false);
            var headerRt = headerGo.AddComponent<RectTransform>();
            headerRt.sizeDelta = new Vector2(0, 18);
            var headerText = headerGo.AddComponent<Text>();
            headerText.text = groupTitle;
            headerText.font = _font;
            headerText.fontSize = 13;
            headerText.fontStyle = FontStyle.Bold;
            headerText.color = new Color(0.2f, 0.3f, 0.2f, 1f);

            foreach (var item in items)
            {
                var supplierName = ResolveSupplierName(supplierService, item.SupplierId);
                if (isCurrent)
                    CreateCurrentItemRow(groupGo.transform, item, supplierName);
                else
                    CreateAvailableItemRow(groupGo.transform, item);
            }
        }

        private static string ResolveSupplierName(ISupplierService supplierService, string supplierId)
        {
            if (string.IsNullOrEmpty(supplierId)) return "—";
            var s = supplierService?.GetById(supplierId);
            return s?.Name ?? supplierId;
        }

        private static string TypeDisplayName(ShowroomItemType type)
        {
            switch (type)
            {
                case ShowroomItemType.Decoration: return "Decoração";
                case ShowroomItemType.Buffet: return "Buffet";
                case ShowroomItemType.Lighting: return "Iluminação";
                case ShowroomItemType.Furniture: return "Mobiliário";
                case ShowroomItemType.Stage: return "Palco";
                default: return "Outro";
            }
        }

        private void CreateCurrentItemRow(Transform parent, ShowroomItem item, string supplierName)
        {
            var row = new GameObject("Row");
            row.transform.SetParent(parent, false);
            var rowRt = row.AddComponent<RectTransform>();
            rowRt.sizeDelta = new Vector2(0, 36);

            var rowLayout = row.AddComponent<HorizontalLayoutGroup>();
            rowLayout.spacing = 8;
            rowLayout.childForceExpandWidth = false;
            rowLayout.childForceExpandHeight = true;

            var textGo = new GameObject("Text");
            textGo.transform.SetParent(row.transform, false);
            var textRt = textGo.AddComponent<RectTransform>();
            textRt.sizeDelta = new Vector2(400, 32);
            var textLE = textGo.AddComponent<LayoutElement>();
            textLE.flexibleWidth = 1;
            var text = textGo.AddComponent<Text>();
            text.text = $"{item.Name} — {supplierName}" + (item.IsIncludedByDefault ? Padrao : "") + "\nZona: " + ZoneDisplayName(item.PlacementZone) + " | Ancoragem: " + AnchorDisplayName(item.SpatialAnchorType);
            text.font = _font;
            text.fontSize = 13;

            var btnGo = new GameObject("RemoverBtn");
            btnGo.transform.SetParent(row.transform, false);
            var btnRt = btnGo.AddComponent<RectTransform>();
            btnRt.sizeDelta = new Vector2(70, 24);
            var btnLE = btnGo.AddComponent<LayoutElement>();
            btnLE.minWidth = 70;
            var img = btnGo.AddComponent<Image>();
            img.color = new Color(0.7f, 0.3f, 0.3f, 1f);
            var btn = btnGo.AddComponent<Button>();
            btn.targetGraphic = img;
            var itemId = item.Id;
            btn.onClick.AddListener(() => _session?.RemoveShowroomItem(itemId));

            var btnLabel = new GameObject("Text");
            btnLabel.transform.SetParent(btnGo.transform, false);
            var btnLabelRt = btnLabel.AddComponent<RectTransform>();
            btnLabelRt.anchorMin = Vector2.zero;
            btnLabelRt.anchorMax = Vector2.one;
            btnLabelRt.offsetMin = Vector2.zero;
            btnLabelRt.offsetMax = Vector2.zero;
            var btnLabelText = btnLabel.AddComponent<Text>();
            btnLabelText.text = Remover;
            btnLabelText.font = _font;
            btnLabelText.fontSize = 12;
            btnLabelText.alignment = TextAnchor.MiddleCenter;
            btnLabelText.color = Color.white;
        }

        private void CreateAvailableItemRow(Transform parent, ShowroomItem item)
        {
            var row = new GameObject("AvailableRow");
            row.transform.SetParent(parent, false);
            var rowRt = row.AddComponent<RectTransform>();
            rowRt.sizeDelta = new Vector2(0, 28);

            var rowLayout = row.AddComponent<HorizontalLayoutGroup>();
            rowLayout.spacing = 8;
            rowLayout.childForceExpandWidth = false;

            var textGo = new GameObject("Text");
            textGo.transform.SetParent(row.transform, false);
            var textRt = textGo.AddComponent<RectTransform>();
            textRt.sizeDelta = new Vector2(350, 22);
            var textLE = textGo.AddComponent<LayoutElement>();
            textLE.flexibleWidth = 1;
            var text = textGo.AddComponent<Text>();
            text.text = item.Name + " — Zona: " + ZoneDisplayName(item.PlacementZone) + " | " + AnchorDisplayName(item.SpatialAnchorType);
            text.font = _font;
            text.fontSize = 13;

            var btnGo = new GameObject("AddBtn");
            btnGo.transform.SetParent(row.transform, false);
            var btnRt = btnGo.AddComponent<RectTransform>();
            btnRt.sizeDelta = new Vector2(70, 24);
            var btnLE = btnGo.AddComponent<LayoutElement>();
            btnLE.minWidth = 70;
            var img = btnGo.AddComponent<Image>();
            img.color = new Color(0.2f, 0.5f, 0.3f, 1f);
            var btn = btnGo.AddComponent<Button>();
            btn.targetGraphic = img;
            var itemId = item.Id;
            btn.onClick.AddListener(() => _session?.AddShowroomItem(itemId));

            var btnLabel = new GameObject("Text");
            btnLabel.transform.SetParent(btnGo.transform, false);
            var btnLabelRt = btnLabel.AddComponent<RectTransform>();
            btnLabelRt.anchorMin = Vector2.zero;
            btnLabelRt.anchorMax = Vector2.one;
            btnLabelRt.offsetMin = Vector2.zero;
            btnLabelRt.offsetMax = Vector2.zero;
            var btnLabelText = btnLabel.AddComponent<Text>();
            btnLabelText.text = Add;
            btnLabelText.font = _font;
            btnLabelText.fontSize = 12;
            btnLabelText.alignment = TextAnchor.MiddleCenter;
            btnLabelText.color = Color.white;
        }

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