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

namespace ChatService.API.Application.Commands.Keys;

/// <summary>
/// EN: Handler for RegisterUserKeysCommand.
/// VI: Handler cho RegisterUserKeysCommand.
/// </summary>
public class RegisterUserKeysCommandHandler : IRequestHandler<RegisterUserKeysCommand, RegisterUserKeysResult>
{
    private readonly IChatUserRepository _chatUserRepository;
    private readonly ILogger<RegisterUserKeysCommandHandler> _logger;

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

    public async Task<RegisterUserKeysResult> Handle(RegisterUserKeysCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Registering keys for user {IdentityUserId}", request.IdentityUserId);

        // EN: Check if user already exists
        // VI: Kiểm tra xem user đã tồn tại chưa
        var existingUser = await _chatUserRepository.GetByIdentityUserIdAsync(request.IdentityUserId, cancellationToken);
        
        if (existingUser != null)
        {
            // EN: Update existing user's keys
            // VI: Cập nhật keys của user đã tồn tại
            existingUser.RegisterKeyBundle(
                request.IdentityPublicKey,
                request.SignedPreKey,
                request.SignedPreKeySignature);

            if (request.OneTimePreKeys?.Any() == true)
            {
                existingUser.UploadOneTimePreKeys(
                    request.OneTimePreKeys.Select(k => (k.KeyId, k.PublicKey)));
            }

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

            _logger.LogInformation("Updated keys for existing user {ChatUserId}", existingUser.Id);

            return new RegisterUserKeysResult(
                existingUser.Id,
                request.OneTimePreKeys?.Count() ?? 0);
        }

        // EN: Create new chat user
        // VI: Tạo chat user mới
        var chatUser = new ChatUser(
            request.IdentityUserId,
            request.DisplayName,
            request.AvatarUrl);

        chatUser.RegisterKeyBundle(
            request.IdentityPublicKey,
            request.SignedPreKey,
            request.SignedPreKeySignature);

        if (request.OneTimePreKeys?.Any() == true)
        {
            chatUser.UploadOneTimePreKeys(
                request.OneTimePreKeys.Select(k => (k.KeyId, k.PublicKey)));
        }

        _chatUserRepository.Add(chatUser);
        await _chatUserRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Created new chat user {ChatUserId} for {IdentityUserId}", 
            chatUser.Id, request.IdentityUserId);

        return new RegisterUserKeysResult(
            chatUser.Id,
            request.OneTimePreKeys?.Count() ?? 0);
    }
}
