using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using EventsAppQuest.Web.Producer.Application;
using EventsAppQuest.Web.Producer.Core;
using EventsAppQuest.Web.Producer.Domain;

namespace EventsAppQuest.Web.Presentation
{
    /// <summary>
    /// Painel no CRM do hotel: escopo actual, revisões de escopo, aprovar/rejeitar, solicitar ajuste, status de confirmação operacional.
    /// </summary>
    public class OrderScopePanel : MonoBehaviour, IWebContentRoot
    {
        private Transform _content;

        public void SetContentRoot(Transform contentRoot) => _content = contentRoot;

        private void Start()
        {
            Refresh();
            WebRuntimeContext.OnDataChanged += Refresh;
        }
        private void OnDestroy() => WebRuntimeContext.OnDataChanged -= Refresh;

        public void Refresh()
        {
            if (_content == null) return;
            ClearContent(_content);
            var font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");

            var label = new GameObject("Label");
            label.transform.SetParent(_content, false);
            var labelRt = label.AddComponent<RectTransform>();
            labelRt.sizeDelta = new Vector2(0, 22);
            var labelText = label.AddComponent<Text>();
            labelText.text = "Escopo do pedido e confirmação operacional";
            labelText.font = font;
            labelText.fontSize = 14;
            labelText.fontStyle = FontStyle.Bold;

            foreach (var order in HandoffStore.GetOrders())
            {
                var orderId = order.OrderId;
                var state = ProducerOrderScopeController.GetConfirmationState(orderId);
                var activeRevision = ProducerOrderScopeController.GetCurrentActiveRevision(orderId);
                var scopeLabel = ScopeIndicatorHelper.GetScopeStatusLabel(state, activeRevision);

                var orderBlock = new GameObject("Scope_" + orderId);
                orderBlock.transform.SetParent(_content, false);
                var orderLayout = orderBlock.AddComponent<VerticalLayoutGroup>();
                orderLayout.spacing = 4;
                orderLayout.childForceExpandHeight = false;
                orderLayout.childForceExpandWidth = true;

                var header = new GameObject("Header");
                header.transform.SetParent(orderBlock.transform, false);
                var headerText = header.AddComponent<Text>();
                headerText.font = font;
                headerText.fontSize = 11;
                headerText.text = $"{orderId} | {scopeLabel} | {(state != null && state.Status == ProducerScopeConfirmationStatus.Confirmed ? "Operacionalmente confirmado" : "")}\nEscopo actual: {order.OrderSummary}";
                headerText.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 32);

                var reqBtn = CreateButton(orderBlock.transform, "Solicitar ajuste de escopo", font, () => OnRequestAdjustment(orderId));
                reqBtn.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 24);

                var revList = new GameObject("Revisions");
                revList.transform.SetParent(orderBlock.transform, false);
                var revText = revList.AddComponent<Text>();
                revText.font = font;
                revText.fontSize = 10;
                var revisions = ProducerOrderScopeController.GetRevisionsForOrder(orderId).ToList();
                revText.text = revisions.Count == 0 ? "(sem revisões)" : string.Join("\n", revisions.Select(r =>
                    $"{r.RevisionId} | Pedido por: {r.RequestedByRole} | {r.Status} | Hotel: {(r.IsApprovedByHotel ? "Aprovado" : "—")} | Produtor: {(r.IsApprovedByProducer ? "Aprovado" : "—")} | {(r.IsCurrentActiveRevision ? " [ACTIVO]" : "")} | {r.RevisionSummary}"));
                revText.GetComponent<RectTransform>().sizeDelta = new Vector2(0, Mathf.Max(40, revisions.Count * 14));

