using AdsManagerService.Domain.AggregatesModel.AdAggregate;
using AdsManagerService.Domain.SeedWork;
using AdsManagerService.Infrastructure;
using MediatR;
using Microsoft.Extensions.Logging;

namespace AdsManagerService.API.Application.Commands;

/// <summary>
/// EN: Handler for approving ad.
/// VI: Handler phê duyệt quảng cáo.
/// </summary>
public class ApproveAdCommandHandler : IRequestHandler<Controllers.ApproveAdCommand, bool>
{
    private readonly IAdRepository _adRepository;
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger<ApproveAdCommandHandler> _logger;

    public ApproveAdCommandHandler(
        IAdRepository adRepository,
        IUnitOfWork unitOfWork,
        ILogger<ApproveAdCommandHandler> logger)
    {
        _adRepository = adRepository ?? throw new ArgumentNullException(nameof(adRepository));
        _unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<bool> Handle(Controllers.ApproveAdCommand request, CancellationToken cancellationToken)
    {
        var ad = await _adRepository.GetByIdAsync(request.AdId);

        if (ad == null)
        {
            _logger.LogWarning("Ad {AdId} not found", request.AdId);
            return false;
        }

        // EN: Approve ad (domain method handles state transition)
        // VI: Phê duyệt quảng cáo (domain method xử lý chuyển trạng thái)
        ad.Approve();

        await _unitOfWork.SaveChangesAsync(cancellationToken);

        _logger.LogInformation("Ad {AdId} approved successfully", request.AdId);

        return true;
    }
}

/// <summary>
/// EN: Handler for rejecting ad.
/// VI: Handler từ chối quảng cáo.
/// </summary>
public class RejectAdCommandHandler : IRequestHandler<Controllers.RejectAdCommand, bool>
{
    private readonly IAdRepository _adRepository;
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger<RejectAdCommandHandler> _logger;

    public RejectAdCommandHandler(
        IAdRepository adRepository,
        IUnitOfWork unitOfWork,
        ILogger<RejectAdCommandHandler> logger)
    {
        _adRepository = adRepository ?? throw new ArgumentNullException(nameof(adRepository));
        _unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<bool> Handle(Controllers.RejectAdCommand request, CancellationToken cancellationToken)
    {
        var ad = await _adRepository.GetByIdAsync(request.AdId);

        if (ad == null)
        {
            _logger.LogWarning("Ad {AdId} not found", request.AdId);
            return false;
        }

        // EN: Reject ad with reason
        // VI: Từ chối quảng cáo với lý do
        ad.Reject(request.Reason);

        await _unitOfWork.SaveChangesAsync(cancellationToken);

        _logger.LogInformation("Ad {AdId} rejected with reason: {Reason}", request.AdId, request.Reason);

        return true;
    }
}
