using System;
using System.Collections.Generic;
using EventsAppQuest.Web.Producer.Core;
using EventsAppQuest.Web.Producer.Domain;

namespace EventsAppQuest.Web.Producer.Application
{
    /// <summary>
    /// Avalia e mantém o estado de prontidão operacional do pedido (preparação e execução).
    /// Detecta bloqueios (aceite, escopo, esclarecimento, revisão) e gera resumo; usa ResolvedBlockingStore para itens marcados como resolvidos (mock).
    /// </summary>
    public static class ProducerExecutionReadinessController
    {
        public const string BlockingAcceptancePending = "AcceptancePending";
        public const string BlockingScopeNotConfirmed = "ScopeNotConfirmed";
        public const string BlockingClarificationPending = "ClarificationPending";
        public const string BlockingRevisionPending = "RevisionPending";

        /// <summary>Avalia o estado de readiness do pedido e devolve o estado actual (com bloqueios e flags).</summary>
        public static ProducerExecutionReadinessState Evaluate(string orderId)
        {
            if (string.IsNullOrEmpty(orderId)) return null;
            var order = HandoffStore.GetOrderById(orderId);
            if (order == null) return null;

            var scopeState = ScopeRevisionStore.GetConfirmationState(orderId);
            var activeRevision = ScopeRevisionStore.GetCurrentActiveRevision(orderId);

            var state = new ProducerExecutionReadinessState
            {
                ProducerOrderId = orderId,
                LastEvaluatedAt = DateTime.UtcNow,
                ActiveScopeRevisionId = activeRevision?.RevisionId
            };

            state.IsProducerAccepted = order.AcceptanceStatus == ProducerAcceptanceStatus.Accepted;
            state.IsScopeConfirmed = scopeState != null && scopeState.Status == ProducerScopeConfirmationStatus.Confirmed;
            state.HasPendingClarifications = order.RequiresClarification;
            state.HasPendingRevisions = scopeState != null &&
                (scopeState.Status == ProducerScopeConfirmationStatus.PendingHotelApproval ||
                 scopeState.Status == ProducerScopeConfirmationStatus.PendingProducerApproval ||
                 scopeState.Status == ProducerScopeConfirmationStatus.NeedsRevision);

            var blocks = new List<ProducerExecutionBlockingItem>();

            if (!state.IsProducerAccepted)
            {
                var item = CreateBlock(BlockingAcceptancePending, "Aceite pendente", "O produtor ainda não aceitou o pedido.", ProducerExecutionBlockingSeverity.Critical);
                item.IsResolved = ResolvedBlockingStore.IsResolved(orderId, item.Code);
                blocks.Add(item);
            }

            if (!state.IsScopeConfirmed)
            {
                var item = CreateBlock(BlockingScopeNotConfirmed, "Escopo não confirmado", "O escopo ainda não foi confirmado por ambos (hotel e produtor).", ProducerExecutionBlockingSeverity.High);
                item.IsResolved = ResolvedBlockingStore.IsResolved(orderId, item.Code);
                blocks.Add(item);
            }

            if (state.HasPendingClarifications)
            {
                var item = CreateBlock(BlockingClarificationPending, "Esclarecimento pendente", order.ClarificationReason ?? "Há pedidos de esclarecimento em aberto.", ProducerExecutionBlockingSeverity.High);
                item.IsResolved = ResolvedBlockingStore.IsResolved(orderId, item.Code);
                blocks.Add(item);
            }

            if (state.HasPendingRevisions)
            {
                var item = CreateBlock(BlockingRevisionPending, "Revisão em aberto", "Existe revisão de escopo aguardando aprovação.", ProducerExecutionBlockingSeverity.Medium);
                item.IsResolved = ResolvedBlockingStore.IsResolved(orderId, item.Code);
                blocks.Add(item);
            }

            state.BlockingItems = blocks;

            var unresolvedCriticalOrHigh = false;
            foreach (var b in state.BlockingItems)
            {
                if (b.IsResolved) continue;
                if (b.Severity == ProducerExecutionBlockingSeverity.Critical || b.Severity == ProducerExecutionBlockingSeverity.High)
                    unresolvedCriticalOrHigh = true;
            }

            state.IsReadyForPreparation = state.IsProducerAccepted && state.IsScopeConfirmed && !state.HasPendingClarifications && !unresolvedCriticalOrHigh;
            state.IsReadyForExecution = state.IsReadyForPreparation;

            state.ReadinessSummary = state.IsReadyForExecution
                ? "Pronto para preparação e execução."
                : BuildSummary(state);

            return state;
        }

        /// <summary>Marca um bloqueio como resolvido (mock).</summary>
        public static void MarkBlockingResolved(string orderId, string code)
        {
            ResolvedBlockingStore.SetResolved(orderId, code);
        }

        /// <summary>Marca um bloqueio como não resolvido.</summary>
        public static void MarkBlockingUnresolved(string orderId, string code)
        {
            ResolvedBlockingStore.SetUnresolved(orderId, code);
        }

        private static ProducerExecutionBlockingItem CreateBlock(string code, string title, string summary, ProducerExecutionBlockingSeverity severity)
        {
            return new ProducerExecutionBlockingItem { Code = code, Title = title, Summary = summary, Severity = severity, IsResolved = false };
        }

        private static string BuildSummary(ProducerExecutionReadinessState state)
        {
            var parts = new List<string>();
            if (!state.IsProducerAccepted) parts.Add("aceite pendente");
            if (!state.IsScopeConfirmed) parts.Add("escopo não confirmado");
            if (state.HasPendingClarifications) parts.Add("esclarecimento pendente");
            if (state.HasPendingRevisions) parts.Add("revisão em aberto");
            var unresolved = new List<string>();
            foreach (var b in state.BlockingItems)
                if (!b.IsResolved) unresolved.Add(b.Title);
            if (unresolved.Count > 0)
                return "Bloqueios: " + string.Join("; ", unresolved);
            return "Avaliado. " + string.Join("; ", parts);
        }
    }
}
