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

namespace EventsAppQuest.Web.Application
{
    /// <summary>
    /// Agrega dados do ciclo completo (Quest → Hotel → Produtor → Aceite Final) numa visão consolidada. Apenas leitura; não duplica regras.
    /// </summary>
    public static class EventCycleDashboardController
    {
        public const string SectionComercial = "Comercial";
        public const string SectionSessaoQuest = "SessaoQuest";
        public const string SectionHandoff = "Handoff";
        public const string SectionProdutor = "Produtor";
        public const string SectionExecucao = "Execucao";
        public const string SectionAceiteFinal = "AceiteFinal";
        public const string SectionStatusGeral = "StatusGeral";

        /// <summary>Constrói o dashboard para todos os pedidos, cruzando com oportunidades, propostas e sessões.</summary>
        public static List<EventCycleDashboardState> BuildDashboard(
            IReadOnlyList<ProducerOrder> orders,
            IReadOnlyList<SalesOpportunity> opportunities,
            IReadOnlyList<ProposalRecord> proposals,
            IReadOnlyList<SessionRecord> sessions)
        {
            var list = new List<EventCycleDashboardState>();
            if (orders == null) return list;
            var opps = opportunities ?? new List<SalesOpportunity>();
            var props = proposals ?? new List<ProposalRecord>();
            var sess = sessions ?? new List<SessionRecord>();

            foreach (var order in orders)
            {
                SalesOpportunity opp = null;
                if (!string.IsNullOrEmpty(order.OpportunityId))
                    opp = opps.FirstOrDefault(o => o.Id == order.OpportunityId);
                ProposalRecord prop = null;
                var propId = order.ProposalId ?? opp?.ProposalRecordId;
                if (!string.IsNullOrEmpty(propId))
                    prop = props.FirstOrDefault(p => p.Id == propId);
                SessionRecord ses = null;
                var sessId = order.SessionId ?? opp?.SessionRecordId;
                if (!string.IsNullOrEmpty(sessId))
                    ses = sess.FirstOrDefault(s => s.Id == sessId);

                var state = BuildCycleState(order, opp, prop, ses);
                if (state != null)
                    list.Add(state);
            }

            return list;
        }

