using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using StorageService.Infrastructure.Persistence;
using StorageService.Infrastructure.Storage;

namespace StorageService.API.Application.Commands.MultipartUpload;

/// <summary>
/// EN: Handler for AbortMultipartUploadCommand.
/// VI: Handler cho AbortMultipartUploadCommand.
/// </summary>
public class AbortMultipartUploadCommandHandler 
    : IRequestHandler<AbortMultipartUploadCommand, AbortMultipartUploadResult>
{
    private readonly StorageServiceContext _context;
    private readonly IStorageProviderFactory _storageProviderFactory;
    private readonly ILogger<AbortMultipartUploadCommandHandler> _logger;

    public AbortMultipartUploadCommandHandler(
        StorageServiceContext context,
        IStorageProviderFactory storageProviderFactory,
        ILogger<AbortMultipartUploadCommandHandler> logger)
    {
        _context = context;
        _storageProviderFactory = storageProviderFactory;
        _logger = logger;
    }

    public async Task<AbortMultipartUploadResult> Handle(
        AbortMultipartUploadCommand request, 
        CancellationToken cancellationToken)
    {
        try
        {
            _logger.LogInformation("Aborting multipart upload {UploadId}", request.UploadId);

            // EN: Get multipart upload / VI: Lấy multipart upload
            var upload = await _context.MultipartUploads
                .FirstOrDefaultAsync(u => u.Id == request.UploadId, cancellationToken);

            if (upload == null)
            {
                _logger.LogWarning("Multipart upload not found: {UploadId}", request.UploadId);
                return AbortMultipartUploadResult.Fail("Multipart upload not found");
            }

            // EN: Verify ownership / VI: Xác minh quyền sở hữu
            if (upload.UserId != request.UserId)
            {
                _logger.LogWarning("User {UserId} attempted to abort upload owned by {OwnerId}", 
                    request.UserId, upload.UserId);
                return AbortMultipartUploadResult.Fail("Unauthorized");
            }

            // EN: Abort at provider / VI: Hủy tại provider
            var provider = _storageProviderFactory.GetProvider();
            
            try
            {
                await provider.AbortMultipartUploadAsync(
                    upload.BucketName,
                    upload.ObjectKey,
                    upload.ProviderUploadId,
                    cancellationToken);
            }
            catch (Exception ex)
            {
                // EN: Log but continue - provider cleanup is best effort
                // VI: Log nhưng tiếp tục - cleanup provider là best effort
                _logger.LogWarning(ex, "Failed to abort multipart upload at provider for {UploadId}", request.UploadId);
            }

            // EN: Mark as aborted in database / VI: Đánh dấu aborted trong database
            upload.Abort();
            await _context.SaveEntitiesAsync(cancellationToken);

            _logger.LogInformation("Multipart upload {UploadId} aborted successfully", request.UploadId);

            return AbortMultipartUploadResult.Ok();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error aborting multipart upload {UploadId}", request.UploadId);
            return AbortMultipartUploadResult.Fail("An error occurred while aborting multipart upload.");
        }
    }
}
