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

namespace EventsAppQuest.Infrastructure.Services
{
    /// <summary>
    /// Compara duas propostas ao longo da jornada com base em scene states, transições, hotspots, fit score e review.
    /// </summary>
    public class MockProposalTemporalComparisonService : IProposalTemporalComparisonService
    {
        public ProposalTemporalComparison Compare(EventProject project, string baseProposalId, string comparedProposalId)
        {
            var result = new ProposalTemporalComparison
            {
                BaseProposalId = baseProposalId,
                ComparedProposalId = comparedProposalId
            };
            if (project?.Proposals == null || string.IsNullOrEmpty(baseProposalId) || string.IsNullOrEmpty(comparedProposalId))
                return result;

            var baseP = project.Proposals.FirstOrDefault(p => p.Id == baseProposalId);
            var comparedP = project.Proposals.FirstOrDefault(p => p.Id == comparedProposalId);
            if (baseP == null || comparedP == null)
                return result;

            var sceneStateService = ServiceRegistry.Instance.Get<IProposalSceneStateService>();
            var planningService = ServiceRegistry.Instance.Get<IEventMomentPlanningService>();

            if (sceneStateService != null)
            {
                if (baseP.SceneStates == null || baseP.SceneStates.Count == 0)
                    baseP.SceneStates = sceneStateService.GenerateSceneStates(project, baseP)?.ToList() ?? new List<ProposalSceneState>();
                if (comparedP.SceneStates == null || comparedP.SceneStates.Count == 0)
                    comparedP.SceneStates = sceneStateService.GenerateSceneStates(project, comparedP)?.ToList() ?? new List<ProposalSceneState>();
            }

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

            var baseStates = (baseP.SceneStates ?? new List<ProposalSceneState>()).ToDictionary(s => s.RelatedPhaseId);
            var comparedStates = (comparedP.SceneStates ?? new List<ProposalSceneState>()).ToDictionary(s => s.RelatedPhaseId);
            var allPhaseIds = baseStates.Keys.Union(comparedStates.Keys).Distinct().ToList();
            var orderedPhaseIds = phases.Where(p => allPhaseIds.Contains(p.Id)).Select(p => p.Id).ToList();
            if (orderedPhaseIds.Count == 0)
                orderedPhaseIds = allPhaseIds;

            var stronger = new List<string>();
            var weaker = new List<string>();

            foreach (var phaseId in orderedPhaseIds)
            {
                var phase = phaseById.TryGetValue(phaseId, out var ph) ? ph : null;
                var phaseName = phase?.Name ?? phaseId;
                baseStates.TryGetValue(phaseId, out var baseState);
                comparedStates.TryGetValue(phaseId, out var comparedState);

                var baseSummary = SceneStateSummary(baseState);
                var comparedSummary = SceneStateSummary(comparedState);
                var diffs = new List<string>();
                string better = null;
                if (baseState != null && comparedState != null)
                {
                    var baseItems = baseState.ActiveShowroomItemIds?.Count ?? 0;
                    var compItems = comparedState.ActiveShowroomItemIds?.Count ?? 0;
                    if (baseItems != compItems) diffs.Add("Itens: base " + baseItems + ", comparada " + compItems);
                    var baseHotspots = baseState.PrimaryHotspotIds?.Count ?? 0;
                    var compHotspots = comparedState.PrimaryHotspotIds?.Count ?? 0;
                    if (baseHotspots != compHotspots) diffs.Add("Hotspots destaque: base " + baseHotspots + ", comparada " + compHotspots);
                    if (baseItems > compItems || (baseItems == compItems && baseHotspots > compHotspots)) better = "Base";
                    else if (compItems > baseItems || compHotspots > baseHotspots) better = "Compared";
                    if (better == "Base") stronger.Add(phaseName);
                    else if (better == "Compared") weaker.Add(phaseName);
                }
                else if (baseState != null) { better = "Base"; stronger.Add(phaseName); diffs.Add("Comparada sem estado nesta fase."); }
                else if (comparedState != null) { better = "Compared"; weaker.Add(phaseName); diffs.Add("Base sem estado nesta fase."); }

                result.PhaseComparisons.Add(new ProposalPhaseComparison
                {
                    PhaseId = phaseId,
                    BaseSceneStateSummary = baseSummary ?? "—",
                    ComparedSceneStateSummary = comparedSummary ?? "—",
                    KeyDifferences = diffs,
                    BetterOption = better,
                    Notes = phase != null ? phase.Description : null
                });
            }

            result.StrongerMoments = stronger;
            result.WeakerMoments = weaker;

            var baseTrans = baseP.MomentTransitions ?? new List<EventMomentTransition>();
            var compTrans = comparedP.MomentTransitions ?? new List<EventMomentTransition>();
            var baseSmooth = baseTrans.Count > 0 ? baseTrans.Sum(t => t.SmoothnessScore) / baseTrans.Count : 0;
            var compSmooth = compTrans.Count > 0 ? compTrans.Sum(t => t.SmoothnessScore) / compTrans.Count : 0;
            result.BetterOperationalContinuity = compSmooth > baseSmooth ? comparedProposalId : baseProposalId;

            var baseStatesCount = baseP.SceneStates?.Count ?? 0;
            var compStatesCount = comparedP.SceneStates?.Count ?? 0;
            var baseHasStruct = baseP.ReviewSummary?.HasStructuredVisualEvolution ?? (baseStatesCount >= 2);
            var compHasStruct = comparedP.ReviewSummary?.HasStructuredVisualEvolution ?? (compStatesCount >= 2);
            if (compStatesCount > baseStatesCount || (compHasStruct && !baseHasStruct))
                result.BetterVisualContinuity = comparedProposalId;
            else
                result.BetterVisualContinuity = baseProposalId;

            var baseHot = baseP.VisualHotspots?.Count ?? 0;
            var compHot = comparedP.VisualHotspots?.Count ?? 0;
            var baseFit = baseP.FitScore?.OverallScore ?? 0;
            var compFit = comparedP.FitScore?.OverallScore ?? 0;
            if (compHot > baseHot || compFit > baseFit)
                result.BetterSalesImpact = comparedProposalId;
            else
                result.BetterSalesImpact = baseProposalId;

            var baseName = baseP.Name ?? "Base";
            var compName = comparedP.Name ?? "Comparada";
            result.OverallExperienceDifferenceSummary = string.Format(
                "Base ({0}): {1} estados de cena, fluidez {2}. Comparada ({3}): {4} estados, fluidez {5}. {6}",
                baseName, baseStatesCount, baseSmooth, compName, compStatesCount, compSmooth,
                result.BetterVisualContinuity == comparedProposalId ? "Comparada com melhor jornada visual." : "Base com melhor jornada visual.");

            return result;
        }

        private static string SceneStateSummary(ProposalSceneState s)
        {
            if (s == null) return null;
            var parts = new List<string> { s.Name ?? s.RelatedPhaseId };
            var n = (s.ActiveShowroomItemIds?.Count ?? 0) + (s.PrimaryHotspotIds?.Count ?? 0);
            if (n > 0) parts.Add(n + " itens/hotspots");
            if (!string.IsNullOrEmpty(s.TransitionFromPreviousSummary)) parts.Add("Trans.: " + s.TransitionFromPreviousSummary);
            return string.Join("; ", parts);
        }
    }
}
