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

namespace EventsAppQuest.Web.Application
{
    /// <summary>
    /// Priorização executiva entre múltiplos ciclos e fila gerencial de atenção. Agregador: usa closure, métricas, alertas, gargalos, recuperação, simulação e resumo executivo.
    /// </summary>
    public static class EventCyclePortfolioPriorityController
    {
        /// <summary>Gera estado de priorização da carteira (fila de atenção).</summary>
        public static EventCyclePortfolioPriorityState BuildPortfolioPriority(
            IReadOnlyList<ProducerOrder> orders,
            IReadOnlyList<SalesOpportunity> opportunities,
            IReadOnlyList<ProposalRecord> proposals,
            IReadOnlyList<SessionRecord> sessions,
            IReadOnlyList<FollowUpTask> followUpTasks)
        {
            var dashboardStates = EventCycleDashboardController.BuildDashboard(orders, opportunities, proposals, sessions);
            var closures = EventCycleClosureController.EvaluateClosure(orders, opportunities, proposals, sessions, followUpTasks);
            var metricsList = EventCycleMetricsController.CalculateMetrics(orders, opportunities, proposals, sessions, followUpTasks);
            var alertStates = EventCycleAlertController.EvaluateAllAlerts(orders, opportunities, proposals, sessions, followUpTasks);
            var bottleneckStates = EventCycleBottleneckController.EvaluateBottlenecks(orders, opportunities, proposals, sessions, followUpTasks);
            var recoveryPlans = EventCycleRecoveryPlanController.GenerateRecoveryPlans(orders, opportunities, proposals, sessions, followUpTasks);
            var scenarioComparisons = EventCycleScenarioSimulationController.RunSimulations(orders, opportunities, proposals, sessions, followUpTasks);
            var summaries = EventCycleExecutiveSummaryController.GenerateSummaries(orders, opportunities, proposals, sessions, followUpTasks);

            var items = new List<EventCyclePortfolioItem>();
            var now = DateTime.UtcNow;

            foreach (var state in dashboardStates)
            {
                var cycleId = state.ProducerOrderId ?? state.CycleId;
                var opportunity = opportunities?.FirstOrDefault(o => o.Id == state.OpportunityId);
                var closure = closures?.FirstOrDefault(c => c.CycleId == cycleId);
                var metrics = metricsList?.FirstOrDefault(m => m.CycleId == cycleId);
                var alertState = alertStates?.FirstOrDefault(a => a.CycleId == cycleId);
                var bottleneckState = bottleneckStates?.FirstOrDefault(b => b.CycleId == cycleId);
                var recoveryPlan = recoveryPlans?.FirstOrDefault(r => r.CycleId == cycleId);
                var scenarioComp = scenarioComparisons?.FirstOrDefault(s => s.CycleId == cycleId);
                var summary = summaries?.FirstOrDefault(s => s.CycleId == cycleId);

                var item = BuildPortfolioItem(cycleId, state, opportunity, closure, metrics, alertState, bottleneckState, recoveryPlan, scenarioComp, summary, now);
                if (item != null)
                    items.Add(item);
            }

            items = items.OrderByDescending(i => i.PriorityScore).ToList();

            EventCyclePortfolioItem highestPriority = items.FirstOrDefault();
            EventCyclePortfolioItem highestRisk = items.FirstOrDefault(i => (i.RiskLevelLabel ?? "").Contains("Bloqueado") || (i.RiskLevelLabel ?? "").Contains("Critical")) ?? items.FirstOrDefault(i => (i.RiskLevelLabel ?? "").Contains("Risco")) ?? highestPriority;
            EventCyclePortfolioItem bestRecovery = items.Where(i => !string.IsNullOrEmpty(i.TopRecoveryAction) && !string.IsNullOrEmpty(i.SimulatedBestScenarioDelta)).OrderByDescending(i => i.PriorityScore).FirstOrDefault() ?? items.FirstOrDefault(i => !string.IsNullOrEmpty(i.TopRecoveryAction));
            EventCyclePortfolioItem nearestToClose = items.FirstOrDefault(i => (i.ClosureStatus ?? "").Contains("Aceite") || (i.CommercialStageLabel ?? "").ToLowerInvariant().Contains("final")) ?? items.FirstOrDefault(i => i.OverallCyclePerformanceScore >= 70);

            var avgScore = items.Count > 0 ? items.Average(i => i.PriorityScore) : 0;
            var summaryText = items.Count == 0
                ? "Nenhum ciclo na carteira."
                : $"{items.Count} caso(s). Prioritário: {(highestPriority?.Title ?? "—")} (score {highestPriority?.PriorityScore ?? 0}). Crítico: {(highestRisk?.Title ?? "—")}. Melhor recuperação: {(bestRecovery?.Title ?? "—")}.";

            return new EventCyclePortfolioPriorityState
            {
                Items = items,
                HighestPriorityItem = highestPriority,
                HighestRiskItem = highestRisk,
                BestRecoveryOpportunity = bestRecovery ?? highestPriority,
                NearestToCloseItem = nearestToClose ?? highestPriority,
                AveragePriorityScore = Math.Round(avgScore, 1),
                PrioritizationSummary = summaryText,
                LastPrioritizedAt = now
            };
        }

