using Knot.Contracts.Messaging.Application.Abstractions;
using Knot.Contracts.Messaging.Domain;
using Knot.Contracts.Conversations.Application.Abstractions;
using Knot.Contracts.Conversations.Domain;
using Knot.Modules.Conversations.Infrastructure.SignalR;
using Knot.Shared.Kernel;
using MediatR;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;

namespace Knot.Modules.Conversations.Application.Messages.React;

public sealed record AddReactionCommand(
    Guid MessageId,
    Guid UserId,
    string Emoji,
    Guid ChatId) : ICommand;

public sealed class AddReactionCommandHandler : ICommandHandler<AddReactionCommand>
{
    private readonly IMessageReactionRepository _reactionRepository;
    private readonly IChatsUnitOfWork _unitOfWork;
    private readonly IHubContext<ChatHub> _hubContext;
    private readonly IUserDisplayNameProvider _displayNameProvider;
    private readonly ILogger<AddReactionCommandHandler> _logger;

    public AddReactionCommandHandler(
        IMessageReactionRepository reactionRepository,
        IChatsUnitOfWork unitOfWork,
        IHubContext<ChatHub> hubContext,
        IUserDisplayNameProvider displayNameProvider,
        ILogger<AddReactionCommandHandler> logger)
    {
        _reactionRepository = reactionRepository;
        _unitOfWork = unitOfWork;
        _hubContext = hubContext;
        _displayNameProvider = displayNameProvider;
        _logger = logger;
    }

    public async Task<Result> Handle(AddReactionCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation("AddReaction: MessageId={MessageId}, UserId={UserId}, Emoji={Emoji}, ChatId={ChatId}",

            request.MessageId, request.UserId, request.Emoji, request.ChatId);


        var reaction = new MessageReaction(request.MessageId, request.UserId, request.Emoji);
        await _reactionRepository.AddAsync(reaction, cancellationToken);

        await _unitOfWork.SaveChangesAsync(cancellationToken);


        _logger.LogInformation("AddReaction: Reaction saved to database");

        var username = await _displayNameProvider.GetDisplayNameAsync(request.UserId, cancellationToken);


        _logger.LogInformation("AddReaction: Sending reaction_added to group {ChatId}", request.ChatId);

        await _hubContext.Clients.Group(request.ChatId.ToString()).SendAsync("reaction_added", new
        {
            messageId = request.MessageId,
            chatId = request.ChatId,
            userId = request.UserId,
            username = username,
            emoji = request.Emoji
        });

        _logger.LogInformation("AddReaction: reaction_added sent successfully");

        return Result.Success();
    }
}