        /// <summary>Constrói o estado consolidado de um ciclo (um pedido + dados comerciais).</summary>
        public static EventCycleDashboardState BuildCycleState(
            ProducerOrder order,
            SalesOpportunity opportunity,
            ProposalRecord proposal,
            SessionRecord session)
        {
            if (order == null) return null;
            var orderId = order.OrderId;
            var readiness = ProducerExecutionReadinessController.Evaluate(orderId);
            var checklistState = ProducerPreparationChecklistController.GetChecklistState(orderId);
            var prepConfirmed = PreparationChecklistStore.IsPreparationConfirmed(orderId);
            var execState = ProducerExecutionTrackingController.GetState(orderId);
            var finalReport = ProducerExecutionFinalReportController.GetReport(orderId);
            var finalAcceptance = HotelFinalAcceptanceController.GetState(orderId);

            var state = new EventCycleDashboardState
            {
                CycleId = orderId,
                ProducerOrderId = orderId,
                LeadId = order.SourceLeadId ?? opportunity?.LeadId,
                OpportunityId = order.OpportunityId ?? opportunity?.Id,
                ProposalId = order.ProposalId ?? opportunity?.ProposalRecordId,
                SessionId = order.SessionId ?? opportunity?.SessionRecordId,
                CommercialStageLabel = opportunity != null ? opportunity.Stage.ToString() : "—",
                OperationalStageLabel = DeriveOperationalStageLabel(order, readiness, prepConfirmed, execState, finalReport, finalAcceptance),
                OverallCycleStatus = DeriveOverallStatus(order, opportunity, execState, finalReport, finalAcceptance),
                LastUpdatedAt = order.LastUpdatedAt ?? order.CreatedAt,
                IsQuestSessionDone = session != null && !string.IsNullOrEmpty(session.SessionId),
                IsHandoffGenerated = !string.IsNullOrEmpty(order.OrderSummary) || order.GeneratedAt.HasValue,
                IsProducerAccepted = order.AcceptanceStatus == ProducerAcceptanceStatus.Accepted,
                IsScopeConfirmed = readiness != null && readiness.IsScopeConfirmed,
                IsPreparationConfirmed = prepConfirmed,
                IsExecutionStarted = execState != null && execState.ExecutionStatus != ProducerExecutionStatus.NotStarted && execState.ExecutionStatus != ProducerExecutionStatus.Preparing,
                IsExecutionCompleted = execState != null && execState.IsCompleted,
                IsFinalAcceptanceDone = finalAcceptance != null && (finalAcceptance.AcceptanceStatus == HotelFinalAcceptanceStatus.Accepted || finalAcceptance.AcceptanceStatus == HotelFinalAcceptanceStatus.Rejected || finalAcceptance.AcceptanceStatus == HotelFinalAcceptanceStatus.Closed),
                FinalAcceptanceStatus = finalAcceptance != null ? finalAcceptance.AcceptanceStatus.ToString() : "—",
                Sections = new List<EventCycleDashboardSection>()
            };

            state.Sections.Add(BuildSectionComercial(opportunity, proposal));
            state.Sections.Add(BuildSectionSessaoQuest(session, opportunity));
            state.Sections.Add(BuildSectionHandoff(order));
            state.Sections.Add(BuildSectionProdutor(order, readiness, checklistState, prepConfirmed));
            state.Sections.Add(BuildSectionExecucao(execState, finalReport));
            state.Sections.Add(BuildSectionAceiteFinal(finalReport, finalAcceptance));
            state.Sections.Add(BuildSectionStatusGeral(state));
            return state;
        }

        /// <summary>Conta secções saudáveis e pendentes para um estado.</summary>
        public static void CountSectionsHealth(EventCycleDashboardState state, out int healthy, out int pending)
        {
            healthy = 0;
            pending = 0;
            if (state?.Sections == null) return;
            foreach (var s in state.Sections)
            {
                if (s.IsHealthy) healthy++;
                else pending++;
            }
        }

        private static string DeriveOperationalStageLabel(ProducerOrder order, ProducerExecutionReadinessState readiness, bool prepConfirmed, ProducerExecutionStatusState execState, ProducerExecutionFinalReport finalReport, HotelFinalAcceptanceState finalAcceptance)
        {
            if (finalAcceptance != null && finalAcceptance.IsOrderCycleClosed)
                return "Ciclo encerrado";
            if (finalAcceptance != null && finalAcceptance.AcceptanceStatus == HotelFinalAcceptanceStatus.Accepted)
                return "Aceite final concedido";
            if (finalReport != null && FinalReportStore.IsOperationallyClosed(order.OrderId))
                return "Relatório final / aguardar hotel";
            if (execState != null && execState.IsCompleted)
                return "Execução concluída";
            if (execState != null && execState.ExecutionStatus != ProducerExecutionStatus.NotStarted && execState.ExecutionStatus != ProducerExecutionStatus.Preparing)
                return "Em execução";
            if (prepConfirmed)
                return "Preparação confirmada";
            if (readiness != null && readiness.IsReadyForPreparation)
                return "Pronto para preparação";
            if (order.AcceptanceStatus == ProducerAcceptanceStatus.Accepted)
                return "Aceite pelo produtor";
            if (!string.IsNullOrEmpty(order.OrderId))
                return "Handoff gerado";
            return "—";
        }

