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 cronograma operacional e sequência de montagem a partir dos itens da proposta (tempo, dependências, fornecedores no local).
    /// </summary>
    public class MockEventSetupTimelineService : IEventSetupTimelineService
    {
        private const int MaxCriticalStepsReasonable = 5;
        private const int HeavySetupMinutesThreshold = 480;

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

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

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

            int totalMinutes = 0;
            var criticalSteps = new List<string>();
            var supplierIdsOnSite = new HashSet<string>();

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

                int duration = item.SetupDurationMinutes > 0 ? item.SetupDurationMinutes : 30;
                totalMinutes += duration;

                if (item.RequiresEarlySetup || item.ExecutionPriority >= 7)
                    criticalSteps.Add(item.Name ?? id + ": montagem antecipada/prioridade alta");

                if (item.RequiresSupplierOnSite && !string.IsNullOrEmpty(item.SupplierId))
                    supplierIdsOnSite.Add(item.SupplierId);
            }

            result.EstimatedTotalSetupMinutes = totalMinutes;
            result.CriticalSteps = criticalSteps;

            if (criticalSteps.Count > MaxCriticalStepsReasonable)
                result.SetupWarnings.Add("Muitos itens críticos de montagem (" + criticalSteps.Count + "); planejar sequência e equipe.");
            if (totalMinutes > HeavySetupMinutesThreshold)
                result.SetupWarnings.Add("Tempo total de montagem elevado (" + totalMinutes + " min); considerar início antecipado ou mais equipe.");
            if (supplierIdsOnSite.Count > 3)
                result.SetupWarnings.Add("Vários fornecedores precisam estar no local (" + supplierIdsOnSite.Count + "); coordenar agenda.");

            foreach (var id in itemIds)
            {
                var item = showroomService.GetById(id);
                if (item?.SetupDependencyTypes == null || item.SetupDependencyTypes.Count == 0) continue;

                foreach (var depType in item.SetupDependencyTypes)
                {
                    if (string.IsNullOrWhiteSpace(depType)) continue;
                    var satisfied = SatisfiesDependency(showroomService, itemIds, id, depType.Trim());
                    if (!satisfied)
                        result.DependencyIssues.Add((item.Name ?? id) + ": dependência \"" + depType + "\" pode não estar atendida na proposta.");
                }
            }

            result.Recommendations = new List<string>();
            if (criticalSteps.Count > 0)
                result.Recommendations.Add("Priorizar montagem antecipada para: " + string.Join(", ", criticalSteps.Take(3)));
            if (result.DependencyIssues.Count > 0)
                result.Recommendations.Add("Resolver dependências antes de confirmar cronograma.");
            if (supplierIdsOnSite.Count > 0)
                result.Recommendations.Add("Confirmar presença no local dos fornecedores dos itens que exigem montagem/operação in loco.");

            if (result.DependencyIssues.Count > 0)
                result.ExecutionReadinessStatus = ExecutionReadinessStatus.NotReady;
            else if (result.SetupWarnings.Count > 1 || totalMinutes > HeavySetupMinutesThreshold)
                result.ExecutionReadinessStatus = ExecutionReadinessStatus.Warning;
            else
                result.ExecutionReadinessStatus = ExecutionReadinessStatus.Ready;

            return result;
        }

        private static bool SatisfiesDependency(IShowroomService showroomService, List<string> proposalItemIds, string currentItemId, string dependencyType)
        {
            foreach (var otherId in proposalItemIds)
            {
                if (otherId == currentItemId) continue;
                var other = showroomService.GetById(otherId);
                if (other == null) continue;
                if (dependencyType.Equals("Stage", System.StringComparison.OrdinalIgnoreCase) && other.Type == ShowroomItemType.Stage)
                    return true;
                if (dependencyType.Equals("Power", System.StringComparison.OrdinalIgnoreCase) && (other.Type == ShowroomItemType.Lighting || other.Type == ShowroomItemType.Other))
                    return true;
                if (dependencyType.Equals("Structure", System.StringComparison.OrdinalIgnoreCase) && (other.Type == ShowroomItemType.Stage || other.Type == ShowroomItemType.Furniture))
                    return true;
            }
            return false;
        }
    }
}
