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

namespace EventsAppQuest.Web.Application
{
    /// <summary>
    /// Visão resumida da carteira com agrupamento por status, risco e prioridade. Agregador: usa priorização da carteira (e indiretamente closure, métricas, alertas, recuperação, simulação).
    /// </summary>
    public static class EventCyclePortfolioOverviewController
    {
        public const string GroupInProgress = "InProgress";
        public const string GroupAtRisk = "AtRisk";
        public const string GroupBlocked = "Blocked";
        public const string GroupClosingSoon = "ClosingSoon";
        public const string GroupCompleted = "Completed";
        public const string GroupCompletedWithIssues = "CompletedWithIssues";
        public const string GroupHighPriority = "HighPriority";
        public const string GroupRecoveryOpportunity = "RecoveryOpportunity";

        /// <summary>Constrói o estado da visão resumida da carteira.</summary>
        public static EventCyclePortfolioOverviewState BuildOverview(
            IReadOnlyList<ProducerOrder> orders,
            IReadOnlyList<SalesOpportunity> opportunities,
            IReadOnlyList<ProposalRecord> proposals,
            IReadOnlyList<SessionRecord> sessions,
            IReadOnlyList<FollowUpTask> followUpTasks)
        {
            var priorityState = EventCyclePortfolioPriorityController.BuildPortfolioPriority(orders, opportunities, proposals, sessions, followUpTasks);
            return BuildOverviewFromPriorityState(priorityState, DateTime.UtcNow);
        }

