using MediatR;
using ChatService.Domain.AggregatesModel.ConversationAggregate;

namespace ChatService.API.Application.Commands.Messages;

/// <summary>
/// EN: Handler for SendMessageCommand.
/// VI: Handler cho SendMessageCommand.
/// </summary>
public class SendMessageCommandHandler : IRequestHandler<SendMessageCommand, SendMessageResult>
{
    private readonly IConversationRepository _conversationRepository;
    private readonly ILogger<SendMessageCommandHandler> _logger;

    public SendMessageCommandHandler(
        IConversationRepository conversationRepository,
        ILogger<SendMessageCommandHandler> logger)
    {
        _conversationRepository = conversationRepository;
        _logger = logger;
    }

    public async Task<SendMessageResult> Handle(SendMessageCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Sending message from {SenderId} to conversation {ConversationId}",
            request.SenderId, request.ConversationId);

        var conversation = await _conversationRepository.GetByIdAsync(request.ConversationId, cancellationToken);

        if (conversation == null)
        {
            throw new InvalidOperationException($"Conversation {request.ConversationId} not found");
        }

        // EN: Parse message type
        // VI: Parse message type
        var messageType = MessageType.FromName(request.MessageType);
        if (messageType == null)
        {
            messageType = MessageType.Text;
        }

        // EN: Send encrypted message via Conversation aggregate
        // VI: Gửi tin nhắn đã mã hóa qua Conversation aggregate
        var message = conversation.SendMessage(
            request.SenderId,
            request.EncryptedContent,
            request.Nonce,
            messageType,
            request.AuthTag,
            request.Metadata,
            request.ReplyToMessageId);

        _conversationRepository.Update(conversation);
        await _conversationRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Message {MessageId} sent to conversation {ConversationId}",
            message.Id, conversation.Id);

        return new SendMessageResult(
            message.Id,
            conversation.Id,
            request.SenderId,
            message.Status.Name,
            message.CreatedAt);
    }
}
