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

namespace EventsAppQuest.Infrastructure.Services
{
    /// <summary>
    /// Recomenda a melhor proposta com base em fit score, review, comparação temporal, orçamento, mood e prontidão.
    /// </summary>
    public class MockProposalRecommendationService : IProposalRecommendationService
    {
        public ProposalRecommendationSummary Recommend(EventProject project)
        {
            var result = new ProposalRecommendationSummary();
            if (project?.Proposals == null || project.Proposals.Count == 0)
                return result;

            var scoringService = ServiceRegistry.Instance.Get<IProposalFitScoringService>();
            var temporal = project.LastTemporalComparison;

            foreach (var p in project.Proposals)
            {
                if (p.FitScore == null && scoringService != null)
                    p.FitScore = scoringService.CalculateScore(project, p);
            }

            var scored = new List<(EventProjectProposal p, int score)>();
            foreach (var p in project.Proposals)
            {
                var score = p.FitScore?.OverallScore ?? 0;
                var review = p.ReviewSummary ?? (p.Id == project.ActiveProposalId ? project.LastProposalReviewSummary : null);
                if (review != null)
                {
                    if (review.IsReadyForPresentation) score += 15;
                    if (review.BudgetWithinTarget) score += 5;
                    if (review.MoodMatchesBrief) score += 5;
                    if (review.HasStructuredVisualEvolution) score += 5;
                }
                if (temporal != null)
                {
                    if (temporal.BetterVisualContinuity == p.Id) score += 5;
                    if (temporal.BetterOperationalContinuity == p.Id) score += 5;
                    if (temporal.BetterSalesImpact == p.Id) score += 5;
                }
                scored.Add((p, score));
            }

            var ordered = scored.OrderByDescending(x => x.score).ToList();
            var best = ordered.FirstOrDefault().p;
            var second = ordered.Count > 1 ? ordered[1].p : null;
            var bestScore = ordered.FirstOrDefault().score;
            var secondScore = ordered.Count > 1 ? ordered[1].score : 0;

            if (best == null)
                return result;

            result.RecommendedProposalId = best.Id;
            result.RecommendationConfidenceScore = (bestScore - secondScore) >= 15 ? 85 : (bestScore > secondScore ? 72 : 60);
            result.SecondaryOptionId = second?.Id;
            result.SecondaryOptionReason = second != null
                ? (secondScore >= bestScore - 5 ? "Alternativa próxima; considerar se prioridade for orçamento ou operação." : "Segunda opção se a recomendada não for aprovada.")
                : null;

            var bestReview = best.ReviewSummary ?? (best.Id == project.ActiveProposalId ? project.LastProposalReviewSummary : null);
            var bestName = best.Name ?? "Proposta recomendada";

            result.ExecutiveSummary = string.Format("{0} é a opção mais adequada ao contexto atual: melhor aderência ao briefing (score {1}), {2}.",
                bestName,
                best.FitScore?.OverallScore ?? 0,
                bestReview?.IsReadyForPresentation == true ? "pronta para apresentação" : "revisar elementos antes de apresentar");

            result.WhyItWins = new List<string>();
            if (best.FitScore?.Highlights != null)
                result.WhyItWins.AddRange(best.FitScore.Highlights.Take(3));
            if (bestReview?.Strengths != null)
                foreach (var s in bestReview.Strengths.Take(2))
                    if (!result.WhyItWins.Contains(s)) result.WhyItWins.Add(s);
            if (temporal != null && (temporal.BetterVisualContinuity == best.Id || temporal.BetterSalesImpact == best.Id))
                result.WhyItWins.Add("Melhor jornada visual ou impacto comercial na comparação temporal.");
            if (result.WhyItWins.Count == 0)
                result.WhyItWins.Add("Melhor score de aderência entre as propostas do projeto.");

            result.Tradeoffs = new List<string>();
            if (best.FitScore?.Gaps != null)
                result.Tradeoffs.AddRange(best.FitScore.Gaps.Take(2));
            if (bestReview?.Warnings != null)
                foreach (var w in bestReview.Warnings.Take(2))
                    if (!result.Tradeoffs.Contains(w)) result.Tradeoffs.Add(w);
            if (bestReview != null && !bestReview.BudgetWithinTarget && project.ClientBrief?.EstimatedBudgetTarget > 0)
                result.Tradeoffs.Add("Orçamento acima do alvo do briefing.");
            if (result.Tradeoffs.Count == 0)
                result.Tradeoffs.Add("Nenhum tradeoff crítico identificado.");

            result.BudgetPositioning = bestReview?.BudgetWithinTarget == true
                ? "Dentro ou próximo do orçamento alvo do briefing."
                : (best.FitScore?.BudgetFitScore >= 70 ? "Orçamento em faixa aceitável." : "Atenção ao orçamento em relação ao alvo.");

            result.ExperiencePositioning = bestReview?.HasStructuredVisualEvolution == true
                ? "Evolução visual estruturada ao longo do evento; jornada clara."
                : (best.SceneStates?.Count >= 2 ? "Jornada com mais de uma fase definida." : "Completar momentos e cena para reforçar experiência.");

            result.OperationalPositioning = !string.IsNullOrEmpty(bestReview?.FlowSummary) || !string.IsNullOrEmpty(bestReview?.SetupTimelineSummary)
                ? (bestReview.FlowSummary ?? "") + (string.IsNullOrEmpty(bestReview.SetupTimelineSummary) ? "" : " " + bestReview.SetupTimelineSummary)
                : "Avaliar fluxo e cronograma na revisão da proposta.";
            if (string.IsNullOrWhiteSpace(result.OperationalPositioning))
                result.OperationalPositioning = "Revisar fluxo e montagem para posicionamento operacional.";

            result.SuggestedSalesAngle = bestReview?.HasStructuredVisualEvolution == true && (best.VisualHotspots?.Count ?? 0) > 0
                ? "Destacar a experiência completa ao longo do evento e os pontos de destaque visuais."
                : "Destacar aderência ao briefing e valor da proposta para o evento.";

            return result;
        }
    }
}
