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

namespace EventsAppQuest.Web.Application
{
    /// <summary>
    /// Comparação entre snapshots executivos: calcula direção de evolução e mudanças-chave. Agregador/manual.
    /// </summary>
    public static class EventCycleSnapshotComparisonController
    {
        public static EventCycleSnapshotComparison Compare(string cycleId, EventCycleExecutiveSnapshot baseSnapshot, EventCycleExecutiveSnapshot comparedSnapshot, DateTime? comparedAt = null)
        {
            if (string.IsNullOrEmpty(cycleId) || baseSnapshot == null || comparedSnapshot == null) return null;
            var now = comparedAt ?? DateTime.UtcNow;

            var baseRisk = NormalizeRiskScore(baseSnapshot.RiskLabel);
            var compRisk = NormalizeRiskScore(comparedSnapshot.RiskLabel);
            var riskDeltaStr = $"{baseSnapshot.RiskLabel ?? "—"}→{comparedSnapshot.RiskLabel ?? "—"}";

            var priorityDelta = comparedSnapshot.PriorityScore - baseSnapshot.PriorityScore;
            var bottleneckChanged = (baseSnapshot.MainBottleneck ?? "") != (comparedSnapshot.MainBottleneck ?? "");
            var actionChanged = (baseSnapshot.MainRecommendedAction ?? "") != (comparedSnapshot.MainRecommendedAction ?? "") || (baseSnapshot.MainRecoveryAction ?? "") != (comparedSnapshot.MainRecoveryAction ?? "");

            // Heurística de direção:
            // - Risk score menor = melhor
            // - PriorityScore menor = melhor (menos atenção urgente)
            var improvedAxes = 0;
            var regressedAxes = 0;

            if (compRisk < baseRisk) improvedAxes++;
            else if (compRisk > baseRisk) regressedAxes++;

            if (comparedSnapshot.PriorityScore < baseSnapshot.PriorityScore) improvedAxes++;
            else if (comparedSnapshot.PriorityScore > baseSnapshot.PriorityScore) regressedAxes++;

            // Closure: heurística simples
            var closureDir = CompareClosure(baseSnapshot.ClosureStatus, comparedSnapshot.ClosureStatus);
            if (closureDir == 1) improvedAxes++;
            else if (closureDir == -1) regressedAxes++;

            var direction = EventCycleEvolutionDirection.Stable;
            if (improvedAxes == 0 && regressedAxes == 0)
                direction = EventCycleEvolutionDirection.Stable;
            else if (improvedAxes > 0 && regressedAxes == 0)
                direction = EventCycleEvolutionDirection.Improved;
            else if (regressedAxes > 0 && improvedAxes == 0)
                direction = EventCycleEvolutionDirection.Regressed;
            else
                direction = EventCycleEvolutionDirection.Mixed;

            var mainImprovement = PickMainImprovement(baseSnapshot, comparedSnapshot, baseRisk, compRisk, closureDir);
            var mainRegression = PickMainRegression(baseSnapshot, comparedSnapshot, baseRisk, compRisk, closureDir);

            var summary = $"Evolução: {direction} | Priority {baseSnapshot.PriorityScore}→{comparedSnapshot.PriorityScore} | Risco {riskDeltaStr}"
                          + (bottleneckChanged ? $" | Gargalo {baseSnapshot.MainBottleneck ?? "—"}→{comparedSnapshot.MainBottleneck ?? "—"}" : "")
                          + (actionChanged ? " | Ação alterada" : "");

            var comparison = new EventCycleSnapshotComparison
            {
                ComparisonId = $"Cmp_{cycleId}_{now.Ticks}",
                CycleId = cycleId,
                BaseSnapshotId = baseSnapshot.SnapshotId,
                ComparedSnapshotId = comparedSnapshot.SnapshotId,
                ComparisonSummary = summary,
                PriorityDelta = priorityDelta,
                RiskDelta = riskDeltaStr,
                BottleneckChanged = bottleneckChanged,
                ActionChanged = actionChanged,
                OverallDirection = direction,
                MainImprovement = mainImprovement,
                MainRegression = mainRegression,
                ComparedAt = now
            };

            SnapshotComparisonStore.AddComparison(comparison);
            return comparison;
        }

        public static EventCycleSnapshotComparison CompareLatestTwo(string cycleId)
        {
            var snaps = ExecutiveSnapshotsStore.GetSnapshots(cycleId);
            if (snaps == null || snaps.Count < 2) return null;
            var compared = snaps[0];
            var baseSnap = snaps[1];
            return Compare(cycleId, baseSnap, compared, DateTime.UtcNow);
        }