        private static EventCyclePortfolioItem BuildPortfolioItem(
            string cycleId,
            EventCycleDashboardState dashboardState,
            SalesOpportunity opportunity,
            EventCycleClosureState closureState,
            EventCycleMetricsState metricsState,
            EventCycleAlertState alertState,
            EventCycleBottleneckState bottleneckState,
            EventCycleRecoveryPlanState recoveryPlanState,
            EventCycleScenarioComparisonState scenarioComparisonState,
            EventCycleExecutiveSummary executiveSummary,
            DateTime? lastUpdatedAt)
        {
            if (dashboardState == null) return null;

            var title = opportunity?.Title ?? ("Ciclo " + cycleId);
            var commercialStage = dashboardState.CommercialStageLabel ?? dashboardState.OverallCycleStatus ?? "—";
            var closureStatus = closureState?.ClosureStatus ?? "—";
            var performanceScore = metricsState?.OverallCyclePerformanceScore ?? 0;

            var riskLabel = "Normal";
            if (closureState?.IsCycleBlocked == true) riskLabel = "Bloqueado";
            else if (closureState?.IsCycleAtRisk == true) riskLabel = "Em risco";
            else if (alertState?.BlockingAlerts > 0) riskLabel = "Alertas bloqueantes";
            else if ((alertState?.Alerts?.Count(x => x.Severity == EventCycleAlertSeverity.Critical) ?? 0) > 0) riskLabel = "Crítico";

            var bottleneckSeverity = bottleneckState?.TopPriorityBottleneck?.Severity.ToString() ?? "—";

            var topRecommended = executiveSummary?.TopRecommendedAction?.Title ?? alertState?.Alerts?.FirstOrDefault()?.SuggestedAction ?? recoveryPlanState?.PrimaryRecoveryAction?.Title ?? "—";
            var topRecovery = recoveryPlanState?.PrimaryRecoveryAction?.Title ?? "—";
            var simulatedDelta = scenarioComparisonState?.BestImprovementDelta ?? "—";

            var priorityScore = 50;
            var reasons = new List<string>();

            if (closureState?.IsCycleBlocked == true) { priorityScore += 25; reasons.Add("Ciclo bloqueado"); }
            if (closureState?.IsCycleAtRisk == true) { priorityScore += 15; reasons.Add("Em risco"); }
            if (recoveryPlanState?.IsRecoveryNeeded == true && !string.IsNullOrEmpty(simulatedDelta)) { priorityScore += 20; reasons.Add("Alto potencial de recuperação"); }
            if (dashboardState.IsExecutionCompleted && !dashboardState.IsFinalAcceptanceDone) { priorityScore += 18; reasons.Add("Perto de fechamento (aceite final)"); }
            if (closureState?.IsCycleCompleted == true && closureState?.IsCycleHealthy == true) { priorityScore -= 30; reasons.Add("Concluído e saudável"); }
            var criticalCount = (bottleneckState?.BlockingBottlenecks?.Count ?? 0) + (alertState?.Alerts?.Count(a => a.Severity == EventCycleAlertSeverity.Critical) ?? 0);
            if (criticalCount >= 2) { priorityScore += 12; reasons.Add("Múltiplos críticos"); }
            if (performanceScore < 40 && (closureState?.IsCycleCompleted != true)) { priorityScore += 10; reasons.Add("Performance baixa"); }

            priorityScore = Math.Max(0, Math.Min(100, priorityScore));
            var priorityReason = reasons.Count > 0 ? string.Join("; ", reasons) : "Prioridade normal.";

            return new EventCyclePortfolioItem
            {
                CycleId = cycleId,
                OpportunityId = dashboardState.OpportunityId,
                LeadId = dashboardState.LeadId,
                Title = title,
                CommercialStageLabel = commercialStage,
                ClosureStatus = closureStatus,
                OverallCyclePerformanceScore = performanceScore,
                RiskLevelLabel = riskLabel,
                BottleneckSeverityLabel = bottleneckSeverity,
                TopRecommendedAction = topRecommended,
                TopRecoveryAction = topRecovery,
                SimulatedBestScenarioDelta = simulatedDelta,
                PriorityScore = priorityScore,
                PriorityReason = priorityReason,
                LastUpdatedAt = lastUpdatedAt ?? dashboardState.LastUpdatedAt
            };
        }
    }
}