                foreach (var rev in revisions.Where(r => r.Status == ProducerScopeConfirmationStatus.PendingHotelApproval))
                {
                    var revRow = new GameObject("RevActions_" + rev.RevisionId);
                    revRow.transform.SetParent(orderBlock.transform, false);
                    var revRowRt = revRow.AddComponent<RectTransform>();
                    revRowRt.sizeDelta = new Vector2(0, 26);
                    var revRowText = revRow.AddComponent<Text>();
                    revRowText.font = font;
                    revRowText.fontSize = 10;
                    revRowText.text = $"Revisão {rev.RevisionId}: {rev.RevisionSummary}";
                    var appBtn = CreateSmallButton(revRow.transform, "Aprovar", font, () => { ProducerOrderScopeController.ApproveByHotel(rev.RevisionId); Refresh(); });
                    var rejBtn = CreateSmallButton(revRow.transform, "Rejeitar", font, () => { ProducerOrderScopeController.RejectByHotel(rev.RevisionId); Refresh(); });
                }
            }
        }

        private void OnRequestAdjustment(string orderId)
        {
            var rev = ProducerOrderScopeController.CreateRevision(orderId, ScopeRevisionRequestedByRole.HotelSales, "Ajuste solicitado pelo hotel (mock)", "Solicitação de ajuste de escopo");
            if (rev != null)
                ProducerOrderScopeController.AddChangeItem(rev.RevisionId, ProducerScopeChangeType.ClarifyRequirement, null, "Esclarecimento solicitado pelo hotel", null, null);
            WebRuntimeContext.NotifyDataChanged();
            Refresh();
        }

        private static Button CreateButton(Transform parent, string text, Font font, System.Action onClick)
        {
            var go = new GameObject("Btn");
            go.transform.SetParent(parent, false);
            var rt = go.AddComponent<RectTransform>();
            var img = go.AddComponent<Image>();
            img.color = new Color(0.4f, 0.65f, 0.9f);
            var btn = go.AddComponent<Button>();
            btn.targetGraphic = img;
            btn.onClick.AddListener(() => onClick?.Invoke());
            var tGo = new GameObject("Text");
            tGo.transform.SetParent(go.transform, false);
            var t = tGo.AddComponent<Text>();
            t.text = text;
            t.font = font;
            t.fontSize = 11;
            t.alignment = TextAnchor.MiddleCenter;
            var tRt = tGo.GetComponent<RectTransform>();
            tRt.anchorMin = Vector2.zero;
            tRt.anchorMax = Vector2.one;
            tRt.offsetMin = Vector2.zero;
            tRt.offsetMax = Vector2.zero;
            return btn;
        }

        private static Button CreateSmallButton(Transform parent, string text, Font font, System.Action onClick)
        {
            var go = new GameObject("Btn_" + text);
            go.transform.SetParent(parent, false);
            var rt = go.AddComponent<RectTransform>();
            rt.anchorMin = new Vector2(1, 0.5f);
            rt.anchorMax = new Vector2(1, 0.5f);
            rt.pivot = new Vector2(1, 0.5f);
            rt.sizeDelta = new Vector2(60, 20);
            rt.anchoredPosition = text == "Aprovar" ? new Vector2(-70, 0) : new Vector2(-5, 0);
            var img = go.AddComponent<Image>();
            img.color = text == "Aprovar" ? new Color(0.3f, 0.7f, 0.4f) : new Color(0.8f, 0.35f, 0.3f);
            var btn = go.AddComponent<Button>();
            btn.targetGraphic = img;
            btn.onClick.AddListener(() => onClick?.Invoke());
            var tGo = new GameObject("Text");
            tGo.transform.SetParent(go.transform, false);
            var t = tGo.AddComponent<Text>();
            t.text = text;
            t.font = font;
            t.fontSize = 9;
            t.alignment = TextAnchor.MiddleCenter;
            var tRt = tGo.GetComponent<RectTransform>();
            tRt.anchorMin = Vector2.zero;
            tRt.anchorMax = Vector2.one;
            tRt.offsetMin = Vector2.zero;
            tRt.offsetMax = Vector2.zero;
            return btn;
        }

        private static void ClearContent(Transform content)
        {
            for (var i = content.childCount - 1; i >= 0; i--)
                Destroy(content.GetChild(i).gameObject);
        }
    }
}