        public static List<EventCycleSnapshotComparison> CompareLatestTwoForAllCycles()
        {
            var comparisons = new List<EventCycleSnapshotComparison>();
            var all = ExecutiveSnapshotsStore.GetAllSnapshots();
            foreach (var cid in all.Select(s => s.CycleId).Distinct())
            {
                var cmp = CompareLatestTwo(cid);
                if (cmp != null) comparisons.Add(cmp);
            }
            return comparisons;
        }

        public static EventCycleSnapshotComparisonState GetComparisonState(string cycleId)
        {
            var list = SnapshotComparisonStore.GetByCycleId(cycleId);
            var latest = list.FirstOrDefault();
            var summary = latest == null
                ? "Nenhuma comparação."
                : $"Última: {latest.OverallDirection} | + {latest.MainImprovement ?? "—"} | − {latest.MainRegression ?? "—"}";

            return new EventCycleSnapshotComparisonState
            {
                CycleId = cycleId,
                Comparisons = list,
                LatestComparison = latest,
                TotalComparisons = list.Count,
                EvolutionSummary = summary,
                LastComparedAt = latest?.ComparedAt
            };
        }

        public static EventCycleSnapshotComparisonState GetGlobalComparisonState()
        {
            var list = SnapshotComparisonStore.GetAll();
            var latest = list.FirstOrDefault();
            var summary = latest == null
                ? "Nenhuma comparação de snapshots."
                : $"Última: {latest.OverallDirection} [{latest.CycleId}] | + {latest.MainImprovement ?? "—"} | − {latest.MainRegression ?? "—"}";

            return new EventCycleSnapshotComparisonState
            {
                CycleId = null,
                Comparisons = list,
                LatestComparison = latest,
                TotalComparisons = list.Count,
                EvolutionSummary = summary,
                LastComparedAt = latest?.ComparedAt
            };
        }

        public static void ClearCycle(string cycleId) => SnapshotComparisonStore.ClearCycle(cycleId);
        public static void ClearAll() => SnapshotComparisonStore.ClearAll();

        private static int NormalizeRiskScore(string riskLabel)
        {
            // menor = melhor
            if (string.IsNullOrEmpty(riskLabel)) return 2;
            var r = riskLabel.ToLowerInvariant();
            if (r.Contains("bloque")) return 5;
            if (r.Contains("crít") || r.Contains("critical")) return 4;
            if (r.Contains("em risco") || r.Contains("risco")) return 3;
            if (r.Contains("alertas bloqueantes")) return 3;
            if (r.Contains("normal")) return 2;
            if (r.Contains("saud")) return 1;
            return 2;
        }

        private static int CompareClosure(string baseClosure, string comparedClosure)
        {
            // retorna: 1 melhorou, -1 piorou, 0 estável/indefinido
            var b = NormalizeClosureScore(baseClosure);
            var c = NormalizeClosureScore(comparedClosure);
            if (c < b) return 1;
            if (c > b) return -1;
            return 0;
        }

        private static int NormalizeClosureScore(string closure)
        {
            // menor = melhor
            if (string.IsNullOrEmpty(closure)) return 2;
            var s = closure.ToLowerInvariant();
            if (s.Contains("concl") || s.Contains("encerr") || s.Contains("closed")) return 0;
            if (s.Contains("saud")) return 1;
            if (s.Contains("andamento") || s.Contains("em andamento")) return 2;
            if (s.Contains("risco")) return 3;
            if (s.Contains("bloque")) return 4;
            return 2;
        }

        private static string PickMainImprovement(EventCycleExecutiveSnapshot b, EventCycleExecutiveSnapshot c, int baseRisk, int compRisk, int closureDir)
        {
            if (closureDir == 1) return "Closure melhorou";
            if (compRisk < baseRisk) return "Risco diminuiu";
            if (c.PriorityScore < b.PriorityScore) return "Prioridade reduziu";
            if ((b.MainBottleneck ?? "") != (c.MainBottleneck ?? "")) return "Gargalo mudou";
            return "—";
        }

        private static string PickMainRegression(EventCycleExecutiveSnapshot b, EventCycleExecutiveSnapshot c, int baseRisk, int compRisk, int closureDir)
        {
            if (closureDir == -1) return "Closure piorou";
            if (compRisk > baseRisk) return "Risco aumentou";
            if (c.PriorityScore > b.PriorityScore) return "Prioridade aumentou";
            if ((b.MainRecommendedAction ?? "") != (c.MainRecommendedAction ?? "")) return "Ação mudou";
            return "—";
        }
    }
}

