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 avaliação de fluxo e logística operacional do evento (status, risco de gargalo, acesso de serviço, avisos e recomendações).
    /// </summary>
    public class EventFlowView : MonoBehaviour
    {
        private const string Title = "Fluxo do Evento / Logística Operacional";
        private const string NenhumProjeto = "Nenhum projeto ou proposta ativa.";
        private const string StatusGeral = "Status geral: ";
        private const string RiscoGargalo = "Risco de gargalo (0–100, maior = pior): ";
        private const string AcessoServico = "Acesso de serviço (0–100, maior = melhor): ";
        private const string AvisosCirculacao = "Avisos de circulação";
        private const string RiscosPorZona = "Riscos por zona";
        private const string Recomendacoes = "Recomendações";

        private AppSession _session;
        private IEventFlowEvaluationService _flowService;
        private Transform _contentRoot;
        private Font _font;

        private void Start()
        {
            _session = ServiceRegistry.Instance.Get<AppSession>();
            _flowService = ServiceRegistry.Instance.Get<IEventFlowEvaluationService>();
            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 = 180;
            var vlg = _contentRoot.gameObject.AddComponent<VerticalLayoutGroup>();
            vlg.spacing = 4;
            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 flow = _flowService?.Evaluate(project, active);
            if (flow == null)
            {
                AppendText(_contentRoot, "Avaliação de fluxo não disponível.");
                return;
            }

            AppendText(_contentRoot, StatusGeral + FlowStatusText(flow.OverallFlowStatus));
            AppendText(_contentRoot, RiscoGargalo + flow.CongestionRiskScore);
            AppendText(_contentRoot, AcessoServico + flow.ServiceAccessScore);
            AppendList(_contentRoot, AvisosCirculacao, flow.CirculationWarnings, new Color(0.6f, 0.35f, 0.15f, 1f));
            AppendList(_contentRoot, RiscosPorZona, flow.ZoneRiskSummaries, new Color(0.5f, 0.3f, 0.2f, 1f));
            AppendList(_contentRoot, Recomendacoes, flow.Recommendations, new Color(0.2f, 0.4f, 0.5f, 1f));
        }

        private static string FlowStatusText(FlowStatus s)
        {
            switch (s)
            {
                case FlowStatus.Good: return "Adequado";
                case FlowStatus.Warning: return "Atenção";
                case FlowStatus.Critical: return "Crítico";
                default: return "—";
            }
        }

        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 void AppendList(Transform parent, string title, List<string> items, Color color)
        {
            if (items == null || items.Count == 0) return;
            var labelGo = new GameObject("Label");
            labelGo.transform.SetParent(parent, false);
            labelGo.AddComponent<RectTransform>().sizeDelta = new Vector2(0, 14);
            var label = labelGo.AddComponent<Text>();
            label.text = title + ":";
            label.font = _font;
            label.fontSize = 11;
            label.fontStyle = FontStyle.Bold;
            foreach (var item in items)
            {
                var line = new GameObject("Item");
                line.transform.SetParent(parent, false);
                line.AddComponent<RectTransform>().sizeDelta = new Vector2(0, 14);
                var t = line.AddComponent<Text>();
                t.text = "• " + item;
                t.font = _font;
                t.fontSize = 11;
                t.color = color;
            }
        }

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