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

namespace EventsAppQuest.Infrastructure.Services
{
    /// <summary>
    /// Avalia cobertura operacional por fornecedores: itens sem fornecedor adequado, montagem antecipada, execução no local, dependência em poucos fornecedores.
    /// </summary>
    public class MockSupplierCoverageEvaluationService : ISupplierCoverageEvaluationService
    {
        private const double SingleSupplierDominanceThreshold = 0.65;

        public SupplierCoverageEvaluationResult Evaluate(EventProject project, EventProjectProposal proposal)
        {
            var result = new SupplierCoverageEvaluationResult();
            if (project == null || proposal == null) return result;

            var showroomService = ServiceRegistry.Instance.Get<IShowroomService>();
            var supplierService = ServiceRegistry.Instance.Get<ISupplierService>();
            if (showroomService == null || supplierService == null) return result;

            var itemIds = proposal.ShowroomItemIds ?? new List<string>();
            if (itemIds.Count == 0)
            {
                result.CoverageScore = 100;
                return result;
            }

            var missing = new List<string>();
            var weakAreas = new HashSet<string>();
            var coveredZones = new HashSet<string>();
            var itemCountBySupplier = new Dictionary<string, int>();
            int issuesCount = 0;

            foreach (var id in itemIds)
            {
                var item = showroomService.GetById(id);
                if (item == null) continue;

                coveredZones.Add(item.PlacementZone.ToString());

                var supplier = string.IsNullOrEmpty(item.SupplierId) ? null : supplierService.GetById(item.SupplierId);
                if (supplier == null)
                {
                    missing.Add((item.Name ?? id) + ": sem fornecedor atribuído");
                    issuesCount++;
                    continue;
                }

                if (!itemCountBySupplier.ContainsKey(supplier.Id))
                    itemCountBySupplier[supplier.Id] = 0;
                itemCountBySupplier[supplier.Id]++;

                if (supplier.SupportedItemTypes != null && supplier.SupportedItemTypes.Count > 0 && !supplier.SupportedItemTypes.Contains(item.Type))
                {
                    missing.Add((item.Name ?? id) + ": fornecedor \"" + supplier.Name + "\" não suporta tipo " + item.Type);
                    issuesCount++;
                    weakAreas.Add("Tipo " + item.Type);
                }
                if (item.RequiresEarlySetup && !supplier.SupportsEarlySetup)
                {
                    missing.Add((item.Name ?? id) + ": exige montagem antecipada; fornecedor \"" + supplier.Name + "\" não suporta");
                    issuesCount++;
                    weakAreas.Add("Montagem antecipada");
                }
                if (item.RequiresSupplierOnSite && !supplier.SupportsOnSiteExecution)
                {
                    missing.Add((item.Name ?? id) + ": exige execução no local; fornecedor \"" + supplier.Name + "\" não suporta");
                    issuesCount++;
                    weakAreas.Add("Execução no local");
                }
            }

            result.MissingSupplierCapabilities = missing;
            result.WeakCoverageAreas = weakAreas.ToList();
            result.CoveredZones = coveredZones.ToList();

            var totalItems = itemIds.Count;
            foreach (var kv in itemCountBySupplier)
            {
                var ratio = (double)kv.Value / totalItems;
                if (ratio >= SingleSupplierDominanceThreshold)
                {
                    var sup = supplierService.GetById(kv.Key);
                    result.CoverageWarnings.Add("Alta dependência em um único fornecedor (\"" + (sup?.Name ?? kv.Key) + "\": " + (int)(ratio * 100) + "% dos itens).");
                    break;
                }
            }

            result.Recommendations = new List<string>();
            if (missing.Count > 0)
                result.Recommendations.Add("Incluir ou trocar fornecedores para cobrir itens sem capacidade adequada (tipo, montagem antecipada, execução no local).");
            if (result.CoverageWarnings.Count > 0)
                result.Recommendations.Add("Diversificar fornecedores para reduzir risco operacional.");
            if (weakAreas.Count > 0)
                result.Recommendations.Add("Reforçar cobertura em: " + string.Join(", ", weakAreas.Take(3)) + ".");

            result.CoverageScore = System.Math.Max(0, 100 - (issuesCount * 15) - (result.CoverageWarnings.Count * 10));
            return result;
        }
    }
}