        private static string DeriveOverallStatus(ProducerOrder order, SalesOpportunity opportunity, ProducerExecutionStatusState execState, ProducerExecutionFinalReport finalReport, HotelFinalAcceptanceState finalAcceptance)
        {
            if (finalAcceptance != null && finalAcceptance.IsOrderCycleClosed)
                return "Ciclo encerrado";
            if (finalAcceptance != null && finalAcceptance.AcceptanceStatus == HotelFinalAcceptanceStatus.Accepted)
                return "Aceite final concedido";
            if (finalAcceptance != null && finalAcceptance.AcceptanceStatus == HotelFinalAcceptanceStatus.Rejected)
                return "Rejeitado pelo hotel";
            if (finalAcceptance != null && finalAcceptance.NeedsFinalAdjustment)
                return "Ajuste final solicitado";
            if (finalReport != null && FinalReportStore.IsOperationallyClosed(order?.OrderId))
                return "Aguardando aceite final do hotel";
            if (execState != null && execState.IsCompleted)
                return "Execução concluída";
            if (execState != null && (execState.ExecutionStatus == ProducerExecutionStatus.InExecution || execState.ExecutionStatus == ProducerExecutionStatus.Paused || execState.ExecutionStatus == ProducerExecutionStatus.Blocked))
                return "Em execução";
            if (order != null && order.AcceptanceStatus == ProducerAcceptanceStatus.Accepted)
                return "Em preparação / execução";
            if (order != null && !string.IsNullOrEmpty(order.OrderId))
                return "Handoff / produtor";
            if (opportunity != null)
                return "Pipeline comercial";
            return "—";
        }

        private static EventCycleDashboardSection BuildSectionComercial(SalesOpportunity opportunity, ProposalRecord proposal)
        {
            var section = new EventCycleDashboardSection { SectionKey = SectionComercial, Title = "Comercial" };
            if (opportunity == null)
            {
                section.Summary = "Sem oportunidade associada.";
                section.StatusLabel = "—";
                section.IsHealthy = false;
                return section;
            }
            section.Summary = opportunity.Title ?? opportunity.Id;
            section.StatusLabel = opportunity.Stage.ToString();
            section.IsHealthy = opportunity.Stage != OpportunityStage.Lost;
            section.Notes = opportunity.SuggestedNextAction;
            return section;
        }

        private static EventCycleDashboardSection BuildSectionSessaoQuest(SessionRecord session, SalesOpportunity opportunity)
        {
            var section = new EventCycleDashboardSection { SectionKey = SectionSessaoQuest, Title = "Sessão Quest" };
            if (session == null || string.IsNullOrEmpty(session.SessionId))
            {
                section.Summary = "Sessão Quest não realizada ou não associada.";
                section.StatusLabel = "—";
                section.IsHealthy = false;
                return section;
            }
            section.Summary = "Sessão realizada: " + (session.SessionId ?? "—");
            section.StatusLabel = session.FinalDecisionState.ToString();
            section.IsHealthy = true;
            section.Notes = session.ConfirmedCTA ?? session.SuggestedNextAction;
            return section;
        }

        private static EventCycleDashboardSection BuildSectionHandoff(ProducerOrder order)
        {
            var section = new EventCycleDashboardSection { SectionKey = SectionHandoff, Title = "Handoff" };
            if (order == null)
            {
                section.Summary = "Sem pedido.";
                section.StatusLabel = "—";
                section.IsHealthy = false;
                return section;
            }
            section.Summary = order.OrderSummary ?? order.OrderId ?? "—";
            section.StatusLabel = order.AcceptanceStatus.ToString();
            section.IsHealthy = order.AcceptanceStatus != ProducerAcceptanceStatus.Rejected;
            section.Notes = order.SalesHandoffNotes;
            return section;
        }

