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

namespace EventsAppQuest.Infrastructure.Services
{
    /// <summary>
    /// Gera revisão comercial e snapshots a partir do projeto (validação, tema, orçamento, narrativa).
    /// </summary>
    public class MockProposalReviewService : IProposalReviewService
    {
        public ProposalReviewSummary GenerateReview(EventProject project)
        {
            var summary = new ProposalReviewSummary();
            if (project == null) return summary;

            var validation = project.LastCompositionValidation;
            summary.ValidationStatus = validation?.Status ?? CompositionValidationStatus.Valid;
            var itemCount = project.ShowroomItemIds?.Count ?? 0;
            summary.PresentationStepCount = project.GeneratedPresentationSteps?.Count ?? 0;

            var themeService = ServiceRegistry.Instance.Get<IVisualThemeService>();
            if (themeService != null && !string.IsNullOrEmpty(project.SelectedThemeId))
            {
                var theme = themeService.GetById(project.SelectedThemeId);
                summary.ThemeName = theme?.Name ?? "";
            }
            summary.PresetName = "";

            var pricingService = ServiceRegistry.Instance.Get<IProposalPricingService>();
            var pricing = pricingService?.GetPricingSummary(project);
            var total = pricing?.TotalEstimated ?? 0f;
            summary.BudgetLevel = total < 4000f ? "Baixo" : total < 12000f ? "Médio" : "Alto";

            summary.Strengths = new List<string>();
            if (itemCount > 0) summary.Strengths.Add("Itens na proposta");
            if (!string.IsNullOrEmpty(summary.ThemeName)) summary.Strengths.Add("Tema definido");
            if (summary.PresentationStepCount > 0) summary.Strengths.Add("Narrativa de apresentação gerada");
            if (summary.ValidationStatus == CompositionValidationStatus.Valid) summary.Strengths.Add("Composição válida");
            if ((pricing?.SupplierCount ?? 0) > 0) summary.Strengths.Add("Fornecedores envolvidos");

            var brief = project.ClientBrief;
            if (brief != null && brief.EstimatedBudgetTarget > 0)
            {
                var ratio = total / brief.EstimatedBudgetTarget;
                if (ratio <= 1.2f && ratio >= 0.8f)
                {
                    summary.BudgetWithinTarget = true;
                    summary.Strengths.Add("Dentro do orçamento alvo");
                }
                else if (ratio > 1.3f)
                    summary.Warnings.Add("Acima do orçamento alvo");
            }

            if (brief != null && !string.IsNullOrWhiteSpace(brief.PreferredMood))
            {
                var themeMood = themeService?.GetById(project.SelectedThemeId)?.Mood ?? "";
                var preferred = (brief.PreferredMood ?? "").Trim();
                if (!string.IsNullOrEmpty(themeMood) && themeMood.Trim().IndexOf(preferred, System.StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    summary.MoodMatchesBrief = true;
                    summary.Strengths.Add("Mood alinhado ao desejado");
                }
            }

            summary.Warnings = summary.Warnings ?? new List<string>();
            if (summary.ValidationStatus == CompositionValidationStatus.HasWarnings)
                summary.Warnings.Add("Composição com avisos");
            if (validation?.Warnings != null)
                foreach (var w in validation.Warnings)
                    if (!string.IsNullOrEmpty(w.Message))
                        summary.Warnings.Add(w.Message);
            if (summary.ValidationStatus == CompositionValidationStatus.Invalid && validation?.Inconsistencies != null)
                foreach (var i in validation.Inconsistencies)
                    if (!string.IsNullOrEmpty(i.Message))
                        summary.Warnings.Add(i.Message);

            summary.MissingElements = new List<string>();
            if (string.IsNullOrEmpty(summary.ThemeName)) summary.MissingElements.Add("Tema não selecionado");
            if (summary.PresentationStepCount == 0) summary.MissingElements.Add("Narrativa não gerada");
            if (summary.ValidationStatus == CompositionValidationStatus.Invalid) summary.MissingElements.Add("Corrigir inconsistências da composição");
            if (itemCount == 0) summary.MissingElements.Add("Nenhum item na proposta");

            summary.IsReadyForPresentation = summary.ValidationStatus != CompositionValidationStatus.Invalid
                && itemCount > 0
                && (!string.IsNullOrEmpty(summary.ThemeName) || summary.PresentationStepCount > 0);

            var capacityService = ServiceRegistry.Instance.Get<ISpaceCapacityEvaluationService>();
            var activeProposal = project.GetActiveProposal();
            if (capacityService != null && activeProposal != null)
            {
                var cap = capacityService.Evaluate(project, activeProposal);
                if (cap.GuestCountFromBrief > 0)
                {
                    if (cap.OverCapacity)
                        summary.CapacitySummary = "Proposta acima da capacidade estimada para " + cap.GuestCountFromBrief + " convidados.";
                    else if (cap.FitsAtLimit)
                        summary.CapacitySummary = "Layout no limite da capacidade (" + cap.RecommendedRangeText + ").";
                    else if (cap.FitsComfortably)
                        summary.CapacitySummary = "Layout confortável para " + cap.GuestCountFromBrief + " convidados (" + cap.RecommendedRangeText + ").";
                    else
                        summary.CapacitySummary = "Capacidade estimada: " + cap.RecommendedRangeText + ".";
                }
                else
                    summary.CapacitySummary = "Capacidade estimada: " + (cap.RecommendedRangeText ?? "—") + ". Informe convidados no briefing.";
            }
            else
                summary.CapacitySummary = "";

            var flowService = ServiceRegistry.Instance.Get<IEventFlowEvaluationService>();
            if (flowService != null && activeProposal != null)
            {
                var flow = flowService.Evaluate(project, activeProposal);
                if (flow.OverallFlowStatus == FlowStatus.Critical)
                    summary.FlowSummary = "Risco crítico de fluxo: gargalos ou acesso de serviço inadequado.";
                else if (flow.OverallFlowStatus == FlowStatus.Warning)
                    summary.FlowSummary = "Atenção ao fluxo: possíveis gargalos ou acesso de serviço a revisar.";
                else if (flow.OverallFlowStatus == FlowStatus.Good)
                    summary.FlowSummary = "Fluxo e logística operacional adequados.";
                else
                    summary.FlowSummary = "";
            }
            else
                summary.FlowSummary = "";

            var timelineService = ServiceRegistry.Instance.Get<IEventSetupTimelineService>();
            if (timelineService != null && activeProposal != null)
            {
                var timeline = timelineService.Evaluate(project, activeProposal);
                var minutes = timeline.EstimatedTotalSetupMinutes;
                var hours = minutes / 60;
                var mins = minutes % 60;
                var timeStr = hours > 0 ? hours + "h" + (mins > 0 ? " " + mins + "min" : "") : minutes + " min";
                if (timeline.ExecutionReadinessStatus == ExecutionReadinessStatus.NotReady)
                    summary.SetupTimelineSummary = "Montagem estimada " + timeStr + "; dependências ou riscos a resolver antes da execução.";
                else if (timeline.ExecutionReadinessStatus == ExecutionReadinessStatus.Warning)
                    summary.SetupTimelineSummary = "Montagem estimada " + timeStr + "; atenção a passos críticos ou tempo elevado.";
                else if (timeline.ExecutionReadinessStatus == ExecutionReadinessStatus.Ready)
                    summary.SetupTimelineSummary = "Montagem estimada " + timeStr + "; pronta para execução.";
                else
                    summary.SetupTimelineSummary = "";
            }
            else
                summary.SetupTimelineSummary = "";

            var coverageService = ServiceRegistry.Instance.Get<ISupplierCoverageEvaluationService>();
            if (coverageService != null && activeProposal != null)
            {
                var coverage = coverageService.Evaluate(project, activeProposal);
                if (coverage.CoverageScore >= 80 && (coverage.MissingSupplierCapabilities?.Count ?? 0) == 0)
                    summary.SupplierCoverageSummary = "Cobertura operacional adequada pelos fornecedores.";
                else if ((coverage.MissingSupplierCapabilities?.Count ?? 0) > 0)
                    summary.SupplierCoverageSummary = "Lacunas de cobertura: " + coverage.MissingSupplierCapabilities.Count + " capacidade(s) ausente(s) ou insuficiente(s).";
                else if (coverage.CoverageWarnings?.Count > 0)
                    summary.SupplierCoverageSummary = "Cobertura com avisos (ex.: dependência em poucos fornecedores).";
                else
                    summary.SupplierCoverageSummary = "Score de cobertura: " + coverage.CoverageScore + "%.";
            }
            else
                summary.SupplierCoverageSummary = "";

            var packageService = ServiceRegistry.Instance.Get<ICommercialPackageService>();
            if (packageService != null && activeProposal != null)
            {
                var pkg = string.IsNullOrEmpty(activeProposal.SelectedCommercialPackageId) ? null : packageService.GetById(activeProposal.SelectedCommercialPackageId);
                var total = activeProposal.TotalEstimatedPrice;
                if (pkg == null)
                    summary.CommercialReadingSummary = "Proposta sem pacote comercial definido.";
                else if (total < pkg.TargetBudgetRangeMin)
                    summary.CommercialReadingSummary = "Proposta abaixo do potencial do tier " + pkg.Tier + "; possibilidade de upsell.";
                else if (total >= pkg.TargetBudgetRangeMin && total <= pkg.TargetBudgetRangeMax)
                    summary.CommercialReadingSummary = "Proposta bem enquadrada no tier " + pkg.Tier + ".";
                else if (total > pkg.TargetBudgetRangeMax)
                    summary.CommercialReadingSummary = "Proposta acima do orçamento-alvo do tier; possibilidade de downsell.";
                else
                    summary.CommercialReadingSummary = "Pacote " + pkg.Name + " (" + pkg.Tier + ").";
            }
            else
                summary.CommercialReadingSummary = "";

            var momentPlanningService = ServiceRegistry.Instance.Get<IEventMomentPlanningService>();
            if (momentPlanningService != null && activeProposal != null)
            {
                if (activeProposal.MomentPlans == null || activeProposal.MomentPlans.Count == 0)
                {
                    var plans = momentPlanningService.GenerateMomentPlan(project, activeProposal);
                    activeProposal.MomentPlans = plans != null ? new List<ProposalMomentPlan>(plans) : new List<ProposalMomentPlan>();
                }
                var count = activeProposal.MomentPlans?.Count ?? 0;
                summary.MomentPlanCount = count;
                var withContent = activeProposal.MomentPlans?.Count(p => (p.RelatedShowroomItemIds?.Count ?? 0) > 0 || (p.KeySupplierIds?.Count ?? 0) > 0) ?? 0;
                if (count == 0)
                    summary.JourneySummary = "Jornada por momentos não gerada.";
                else if (withContent >= 4)
                    summary.JourneySummary = "Jornada com " + count + " fases; bom equilíbrio de momentos.";
                else if (withContent >= 1)
                    summary.JourneySummary = "Jornada com " + count + " fases; possíveis lacunas em fases importantes.";
                else
                    summary.JourneySummary = "Jornada com " + count + " fases; lacunas em fases importantes (sem itens/fornecedores por fase).";
            }
            else
            {
                summary.MomentPlanCount = 0;
                summary.JourneySummary = "";
            }

            var transitionService = ServiceRegistry.Instance.Get<IEventMomentTransitionService>();
            if (transitionService != null && activeProposal != null)
            {
                if (activeProposal.MomentTransitions == null || activeProposal.MomentTransitions.Count == 0)
                {
                    var transitions = transitionService.GenerateTransitions(project, activeProposal);
                    activeProposal.MomentTransitions = transitions != null ? new List<EventMomentTransition>(transitions) : new List<EventMomentTransition>();
                }
                var transList = activeProposal.MomentTransitions ?? new List<EventMomentTransition>();
                summary.TransitionCount = transList.Count;
                if (transList.Count > 0)
                {
                    var sum = 0;
                    foreach (var t in transList) sum += t.SmoothnessScore;
                    summary.AverageSmoothnessScore = sum / transList.Count;
                    var reconfigCount = transList.Count(t => t.RequiresSpaceReset);
                    var coordCount = transList.Count(t => t.RequiresSupplierCoordination);
                    if (summary.AverageSmoothnessScore >= 75 && reconfigCount == 0)
                        summary.TransitionSummary = "Jornada fluida; transições coerentes.";
                    else if (reconfigCount > 2)
                        summary.TransitionSummary = reconfigCount + " reconfigurações críticas entre fases; planejar passagens.";
                    else if (coordCount > 2)
                        summary.TransitionSummary = "Atenção ao atrito operacional: " + coordCount + " transições exigem coordenação de fornecedores.";
                    else if (summary.AverageSmoothnessScore >= 60)
                        summary.TransitionSummary = transList.Count + " transições; fluidez média " + summary.AverageSmoothnessScore + ".";
                    else
                        summary.TransitionSummary = "Transições com atrito; revisar sequência ou zonas.";
                }
                else
                {
                    summary.AverageSmoothnessScore = 0;
                    summary.TransitionSummary = "";
                }
            }
            else
            {
                summary.TransitionCount = 0;
                summary.AverageSmoothnessScore = 0;
                summary.TransitionSummary = "";
            }

            var guidedTourService = ServiceRegistry.Instance.Get<IProposalGuidedTourService>();
            if (guidedTourService != null && activeProposal != null)
            {
                if (activeProposal.GuidedTourSteps == null || activeProposal.GuidedTourSteps.Count == 0)
                {
                    var steps = guidedTourService.GenerateGuidedTour(project, activeProposal);
                    activeProposal.GuidedTourSteps = steps != null ? new List<ProposalGuidedTourStep>(steps) : new List<ProposalGuidedTourStep>();
                }
                var tourSteps = activeProposal.GuidedTourSteps ?? new List<ProposalGuidedTourStep>();
                summary.GuidedTourStepCount = tourSteps.Count;
                summary.ReadyForGuidedPresentation = tourSteps.Count >= 3 && summary.IsReadyForPresentation;
                if (tourSteps.Count >= 5)
                    summary.GuidedTourSummary = "Roteiro guiado claro com " + tourSteps.Count + " passos; pronta para apresentação ao cliente.";
                else if (tourSteps.Count >= 3)
                    summary.GuidedTourSummary = "Roteiro com " + tourSteps.Count + " passos; adequado para visita guiada.";
                else if (tourSteps.Count > 0)
                    summary.GuidedTourSummary = tourSteps.Count + " passos no roteiro; completar narrativa e momentos para reforçar.";
                else
                    summary.GuidedTourSummary = "Roteiro não gerado; gere narrativa e momentos primeiro.";
            }
            else
            {
                summary.GuidedTourStepCount = 0;
                summary.ReadyForGuidedPresentation = false;
                summary.GuidedTourSummary = "";
            }

            var hotspotService = ServiceRegistry.Instance.Get<IProposalVisualHotspotService>();
            if (hotspotService != null && activeProposal != null)
            {
                if (activeProposal.VisualHotspots == null || activeProposal.VisualHotspots.Count == 0)
                {
                    var hotspots = hotspotService.GenerateHotspots(project, activeProposal);
                    activeProposal.VisualHotspots = hotspots != null ? new List<ProposalVisualHotspot>(hotspots) : new List<ProposalVisualHotspot>();
                }
                var hotspotList = activeProposal.VisualHotspots ?? new List<ProposalVisualHotspot>();
                summary.VisualHotspotCount = hotspotList.Count;
                var primary = hotspotList.OrderBy(h => h.HighlightPriority).FirstOrDefault();
                summary.PrimaryHotspotTitle = primary?.Title ?? "";
                summary.HasPremiumHotspots = hotspotList.Any(h => h.IsPremiumUpsell);
                if (hotspotList.Count >= 5)
                    summary.VisualHotspotSummary = hotspotList.Count + " pontos de destaque; alto impacto visual.";
                else if (hotspotList.Count >= 3)
                    summary.VisualHotspotSummary = hotspotList.Count + " hotspots; bom potencial de encantamento.";
                else if (hotspotList.Count > 0)
                    summary.VisualHotspotSummary = hotspotList.Count + " hotspots; completar roteiro para reforçar.";
                else
                    summary.VisualHotspotSummary = "Nenhum hotspot; gere o roteiro guiado primeiro.";
            }
            else
            {
                summary.VisualHotspotCount = 0;
                summary.PrimaryHotspotTitle = "";
                summary.HasPremiumHotspots = false;
                summary.VisualHotspotSummary = "";
            }

            var sceneStateService = ServiceRegistry.Instance.Get<IProposalSceneStateService>();
            if (sceneStateService != null && activeProposal != null)
            {
                if (activeProposal.SceneStates == null || activeProposal.SceneStates.Count == 0)
                {
                    var states = sceneStateService.GenerateSceneStates(project, activeProposal);
                    activeProposal.SceneStates = states != null ? new List<ProposalSceneState>(states) : new List<ProposalSceneState>();
                }
                var stateList = activeProposal.SceneStates ?? new List<ProposalSceneState>();
                summary.SceneStateCount = stateList.Count;
                summary.HasStructuredVisualEvolution = stateList.Count >= 2;
                if (stateList.Count >= 4)
                    summary.SceneStateSummary = stateList.Count + " estados por fase; evolução visual estruturada.";
                else if (stateList.Count >= 2)
                    summary.SceneStateSummary = stateList.Count + " estados de cena; continuidade visual presente.";
                else if (stateList.Count == 1)
                    summary.SceneStateSummary = "1 estado de cena; complete momentos e transições para evolução.";
                else
                    summary.SceneStateSummary = "Sem estados de cena; preencha momentos do evento.";
            }
            else
            {
                summary.SceneStateCount = 0;
                summary.HasStructuredVisualEvolution = false;
                summary.SceneStateSummary = "";
            }

            var mrPlanningService = ServiceRegistry.Instance.Get<IMRPresentationPlanningService>();
            if (mrPlanningService != null && activeProposal != null)
            {
                var mrPlan = mrPlanningService.GeneratePlan(project, activeProposal);
                if (mrPlan != null)
                {
                    activeProposal.MRPresentationPlan = mrPlan;
                    summary.ReadyForMRMapping = mrPlan.ReadyForMRMapping;
                    summary.MRPresentationModeSuggested = mrPlan.TargetExperienceMode.ToString();
                }
            }

            return summary;
        }

        public ProposalVersionSnapshot CreateSnapshot(EventProject project, string versionName)
        {
            var snapshot = new ProposalVersionSnapshot
            {
                Id = Guid.NewGuid().ToString(),
                Name = string.IsNullOrEmpty(versionName) ? "Versão" : versionName,
                CreatedAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm"),
                ThemeId = project?.SelectedThemeId,
                PresetId = project?.AppliedPresetId,
                ShowroomItemCount = project?.ShowroomItemIds?.Count ?? 0,
                ValidationStatus = project?.LastCompositionValidation?.Status ?? CompositionValidationStatus.Valid,
                Notes = null
            };

            var pricingService = ServiceRegistry.Instance.Get<IProposalPricingService>();
            var pricing = pricingService?.GetPricingSummary(project);
            if (pricing != null)
            {
                snapshot.TotalEstimatedPrice = pricing.TotalEstimated;
                snapshot.SupplierCount = pricing.SupplierCount;
            }
            return snapshot;
        }
    }
}
