#nullable enable
using Baya.Application.Common;
using Baya.Application.Contracts.Common;
using Baya.Application.Contracts.Persistence;
using Baya.Application.Models.Common;
using Baya.Application.Models.Identity;
using Baya.Domain.Entities.User;
using Mediator;

namespace Baya.Application.Features.Identity.Commands.UploadNurseAvatar;

internal sealed class UploadNurseAvatarCommandHandler(
    ICurrentUser currentUser,
    IUnitOfWork unitOfWork,
    IObjectStorage objectStorage)
    : IRequestHandler<UploadNurseAvatarCommand, OperationResult<AvatarUploadResult>>
{
    public async ValueTask<OperationResult<AvatarUploadResult>> Handle(UploadNurseAvatarCommand request, CancellationToken cancellationToken)
    {
        if (currentUser.UserId is not { } userId)
            return OperationResult<AvatarUploadResult>.UnauthorizedResult("Not authenticated.");

        if (currentUser.Roles?.Contains(RoleNames.Nurse) != true)
            return OperationResult<AvatarUploadResult>.ForbiddenResult("Only a nurse can upload a nurse avatar.");

        if (!AvatarUpload.IsAllowedContentType(request.ContentType))
            return OperationResult<AvatarUploadResult>.FailureResult("Unsupported image type. Use JPEG, PNG, or WebP.");

        if (!AvatarUpload.IsWithinSizeLimit(request.Length))
            return OperationResult<AvatarUploadResult>.FailureResult("Image is empty or exceeds the 5 MB limit.");

        var profile = await unitOfWork.NurseProfileRepository.GetByUserIdAsync(userId, cancellationToken);
        if (profile is null)
            return OperationResult<AvatarUploadResult>.NotFoundResult("No nurse profile exists yet.");

        var key = AvatarUpload.BuildKey("nurse", profile.Id, request.ContentType, Guid.NewGuid().ToString("N"));
        using (var stream = new MemoryStream(request.Content))
            await objectStorage.PutAsync(key, stream, request.ContentType, cancellationToken);

        var url = objectStorage.GetUrl(key);
        profile.AvatarUrl = url;
        await unitOfWork.CommitAsync();

        return OperationResult<AvatarUploadResult>.SuccessResult(new AvatarUploadResult(url));
    }
}