        private static EventCycleDashboardSection BuildSectionProdutor(ProducerOrder order, ProducerExecutionReadinessState readiness, ProducerPreparationChecklistState checklistState, bool prepConfirmed)
        {
            var section = new EventCycleDashboardSection { SectionKey = SectionProdutor, Title = "Produtor" };
            if (order == null)
            {
                section.Summary = "—";
                section.StatusLabel = "—";
                section.IsHealthy = false;
                return section;
            }
            section.Summary = readiness != null ? (readiness.ReadinessSummary ?? (readiness.IsReadyForPreparation ? "Pronto para preparação" : "Pendente")) : "—";
            section.StatusLabel = prepConfirmed ? "Preparação confirmada" : (checklistState != null ? checklistState.CompletedItems + "/" + checklistState.TotalItems + " itens" : order.AcceptanceStatus.ToString());
            section.IsHealthy = order.AcceptanceStatus == ProducerAcceptanceStatus.Accepted && (readiness == null || !readiness.HasPendingClarifications);
            section.Notes = checklistState != null && checklistState.RequiredItems > 0 && checklistState.CompletedRequiredItems < checklistState.RequiredItems ? "Pendências obrigatórias" : null;
            return section;
        }

        private static EventCycleDashboardSection BuildSectionExecucao(ProducerExecutionStatusState execState, ProducerExecutionFinalReport finalReport)
        {
            var section = new EventCycleDashboardSection { SectionKey = SectionExecucao, Title = "Execução" };
            if (execState == null)
            {
                section.Summary = "Execução não iniciada.";
                section.StatusLabel = "—";
                section.IsHealthy = true;
                return section;
            }
            section.Summary = execState.CurrentExecutionSummary ?? execState.CompletionSummary ?? ("Progresso: " + execState.ProgressPercent + "%");
            section.StatusLabel = execState.ExecutionStatus + " " + execState.ProgressPercent + "%";
            section.IsHealthy = !execState.HasIssues && execState.ExecutionStatus != ProducerExecutionStatus.Blocked;
            section.Notes = finalReport != null && finalReport.ClosedByProducerAt.HasValue ? "Relatório final gerado" : null;
            return section;
        }

        private static EventCycleDashboardSection BuildSectionAceiteFinal(ProducerExecutionFinalReport finalReport, HotelFinalAcceptanceState finalAcceptance)
        {
            var section = new EventCycleDashboardSection { SectionKey = SectionAceiteFinal, Title = "Aceite Final" };
            if (finalAcceptance == null)
            {
                section.Summary = finalReport != null && finalReport.ClosedByProducerAt.HasValue ? "Aguardando decisão do hotel." : "Aguardando relatório/conclusão do produtor.";
                section.StatusLabel = "—";
                section.IsHealthy = true;
                return section;
            }
            section.Summary = finalAcceptance.FinalAcceptanceSummary ?? finalAcceptance.AcceptanceStatus.ToString();
            section.StatusLabel = finalAcceptance.AcceptanceStatus.ToString();
            section.IsHealthy = finalAcceptance.AcceptanceStatus != HotelFinalAcceptanceStatus.Rejected;
            section.Notes = finalAcceptance.HotelAcceptanceNotes;
            if (finalAcceptance.IsOrderCycleClosed)
                section.Notes = (section.Notes ?? "") + " [Ciclo encerrado]";
            return section;
        }

        private static EventCycleDashboardSection BuildSectionStatusGeral(EventCycleDashboardState state)
        {
            var section = new EventCycleDashboardSection { SectionKey = SectionStatusGeral, Title = "Status Geral" };
            section.Summary = state.OverallCycleStatus ?? "—";
            section.StatusLabel = state.OperationalStageLabel ?? state.CommercialStageLabel ?? "—";
            var healthy = 0;
            var total = state.Sections?.Count ?? 0;
            if (state.Sections != null)
                foreach (var s in state.Sections)
                    if (s.SectionKey != SectionStatusGeral && s.IsHealthy) healthy++;
            section.IsHealthy = state.IsFinalAcceptanceDone || (total > 0 && healthy >= total - 2);
            section.Notes = "Última atualização: " + (state.LastUpdatedAt?.ToString("yyyy-MM-dd HH:mm") ?? "—");
            return section;
        }
    }
}
