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

namespace EventsAppQuest.Presentation
{
    /// <summary>
    /// Exibe a jornada do evento por momentos/fases: ordem, descrição, duração, itens principais, fornecedores-chave e destaque.
    /// </summary>
    public class EventMomentPlanView : MonoBehaviour
    {
        private const string Title = "Momentos do Evento / Jornada da Experiência";
        private const string NenhumProjeto = "Nenhum projeto ou proposta ativa.";
        private const string Duracao = "Duração estimada: ";
        private const string ItensPrincipais = "Itens: ";
        private const string FornecedoresChave = "Fornecedores: ";
        private const string Destaque = "Destaque: ";

        private AppSession _session;
        private IEventMomentPlanningService _planningService;
        private IShowroomService _showroomService;
        private ISupplierService _supplierService;
        private Transform _contentRoot;
        private Font _font;

        private void Start()
        {
            _session = ServiceRegistry.Instance.Get<AppSession>();
            _planningService = ServiceRegistry.Instance.Get<IEventMomentPlanningService>();
            _showroomService = ServiceRegistry.Instance.Get<IShowroomService>();
            _supplierService = ServiceRegistry.Instance.Get<ISupplierService>();
            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 = 6;
                layout.padding = new RectOffset(12, 12, 12, 12);
                layout.childForceExpandHeight = false;
                layout.childForceExpandWidth = true;
            }

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

            _contentRoot = new GameObject("ContentRoot").transform;
            _contentRoot.SetParent(transform, false);
            _contentRoot.gameObject.AddComponent<LayoutElement>().preferredHeight = 340;
            var vlg = _contentRoot.gameObject.AddComponent<VerticalLayoutGroup>();
            vlg.spacing = 6;
            vlg.childForceExpandHeight = false;
            vlg.childForceExpandWidth = true;
        }

        private void UpdateContent()
        {
            ClearChildren(_contentRoot);

            var project = _session?.CurrentProject;
            var active = project?.GetActiveProposal();
            if (project == null || active == null)
            {
                AppendText(_contentRoot, NenhumProjeto);
                return;
            }

            var plans = _planningService?.GenerateMomentPlan(project, active);
            if (plans == null || plans.Count == 0)
            {
                AppendText(_contentRoot, "Nenhum momento planejado. Gere a narrativa da proposta para preencher a jornada.");
                return;
            }

            active.MomentPlans = new List<ProposalMomentPlan>(plans);

            var phases = (_planningService.GetAvailablePhases(project.EventTemplateId) ?? new List<EventMomentPhase>())
                .ToDictionary(p => p.Id, p => p);

            foreach (var plan in plans)
            {
                var phase = phases.TryGetValue(plan.PhaseId, out var p) ? p : null;
                var phaseName = phase?.Name ?? plan.PhaseId;
                var phaseDesc = phase?.Description ?? "";

                var card = new GameObject("MomentCard");
                card.transform.SetParent(_contentRoot, false);
                card.AddComponent<RectTransform>().sizeDelta = new Vector2(0, 72);
                var cardVlg = card.AddComponent<VerticalLayoutGroup>();
                cardVlg.spacing = 2;
                cardVlg.padding = new RectOffset(8, 8, 8, 8);
                cardVlg.childForceExpandHeight = false;
                cardVlg.childForceExpandWidth = true;
                card.AddComponent<Image>().color = new Color(0.96f, 0.97f, 0.95f, 1f);

                var nameLine = new GameObject("Name");
                nameLine.transform.SetParent(card.transform, false);
                nameLine.AddComponent<RectTransform>().sizeDelta = new Vector2(0, 16);
                var nameText = nameLine.AddComponent<Text>();
                nameText.text = phaseName + (plan.EstimatedDurationMinutes > 0 ? " — " + Duracao + plan.EstimatedDurationMinutes + " min" : "");
                nameText.font = _font;
                nameText.fontSize = 13;
                nameText.fontStyle = FontStyle.Bold;

                if (!string.IsNullOrEmpty(phaseDesc))
                {
                    var descLine = new GameObject("Desc");
                    descLine.transform.SetParent(card.transform, false);
                    descLine.AddComponent<RectTransform>().sizeDelta = new Vector2(0, 14);
                    var descText = descLine.AddComponent<Text>();
                    descText.text = phaseDesc;
                    descText.font = _font;
                    descText.fontSize = 11;
                    descText.color = new Color(0.35f, 0.35f, 0.4f, 1f);
                }

                var detailParts = new List<string>();
                if (plan.RelatedShowroomItemIds != null && plan.RelatedShowroomItemIds.Count > 0)
                {
                    var names = plan.RelatedShowroomItemIds
                        .Select(id => _showroomService?.GetById(id)?.Name)
                        .Where(n => !string.IsNullOrEmpty(n))
                        .Take(3);
                    detailParts.Add(ItensPrincipais + string.Join(", ", names) + (plan.RelatedShowroomItemIds.Count > 3 ? "…" : ""));
                }
                if (plan.KeySupplierIds != null && plan.KeySupplierIds.Count > 0)
                {
                    var names = plan.KeySupplierIds
                        .Select(id => _supplierService?.GetById(id)?.Name)
                        .Where(n => !string.IsNullOrEmpty(n))
                        .Take(2);
                    detailParts.Add(FornecedoresChave + string.Join(", ", names) + (plan.KeySupplierIds.Count > 2 ? "…" : ""));
                }
                if (!string.IsNullOrEmpty(plan.HighlightText))
                    detailParts.Add(Destaque + plan.HighlightText);

                if (detailParts.Count > 0)
                {
                    var detailLine = new GameObject("Detail");
                    detailLine.transform.SetParent(card.transform, false);
                    detailLine.AddComponent<RectTransform>().sizeDelta = new Vector2(0, 14);
                    var detailText = detailLine.AddComponent<Text>();
                    detailText.text = string.Join(" | ", detailParts);
                    detailText.font = _font;
                    detailText.fontSize = 10;
                    detailText.color = new Color(0.4f, 0.45f, 0.5f, 1f);
                }
            }
        }

        private void AppendText(Transform parent, string text)
        {
            var go = new GameObject("TextLine");
            go.transform.SetParent(parent, false);
            go.AddComponent<RectTransform>().sizeDelta = new Vector2(0, 16);
            var t = go.AddComponent<Text>();
            t.text = text;
            t.font = _font;
            t.fontSize = 12;
        }

        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);
        }
    }
}
