using MediatR;
using StorageService.Domain.AggregatesModel.FileShareAggregate;

namespace StorageService.API.Application.Commands.FileShare;

/// <summary>
/// EN: Handler for RevokeFileShareCommand.
/// VI: Handler cho RevokeFileShareCommand.
/// </summary>
public class RevokeFileShareCommandHandler : IRequestHandler<RevokeFileShareCommand, RevokeFileShareResult>
{
    private readonly IFileShareRepository _fileShareRepository;
    private readonly ILogger<RevokeFileShareCommandHandler> _logger;

    public RevokeFileShareCommandHandler(
        IFileShareRepository fileShareRepository,
        ILogger<RevokeFileShareCommandHandler> logger)
    {
        _fileShareRepository = fileShareRepository;
        _logger = logger;
    }

    public async Task<RevokeFileShareResult> Handle(RevokeFileShareCommand request, CancellationToken cancellationToken)
    {
        try
        {
            _logger.LogInformation(
                "Revoking file share {ShareId} by user {UserId}",
                request.ShareId, request.UserId);

            // EN: Get the file share / VI: Lấy file share
            var fileShare = await _fileShareRepository.GetByIdAsync(request.ShareId, cancellationToken);
            
            if (fileShare == null)
            {
                return RevokeFileShareResult.Fail("Share not found.");
            }

            // EN: Verify user owns the share / VI: Kiểm tra user sở hữu share
            if (fileShare.SharedBy != request.UserId)
            {
                _logger.LogWarning(
                    "User {UserId} attempted to revoke share {ShareId} created by {OwnerId}",
                    request.UserId, request.ShareId, fileShare.SharedBy);
                return RevokeFileShareResult.Fail("You don't have permission to revoke this share.");
            }

            // EN: Check if already revoked / VI: Kiểm tra đã thu hồi chưa
            if (fileShare.Status == FileShareStatus.Revoked)
            {
                return RevokeFileShareResult.Ok(); // EN: Idempotent / VI: Idempotent
            }

            // EN: Revoke the share / VI: Thu hồi share
            fileShare.Revoke();
            _fileShareRepository.Update(fileShare);
            await _fileShareRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

            _logger.LogInformation("File share {ShareId} revoked successfully", request.ShareId);
            return RevokeFileShareResult.Ok();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error revoking file share {ShareId}", request.ShareId);
            return RevokeFileShareResult.Fail("An error occurred while revoking the share.");
        }
    }
}
