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

namespace StorageService.API.Application.Commands.Admin;

/// <summary>
/// EN: Handler for UpdateUserQuotaCommand.
/// VI: Handler cho UpdateUserQuotaCommand.
/// </summary>
public class UpdateUserQuotaCommandHandler : IRequestHandler<UpdateUserQuotaCommand, UpdateUserQuotaResult>
{
    private readonly IQuotaRepository _quotaRepository;
    private readonly IRedisCacheService _cache;
    private readonly ILogger<UpdateUserQuotaCommandHandler> _logger;

    public UpdateUserQuotaCommandHandler(
        IQuotaRepository quotaRepository,
        IRedisCacheService cache,
        ILogger<UpdateUserQuotaCommandHandler> logger)
    {
        _quotaRepository = quotaRepository;
        _cache = cache;
        _logger = logger;
    }

    public async Task<UpdateUserQuotaResult> Handle(UpdateUserQuotaCommand request, CancellationToken cancellationToken)
    {
        try
        {
            // EN: Get user quota / VI: Lấy quota của user
            var quota = await _quotaRepository.GetByUserIdAsync(request.TargetUserId, cancellationToken);
            
            if (quota == null)
            {
                // EN: Create new quota if not exists / VI: Tạo quota mới nếu chưa có
                quota = new UserStorageQuota(
                    request.TargetUserId,
                    request.MaxStorageBytes,
                    request.MaxFileCount,
                    request.QuotaTier);
                await _quotaRepository.AddAsync(quota, cancellationToken);
                
                _logger.LogInformation(
                    "Created new quota for user {UserId}: MaxStorage={MaxStorageBytes}, MaxFiles={MaxFileCount}, Tier={QuotaTier}",
                    request.TargetUserId, request.MaxStorageBytes, request.MaxFileCount, request.QuotaTier);
            }
            else
            {
                // EN: Update existing quota / VI: Cập nhật quota hiện có
                quota.UpdateLimits(request.MaxStorageBytes, request.MaxFileCount, request.QuotaTier);
                _quotaRepository.Update(quota);
                
                _logger.LogInformation(
                    "Updated quota for user {UserId}: MaxStorage={MaxStorageBytes}, MaxFiles={MaxFileCount}, Tier={QuotaTier}",
                    request.TargetUserId, request.MaxStorageBytes, request.MaxFileCount, request.QuotaTier);
            }

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

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

            var result = new QuotaUpdatedDto(
                quota.UserId,
                quota.MaxStorageBytes,
                quota.UsedStorageBytes,
                quota.MaxFileCount,
                quota.CurrentFileCount,
                quota.QuotaTier,
                quota.LastUpdatedAt);

            return new UpdateUserQuotaResult(true, result, null);
        }
        catch (InvalidOperationException ex)
        {
            // EN: Business rule violation (e.g., max < current usage) / VI: Vi phạm business rule
            _logger.LogWarning(ex, "Failed to update quota for user {UserId}: {Error}", request.TargetUserId, ex.Message);
            return new UpdateUserQuotaResult(false, null, ex.Message);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error updating quota for user {UserId}", request.TargetUserId);
            return new UpdateUserQuotaResult(false, null, "An error occurred while updating the quota.");
        }
    }
}
