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

namespace EventsAppQuest.Infrastructure.Services
{
    /// <summary>
    /// Avalia capacidade operacional da proposta para o espaço (convidados do briefing vs capacidade estimada).
    /// </summary>
    public class MockSpaceCapacityEvaluationService : ISpaceCapacityEvaluationService
    {
        public SpaceCapacityEvaluationResult Evaluate(EventProject project, EventProjectProposal proposal)
        {
            var result = new SpaceCapacityEvaluationResult();
            if (project == null || proposal == null) return result;

            result.GuestCountFromBrief = project.ClientBrief?.GuestCount ?? 0;

            var spaceService = ServiceRegistry.Instance.Get<ISpaceService>();
            var layoutService = ServiceRegistry.Instance.Get<ISpaceLayoutService>();
            var showroomService = ServiceRegistry.Instance.Get<IShowroomService>();
            if (spaceService == null || layoutService == null || string.IsNullOrEmpty(project.SpaceId))
            {
                result.Status = CapacityOperationalStatus.Unknown;
                result.RecommendedRangeText = "—";
                return result;
            }

            var space = spaceService.GetById(project.SpaceId);
            if (space == null)
            {
                result.Status = CapacityOperationalStatus.Unknown;
                result.RecommendedRangeText = "—";
                return result;
            }

            int baseCapacity = space.MaxRecommendedGuests > 0 ? space.MaxRecommendedGuests : space.Capacity;
            var slots = layoutService.GetBySpaceId(project.SpaceId) ?? new List<SpaceLayoutSlot>();
            var assignments = proposal.ItemSlotAssignments ?? new List<ItemSlotAssignment>();
            var assignedSlotIds = new HashSet<string>(assignments.Select(a => a.SlotId));

            int slotContrib = 0;
            foreach (var slot in slots)
            {
                if (assignedSlotIds.Contains(slot.Id))
                    slotContrib += slot.CapacityContribution;
            }

            int seatingFromItems = 0, standingFromItems = 0;
            var itemIds = proposal.ShowroomItemIds ?? new List<string>();
            if (showroomService != null)
            {
                foreach (var id in itemIds)
                {
                    var item = showroomService.GetById(id);
                    if (item != null)
                    {
                        seatingFromItems += item.SeatingProvided;
                        standingFromItems += item.StandingAreaImpact;
                    }
                }
            }

            int estimatedMax = baseCapacity + slotContrib + seatingFromItems + standingFromItems;
            int estimatedMin = (int)(estimatedMax * 0.75);
            if (estimatedMin < 10) estimatedMin = System.Math.Max(0, estimatedMax - 20);

            result.EstimatedCapacityMin = estimatedMin;
            result.EstimatedCapacityMax = estimatedMax;
            result.RecommendedRangeText = estimatedMin + "–" + estimatedMax + " convidados";

            if (result.GuestCountFromBrief <= 0)
            {
                result.Status = CapacityOperationalStatus.Unknown;
                result.FitsComfortably = result.FitsAtLimit = result.OverCapacity = false;
                return result;
            }

            int guests = result.GuestCountFromBrief;
            if (guests <= estimatedMin)
            {
                result.Status = CapacityOperationalStatus.Comfortable;
                result.FitsComfortably = true;
                result.FitsAtLimit = false;
                result.OverCapacity = false;
                result.OperationalRisks = new List<string>();
            }
            else if (guests <= estimatedMax)
            {
                result.Status = CapacityOperationalStatus.AtLimit;
                result.FitsComfortably = false;
                result.FitsAtLimit = true;
                result.OverCapacity = false;
                result.OperationalRisks = new List<string> { "Layout no limite da capacidade recomendada." };
            }
            else
            {
                result.Status = CapacityOperationalStatus.OverCapacity;
                result.FitsComfortably = false;
                result.FitsAtLimit = false;
                result.OverCapacity = true;
                result.OperationalRisks = new List<string> { "Proposta acima da capacidade estimada do espaço para o número de convidados." };
            }

            return result;
        }
    }
}