        /// <summary>Constrói overview a partir do estado de priorização já calculado.</summary>
        public static EventCyclePortfolioOverviewState BuildOverviewFromPriorityState(
            EventCyclePortfolioPriorityState priorityState,
            DateTime? updatedAt = null)
        {
            var now = updatedAt ?? DateTime.UtcNow;
            var items = priorityState?.Items ?? new List<EventCyclePortfolioItem>();
            var total = items.Count;

            int blocked = 0, atRisk = 0, inProgress = 0, closingSoon = 0, completed = 0, completedWithIssues = 0, highPriority = 0, recoveryOpp = 0;
            foreach (var i in items)
            {
                var risk = i.RiskLevelLabel ?? "";
                var closure = i.ClosureStatus ?? "";
                var isBlocked = risk.Contains("Bloqueado");
                var isAtRisk = risk.Contains("Em risco") || risk.Contains("Crítico") || risk.Contains("Alertas bloqueantes");
                var isCompleted = closure.Contains("Concluído") || closure.Contains("Encerrado") || closure.ToLowerInvariant().Contains("closed");
                var isClosingSoon = (i.PriorityReason ?? "").Contains("Perto de fechamento") || closure.Contains("Aceite") || (i.CommercialStageLabel ?? "").ToLowerInvariant().Contains("final");
                var hasRecovery = !string.IsNullOrEmpty(i.TopRecoveryAction) && !string.IsNullOrEmpty(i.SimulatedBestScenarioDelta);

                if (isBlocked) blocked++;
                if (isAtRisk) atRisk++;
                if (isClosingSoon) closingSoon++;
                if (isCompleted)
                {
                    completed++;
                    if (i.OverallCyclePerformanceScore < 70 || (i.TopRecommendedAction ?? "") != "—") completedWithIssues++;
                }
                else if (!isBlocked)
                    inProgress++;
                if (i.PriorityScore >= 70) highPriority++;
                if (hasRecovery) recoveryOpp++;
            }

            var groups = new List<EventCyclePortfolioGroup>();

            AddGroup(groups, items, GroupBlocked, "Bloqueados", "Ciclos bloqueados.", i => (i.RiskLevelLabel ?? "").Contains("Bloqueado"));
            AddGroup(groups, items, GroupAtRisk, "Em risco", "Ciclos em risco ou com alertas críticos.", i => { var r = i.RiskLevelLabel ?? ""; return r.Contains("Em risco") || r.Contains("Crítico") || r.Contains("Alertas bloqueantes"); });
            AddGroup(groups, items, GroupHighPriority, "Alta prioridade", "Casos com score de prioridade alto.", i => i.PriorityScore >= 70);
            AddGroup(groups, items, GroupRecoveryOpportunity, "Boa oportunidade de recuperação", "Casos com plano de recuperação e ganho simulado.", i => !string.IsNullOrEmpty(i.TopRecoveryAction) && !string.IsNullOrEmpty(i.SimulatedBestScenarioDelta));
            AddGroup(groups, items, GroupClosingSoon, "Perto de fechar", "Casos próximos do aceite final.", i => (i.PriorityReason ?? "").Contains("Perto de fechamento") || (i.ClosureStatus ?? "").Contains("Aceite") || (i.CommercialStageLabel ?? "").ToLowerInvariant().Contains("final"));
            AddGroup(groups, items, GroupInProgress, "Em andamento", "Ciclos em andamento (não bloqueados, não concluídos).", i =>
            {
                var c = i.ClosureStatus ?? "";
                var closed = c.Contains("Concluído") || c.Contains("Encerrado") || c.ToLowerInvariant().Contains("closed");
                return !closed && !(i.RiskLevelLabel ?? "").Contains("Bloqueado");
            });
            AddGroup(groups, items, GroupCompleted, "Concluídos", "Ciclos concluídos.", i => { var c = i.ClosureStatus ?? ""; return c.Contains("Concluído") || c.Contains("Encerrado") || c.ToLowerInvariant().Contains("closed"); });
            AddGroup(groups, items, GroupCompletedWithIssues, "Concluídos com issues", "Ciclos concluídos com performance baixa ou pendências.", i => { var c = i.ClosureStatus ?? ""; var closed = c.Contains("Concluído") || c.Contains("Encerrado") || c.ToLowerInvariant().Contains("closed"); return closed && (i.OverallCyclePerformanceScore < 70 || (i.TopRecommendedAction ?? "") != "—"); });
            groups = groups.OrderByDescending(g => g.ItemCount).ThenBy(g => g.GroupKey).ToList();

            var mostCriticalGroup = groups.FirstOrDefault(g => g.GroupKey == GroupBlocked) ?? groups.FirstOrDefault(g => g.GroupKey == GroupAtRisk) ?? groups.FirstOrDefault();
            var largestGroup = groups.FirstOrDefault();

            var summaryText = total == 0
                ? "Nenhum ciclo na carteira."
                : $"Total {total} ciclo(s). Em andamento: {inProgress} | Em risco: {atRisk} | Bloqueados: {blocked} | Perto fechar: {closingSoon} | Concluídos: {completed} | Alta prioridade: {highPriority} | Recuperação: {recoveryOpp}.";

            return new EventCyclePortfolioOverviewState
            {
                TotalCycles = total,
                InProgressCount = inProgress,
                AtRiskCount = atRisk,
                BlockedCount = blocked,
                CompletedCount = completed,
                CompletedWithIssuesCount = completedWithIssues,
                HighPriorityCount = highPriority,
                ClosingSoonCount = closingSoon,
                RecoveryOpportunityCount = recoveryOpp,
                OverviewSummary = summaryText,
                Groups = groups,
                LastUpdatedAt = now
            };
        }

        private static void AddGroup(List<EventCyclePortfolioGroup> list, List<EventCyclePortfolioItem> items, string key, string title, string summary, System.Func<EventCyclePortfolioItem, bool> predicate)
        {
            var inGroup = items.Where(predicate).ToList();
            var top = inGroup.OrderByDescending(i => i.PriorityScore).FirstOrDefault();
            list.Add(new EventCyclePortfolioGroup
            {
                GroupKey = key,
                Title = title,
                ItemCount = inGroup.Count,
                Summary = summary,
                HighestPriorityItemId = top?.CycleId,
                Notes = inGroup.Count > 0 ? $"Prioritário no grupo: {top?.Title ?? top?.CycleId}" : null
            });
        }
    }
}
