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

namespace EventsAppQuest.Web.Communication.Application
{
    /// <summary>
    /// Armazenamento em memória de threads e mensagens de comunicação operacional (mock).
    /// Partilhado entre web do hotel e web do produtor; sem persistência real.
    /// </summary>
    public static class CommunicationStore
    {
        private static readonly List<CommunicationThread> Threads = new List<CommunicationThread>();
        private static readonly List<CommunicationMessage> Messages = new List<CommunicationMessage>();
        private static readonly List<CommunicationParticipant> Participants = new List<CommunicationParticipant>();
        private static readonly object Lock = new object();

        public static CommunicationThread GetOrCreateThread(string orderId, string opportunityId = null, string proposalId = null, string sessionId = null)
        {
            if (string.IsNullOrEmpty(orderId)) return null;
            lock (Lock)
            {
                var existing = Threads.FirstOrDefault(t => t.OrderId == orderId);
                if (existing != null) return existing;

                var id = "thread-" + Guid.NewGuid().ToString("N").Substring(0, 8);
                var now = DateTime.UtcNow;
                var thread = new CommunicationThread
                {
                    Id = id,
                    OrderId = orderId,
                    OpportunityId = opportunityId,
                    ProposalId = proposalId,
                    SessionId = sessionId,
                    CreatedAt = now,
                    LastMessageAt = null
                };
                Threads.Add(thread);
                Participants.Add(new CommunicationParticipant { Id = "p-" + id + "-hotel", ThreadId = id, Role = CommunicationParticipantRole.HotelSales, DisplayLabel = "Hotel" });
                Participants.Add(new CommunicationParticipant { Id = "p-" + id + "-prod", ThreadId = id, Role = CommunicationParticipantRole.Producer, DisplayLabel = "Produtor" });
                return thread;
            }
        }

        public static CommunicationThread GetThreadByOrderId(string orderId)
        {
            if (string.IsNullOrEmpty(orderId)) return null;
            lock (Lock)
                return Threads.FirstOrDefault(t => t.OrderId == orderId);
        }

        public static IReadOnlyList<CommunicationThread> GetThreads() => Threads.ToList();

        public static CommunicationMessage AddMessage(string threadId, string orderId, CommunicationParticipantRole senderRole, CommunicationMessageType messageType, string content)
        {
            if (string.IsNullOrEmpty(threadId)) return null;
            lock (Lock)
            {
                var thread = Threads.FirstOrDefault(t => t.Id == threadId);
                if (thread == null) return null;

                var id = "msg-" + Guid.NewGuid().ToString("N").Substring(0, 8);
                var now = DateTime.UtcNow;
                var msg = new CommunicationMessage
                {
                    Id = id,
                    ThreadId = threadId,
                    OrderId = orderId ?? thread.OrderId,
                    SenderRole = senderRole,
                    MessageType = messageType,
                    Content = content ?? "",
                    CreatedAt = now
                };
                Messages.Add(msg);
                thread.LastMessageAt = now;
                return msg;
            }
        }

        public static IReadOnlyList<CommunicationMessage> GetMessages(string threadId, int maxCount = 50)
        {
            if (string.IsNullOrEmpty(threadId)) return new List<CommunicationMessage>();
            lock (Lock)
                return Messages.Where(m => m.ThreadId == threadId).OrderBy(m => m.CreatedAt).Take(maxCount).ToList();
        }

        public static IReadOnlyList<CommunicationMessage> GetMessagesForOrder(string orderId, int maxCount = 50)
        {
            var thread = GetThreadByOrderId(orderId);
            return thread == null ? new List<CommunicationMessage>() : GetMessages(thread.Id, maxCount);
        }

        public static IReadOnlyList<CommunicationParticipant> GetParticipants(string threadId)
        {
            if (string.IsNullOrEmpty(threadId)) return new List<CommunicationParticipant>();
            lock (Lock)
                return Participants.Where(p => p.ThreadId == threadId).ToList();
        }
    }
}
