using MediatR;
using StorageService.Domain.AggregatesModel.FileAggregate;
using StorageService.Domain.AggregatesModel.QuotaAggregate;
using StorageService.Infrastructure.Caching;
using StorageService.Infrastructure.Storage;

namespace StorageService.API.Application.Commands;

/// <summary>
/// EN: Handler for DeleteFileCommand.
/// VI: Handler cho DeleteFileCommand.
/// </summary>
public class DeleteFileCommandHandler : IRequestHandler<DeleteFileCommand, DeleteFileResult>
{
    private readonly IFileRepository _fileRepository;
    private readonly IQuotaRepository _quotaRepository;
    private readonly IStorageProviderFactory _storageProviderFactory;
    private readonly IRedisCacheService _cache;
    private readonly ILogger<DeleteFileCommandHandler> _logger;

    public DeleteFileCommandHandler(
        IFileRepository fileRepository,
        IQuotaRepository quotaRepository,
        IStorageProviderFactory storageProviderFactory,
        IRedisCacheService cache,
        ILogger<DeleteFileCommandHandler> logger)
    {
        _fileRepository = fileRepository;
        _quotaRepository = quotaRepository;
        _storageProviderFactory = storageProviderFactory;
        _cache = cache;
        _logger = logger;
    }

    public async Task<DeleteFileResult> Handle(DeleteFileCommand request, CancellationToken cancellationToken)
    {
        try
        {
            // EN: Get file metadata / VI: Lấy metadata file
            var file = await _fileRepository.GetByIdAsync(request.FileId, cancellationToken);
            
            if (file == null)
            {
                return new DeleteFileResult(false, "File not found.");
            }

            // EN: Check ownership / VI: Kiểm tra quyền sở hữu
            if (file.UserId != request.UserId)
            {
                return new DeleteFileResult(false, "You don't have permission to delete this file.");
            }

            // EN: Delete from storage provider / VI: Xóa khỏi storage provider
            var provider = _storageProviderFactory.GetProvider(file.Provider);
            var deleted = await provider.DeleteAsync(file.BucketName, file.ObjectKey, cancellationToken);

            if (!deleted)
            {
                _logger.LogWarning("Failed to delete file from storage: {FileId}", request.FileId);
                // EN: Continue with soft delete even if storage delete fails
                // VI: Tiếp tục soft delete ngay cả khi xóa storage thất bại
            }

            // EN: Soft delete file record / VI: Soft delete record file
            file.Delete();
            _fileRepository.Update(file);

            // EN: Update quota / VI: Cập nhật quota
            var quota = await _quotaRepository.GetByUserIdAsync(request.UserId, cancellationToken);
            if (quota != null)
            {
                quota.RemoveUsage(file.FileSizeBytes);
                _quotaRepository.Update(quota);
            }

            // EN: Save changes / VI: Lưu thay đổi
            await _fileRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

            // EN: Invalidate quota cache / VI: Invalidate quota cache
            if (Guid.TryParse(request.UserId, out var userId))
            {
                await _cache.DeleteAsync(CacheKeys.UserQuota(userId), cancellationToken);
            }

            // EN: Invalidate file metadata cache / VI: Invalidate file metadata cache
            await _cache.DeleteAsync(CacheKeys.FileMetadata(request.FileId), cancellationToken);

            _logger.LogInformation("File deleted successfully: {FileId}", request.FileId);
            return new DeleteFileResult(true, null);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error deleting file {FileId}", request.FileId);
            return new DeleteFileResult(false, "An error occurred while deleting the file.");
        }
    }
}
