using MediatR;
using ChatService.Domain.AggregatesModel.UserAggregate;

namespace ChatService.API.Application.Commands.Keys;

/// <summary>
/// EN: Handler for UploadOneTimeKeysCommand.
/// VI: Handler cho UploadOneTimeKeysCommand.
/// </summary>
public class UploadOneTimeKeysCommandHandler : IRequestHandler<UploadOneTimeKeysCommand, UploadOneTimeKeysResult>
{
    private readonly IChatUserRepository _chatUserRepository;
    private readonly ILogger<UploadOneTimeKeysCommandHandler> _logger;

    public UploadOneTimeKeysCommandHandler(
        IChatUserRepository chatUserRepository,
        ILogger<UploadOneTimeKeysCommandHandler> logger)
    {
        _chatUserRepository = chatUserRepository;
        _logger = logger;
    }

    public async Task<UploadOneTimeKeysResult> Handle(UploadOneTimeKeysCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Uploading {Count} one-time keys for user {ChatUserId}", 
            request.OneTimePreKeys.Count(), request.ChatUserId);

        var user = await _chatUserRepository.GetWithKeysAsync(request.ChatUserId, cancellationToken);
        
        if (user == null)
        {
            throw new InvalidOperationException($"Chat user {request.ChatUserId} not found");
        }

        user.UploadOneTimePreKeys(
            request.OneTimePreKeys.Select(k => (k.KeyId, k.PublicKey)));

        _chatUserRepository.Update(user);
        await _chatUserRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        var totalAvailable = user.GetAvailableOneTimePreKeyCount();

        _logger.LogInformation("Uploaded {Count} keys, total available: {Total}", 
            request.OneTimePreKeys.Count(), totalAvailable);

        return new UploadOneTimeKeysResult(
            request.OneTimePreKeys.Count(),
            totalAvailable);
    }
}
