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 roteiro guiado da proposta a partir de narrativa, momentos, transições, tema, pacote e review.
    /// </summary>
    public class MockProposalGuidedTourService : IProposalGuidedTourService
    {
        public IReadOnlyList<ProposalGuidedTourStep> GenerateGuidedTour(EventProject project, EventProjectProposal proposal)
        {
            var steps = new List<ProposalGuidedTourStep>();
            if (proposal == null) return steps;

            var planningService = ServiceRegistry.Instance.Get<IEventMomentPlanningService>();
            var transitionService = ServiceRegistry.Instance.Get<IEventMomentTransitionService>();
            var themeService = ServiceRegistry.Instance.Get<IVisualThemeService>();
            var packageService = ServiceRegistry.Instance.Get<ICommercialPackageService>();

            var plans = proposal.MomentPlans ?? new List<ProposalMomentPlan>();
            if (plans.Count == 0 && planningService != null)
            {
                var generated = planningService.GenerateMomentPlan(project, proposal);
                if (generated != null) { proposal.MomentPlans = new List<ProposalMomentPlan>(generated); plans = proposal.MomentPlans; }
            }
            var transitions = proposal.MomentTransitions ?? new List<EventMomentTransition>();
            if (transitions.Count == 0 && transitionService != null)
            {
                var generated = transitionService.GenerateTransitions(project, proposal);
                if (generated != null) { proposal.MomentTransitions = new List<EventMomentTransition>(generated); transitions = proposal.MomentTransitions; }
            }

            var phases = planningService?.GetAvailablePhases(project?.EventTemplateId)?.ToList() ?? new List<EventMomentPhase>();
            var phaseById = phases.ToDictionary(p => p.Id, p => p);
            var order = 0;

            var narrativeSteps = proposal.PresentationSteps ?? project?.GeneratedPresentationSteps;
            var welcomeTitle = "Bem-vindo à proposta";
            var welcomeDesc = "Apresentação da proposta e do que será mostrado.";
            if (narrativeSteps != null && narrativeSteps.Count > 0)
            {
                var first = narrativeSteps.OrderBy(s => s.DisplayOrder).FirstOrDefault();
                if (first != null)
                {
                    welcomeTitle = first.Title ?? welcomeTitle;
                    welcomeDesc = first.Description ?? welcomeDesc;
                }
            }
            steps.Add(CreateStep("tour-welcome", welcomeTitle, welcomeDesc, null, new List<string>(), new List<string>(), ProposalGuidedTourFocusType.Welcome, 3, "Esta proposta foi preparada para o seu evento.", order++, true));

            steps.Add(CreateStep("tour-space", "Visão do espaço", "Percurso pelo layout e pelas áreas do evento.", null, new List<string>(), new List<string>(), ProposalGuidedTourFocusType.SpaceOverview, 5, "O espaço está organizado para fluir entre as áreas.", order++, false));

            if (themeService != null && !string.IsNullOrEmpty(proposal.ThemeId))
            {
                var theme = themeService.GetById(proposal.ThemeId);
                if (theme != null)
                    steps.Add(CreateStep("tour-theme", "Direção estética: " + theme.Name, theme.Description ?? "", null, new List<string>(), new List<string>(), ProposalGuidedTourFocusType.ThemeHighlight, 4, "O tema " + theme.Name + " dá o tom do evento.", order++, true));
            }

            foreach (var plan in plans.OrderBy(p => phaseById.TryGetValue(p.PhaseId, out var ph) ? ph.DisplayOrder : 99))
            {
                var hasContent = (plan.RelatedShowroomItemIds?.Count ?? 0) > 0 || (plan.KeySupplierIds?.Count ?? 0) > 0;
                if (!hasContent) continue;
                var phaseName = phaseById.TryGetValue(plan.PhaseId, out var px) ? px.Name : plan.PhaseId;
                var title = "Momento: " + phaseName;
                var desc = plan.HighlightText ?? phaseName + " na jornada do evento.";
                var sales = string.IsNullOrEmpty(plan.HighlightText) ? "Destaque para " + phaseName + "." : plan.HighlightText;
                steps.Add(CreateStep("tour-moment-" + plan.PhaseId, title, desc, plan.PhaseId, plan.RelatedZoneTypes ?? new List<string>(), plan.RelatedShowroomItemIds ?? new List<string>(), ProposalGuidedTourFocusType.MomentHighlight, Math.Max(2, plan.EstimatedDurationMinutes / 10), sales, order++, plan.EstimatedDurationMinutes >= 30));
            }

            if (project?.SupplierIds != null && project.SupplierIds.Count > 0)
            {
                var supplierService = ServiceRegistry.Instance.Get<ISupplierService>();
                var names = project.SupplierIds.Select(id => supplierService?.GetById(id)?.Name).Where(n => !string.IsNullOrEmpty(n)).Take(3).ToList();
                var supplierText = names.Count > 0 ? string.Join(", ", names) : project.SupplierIds.Count + " parceiro(s)";
                steps.Add(CreateStep("tour-suppliers", "Fornecedores e parceiros", "Quem vai executar: " + supplierText + ".", null, new List<string>(), new List<string>(), ProposalGuidedTourFocusType.SupplierHighlight, 3, "Toda a operação está coberta por parceiros qualificados.", order++, false));
            }

            var review = proposal.ReviewSummary ?? project?.LastProposalReviewSummary;
            var operationalOk = review != null && (review.CapacitySummary == null || review.CapacitySummary.IndexOf("confortável", StringComparison.OrdinalIgnoreCase) >= 0 || review.FlowSummary == null || review.FlowSummary.IndexOf("adequado", StringComparison.OrdinalIgnoreCase) >= 0);
            if (operationalOk || (review?.SetupTimelineSummary != null && review.SetupTimelineSummary.IndexOf("pronta", StringComparison.OrdinalIgnoreCase) >= 0))
            {
                steps.Add(CreateStep("tour-operational", "Operação e execução", "Capacidade, fluxo e cronograma alinhados para a data do evento.", null, new List<string>(), new List<string>(), ProposalGuidedTourFocusType.OperationalConfidence, 2, "Tudo planejado para executar com segurança.", order++, false));
            }

            if (packageService != null && !string.IsNullOrEmpty(proposal.SelectedCommercialPackageId))
            {
                var pkg = packageService.GetById(proposal.SelectedCommercialPackageId);
                if (pkg != null && !string.IsNullOrEmpty(pkg.UpsellNotes))
                {
                    steps.Add(CreateStep("tour-upsell", "Possibilidade de upgrade", pkg.UpsellNotes, null, new List<string>(), new List<string>(), ProposalGuidedTourFocusType.PremiumUpsell, 2, pkg.UpsellNotes, order++, false));
                }
            }

            steps.Add(CreateStep("tour-closing", "Encerramento", "Resumo e próximos passos para fechamento.", "phase-closing", new List<string>(), new List<string>(), ProposalGuidedTourFocusType.Closing, 3, "Pronto para validar e fechar a proposta.", order++, true));

            return steps.OrderBy(s => s.DisplayOrder).ToList();
        }

        private static ProposalGuidedTourStep CreateStep(string id, string title, string description, string relatedPhaseId, List<string> zoneTypes, List<string> itemIds, ProposalGuidedTourFocusType focusType, int durationMin, string salesMessage, int displayOrder, bool isKeyMoment)
        {
            return new ProposalGuidedTourStep
            {
                Id = id,
                Title = title,
                Description = description,
                RelatedPhaseId = relatedPhaseId,
                RelatedZoneTypes = zoneTypes ?? new List<string>(),
                RelatedShowroomItemIds = itemIds ?? new List<string>(),
                FocusType = focusType,
                SuggestedDurationMinutes = durationMin,
                SalesMessage = salesMessage,
                DisplayOrder = displayOrder,
                IsKeyMoment = isKeyMoment
            };
        }
    }
}
