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

namespace EventsAppQuest.Web.Producer.Application
{
    /// <summary>
    /// Controlador para ajustes de escopo e confirmação operacional (mock).
    /// Criar revisão, adicionar itens de mudança, aprovar/rejeitar pelo hotel ou produtor, marcar como escopo actual confirmado.
    /// </summary>
    public static class ProducerOrderScopeController
    {
        /// <summary>Cria uma nova revisão de escopo para o pedido.</summary>
        public static ProducerOrderScopeRevision CreateRevision(string orderId, ScopeRevisionRequestedByRole requestedBy, string summary, string notes = null)
        {
            if (string.IsNullOrEmpty(orderId)) return null;
            var id = "rev-" + Guid.NewGuid().ToString("N").Substring(0, 8);
            var revision = new ProducerOrderScopeRevision
            {
                RevisionId = id,
                ProducerOrderId = orderId,
                RequestedByRole = requestedBy,
                RevisionSummary = summary ?? "",
                ChangeItems = new List<ProducerScopeChangeItem>(),
                CreatedAt = DateTime.UtcNow,
                IsApprovedByHotel = false,
                IsApprovedByProducer = false,
                IsCurrentActiveRevision = false,
                Notes = notes,
                Status = requestedBy == ScopeRevisionRequestedByRole.Producer || requestedBy == ScopeRevisionRequestedByRole.InternalAdmin
                    ? ProducerScopeConfirmationStatus.PendingHotelApproval
                    : ProducerScopeConfirmationStatus.PendingProducerApproval
            };
            ScopeRevisionStore.AddRevision(revision);
            return revision;
        }

        /// <summary>Adiciona um item de mudança à revisão.</summary>
        public static void AddChangeItem(string revisionId, ProducerScopeChangeType changeType, string targetReference, string description, string previousValue = null, string newValue = null)
        {
            var revision = ScopeRevisionStore.GetRevisionById(revisionId);
            if (revision == null) return;
            var item = new ProducerScopeChangeItem
            {
                ItemId = "item-" + Guid.NewGuid().ToString("N").Substring(0, 6),
                ChangeType = changeType,
                TargetReference = targetReference,
                Description = description ?? "",
                PreviousValue = previousValue,
                NewValue = newValue
            };
            revision.ChangeItems.Add(item);
            ScopeRevisionStore.UpdateRevision(revision);
        }

        /// <summary>Aprova a revisão pelo hotel.</summary>
        public static void ApproveByHotel(string revisionId)
        {
            var revision = ScopeRevisionStore.GetRevisionById(revisionId);
            if (revision == null) return;
            revision.IsApprovedByHotel = true;
            revision.Status = revision.IsApprovedByProducer ? ProducerScopeConfirmationStatus.Confirmed : ProducerScopeConfirmationStatus.PendingProducerApproval;
            if (revision.IsApprovedByHotel && revision.IsApprovedByProducer)
                SetAsCurrentActive(revisionId);
            ScopeRevisionStore.UpdateRevision(revision);
        }

        /// <summary>Rejeita a revisão pelo hotel.</summary>
        public static void RejectByHotel(string revisionId, string note = null)
        {
            var revision = ScopeRevisionStore.GetRevisionById(revisionId);
            if (revision == null) return;
            revision.IsApprovedByHotel = false;
            revision.Status = ProducerScopeConfirmationStatus.Rejected;
            if (!string.IsNullOrEmpty(note)) revision.Notes = (revision.Notes ?? "") + " [Hotel rejeitou: " + note + "]";
            ScopeRevisionStore.UpdateRevision(revision);
        }

        /// <summary>Aprova a revisão pelo produtor.</summary>
        public static void ApproveByProducer(string revisionId)
        {
            var revision = ScopeRevisionStore.GetRevisionById(revisionId);
            if (revision == null) return;
            revision.IsApprovedByProducer = true;
            revision.Status = revision.IsApprovedByHotel ? ProducerScopeConfirmationStatus.Confirmed : ProducerScopeConfirmationStatus.PendingHotelApproval;
            if (revision.IsApprovedByHotel && revision.IsApprovedByProducer)
                SetAsCurrentActive(revisionId);
            ScopeRevisionStore.UpdateRevision(revision);
        }

        /// <summary>Rejeita a revisão pelo produtor.</summary>
        public static void RejectByProducer(string revisionId, string note = null)
        {
            var revision = ScopeRevisionStore.GetRevisionById(revisionId);
            if (revision == null) return;
            revision.IsApprovedByProducer = false;
            revision.Status = ProducerScopeConfirmationStatus.Rejected;
            if (!string.IsNullOrEmpty(note)) revision.Notes = (revision.Notes ?? "") + " [Produtor rejeitou: " + note + "]";
            ScopeRevisionStore.UpdateRevision(revision);
        }

        /// <summary>Marca a revisão como escopo actual confirmado (ambos aprovaram).</summary>
        public static void SetAsCurrentActive(string revisionId)
        {
            var revision = ScopeRevisionStore.GetRevisionById(revisionId);
            if (revision == null) return;
            var orderId = revision.ProducerOrderId;
            ScopeRevisionStore.SetCurrentActiveRevision(orderId, revisionId);
            ScopeRevisionStore.SetConfirmationState(new ProducerScopeConfirmationState
            {
                OrderId = orderId,
                Status = ProducerScopeConfirmationStatus.Confirmed,
                ConfirmedRevisionId = revisionId,
                LastUpdatedAt = DateTime.UtcNow
            });
        }

        public static IReadOnlyList<ProducerOrderScopeRevision> GetRevisionsForOrder(string orderId) => ScopeRevisionStore.GetRevisionsForOrder(orderId);
        public static ProducerOrderScopeRevision GetRevisionById(string revisionId) => ScopeRevisionStore.GetRevisionById(revisionId);
        public static ProducerOrderScopeRevision GetCurrentActiveRevision(string orderId) => ScopeRevisionStore.GetCurrentActiveRevision(orderId);
        public static ProducerScopeConfirmationState GetConfirmationState(string orderId) => ScopeRevisionStore.GetConfirmationState(orderId);
    }
}
