using MediatR;
using Modules.Media.Api.Commands;
using Modules.User.Application.Gateways;
using Modules.User.Domain.ValueObjects;

namespace Modules.User.Application.Commands.UserInformation;

public class SetUserAvatarCommand : IRequest<Unit>, IDisposable, IAsyncDisposable
{
    public string Extension { get; init; } = null!;
    public string ContentType { get; init; } = null!;
    public Stream Data { get; init; } = null!;

    public void Dispose()
    {
        Data.Dispose();
    }

    public async ValueTask DisposeAsync()
    {
        await Data.DisposeAsync();
    }
}

public class SetUserAvatarCommandHandler(UserContext userContext, IUserRepository userRepository,
    IMediator mediator, IUnitOfWork unitOfWork) : IRequestHandler<SetUserAvatarCommand, Unit>
{
    public async Task<Unit> Handle(SetUserAvatarCommand request, CancellationToken cancellationToken)
    {
        var accountId = userContext.GetAccountId();
        if (!accountId.HasValue) return Unit.Value;
        //TODO: if (!accountId.HasValue) throw new UnauthorizedAccessException("AccountId not found");
        
        var user = await userRepository.GetByAccountIdAsync(accountId.Value, cancellationToken);
        if (user == null) return Unit.Value;
        //TODO: if (user == null) throw new UserNotFoundException(); //"User not found"
        
        var newAvatarId = await mediator.Send(new AddObjectCommand
        {
            ObjectName = user.Avatar?.Id,
            BusketName = "my-bookmark.user",
            ObjectPrefix = "avatar",
            ObjectExtension = request.Extension,
            ContentType = request.ContentType,
            Data = request.Data,
        }, cancellationToken);

        if (string.IsNullOrWhiteSpace(newAvatarId))
        {
            //TODO: log error
            return Unit.Value;
        }
        
        user.SetAvatar(Avatar.Create(newAvatarId));
        await userRepository.SaveAsync(user, cancellationToken);
        await unitOfWork.SaveChangesAsync(cancellationToken);

        return Unit.Value;
    }
}