// EN: Command to reject a merchant registration.
// VI: Command để từ chối đăng ký merchant.

using MediatR;
using MerchantService.Domain.AggregatesModel.MerchantAggregate;
using MerchantService.Domain.Exceptions;

namespace MerchantService.API.Application.Commands.Admin;

/// <summary>
/// EN: Command to reject a merchant registration (Admin only).
/// VI: Command để từ chối đăng ký merchant (chỉ Admin).
/// </summary>
/// <param name="MerchantId">Merchant ID to reject / ID Merchant cần từ chối</param>
/// <param name="Reason">Reason for rejection / Lý do từ chối</param>
/// <param name="RejectedBy">Admin user ID / ID Admin từ chối</param>
public record RejectMerchantCommand(
    Guid MerchantId,
    string Reason,
    Guid RejectedBy) : IRequest<RejectMerchantResult>;

/// <summary>
/// EN: Result of merchant rejection.
/// VI: Kết quả từ chối merchant.
/// </summary>
public record RejectMerchantResult(
    Guid MerchantId,
    string Status,
    string Reason,
    DateTime RejectedAt);

/// <summary>
/// EN: Handler for RejectMerchantCommand.
/// VI: Handler cho RejectMerchantCommand.
/// </summary>
public class RejectMerchantCommandHandler : IRequestHandler<RejectMerchantCommand, RejectMerchantResult>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly ILogger<RejectMerchantCommandHandler> _logger;

    public RejectMerchantCommandHandler(
        IMerchantRepository merchantRepository,
        ILogger<RejectMerchantCommandHandler> logger)
    {
        _merchantRepository = merchantRepository;
        _logger = logger;
    }

    public async Task<RejectMerchantResult> Handle(
        RejectMerchantCommand request,
        CancellationToken cancellationToken)
    {
        if (string.IsNullOrWhiteSpace(request.Reason))
            throw new DomainException("Rejection reason is required");

        var merchant = await _merchantRepository.GetByIdAsync(request.MerchantId, cancellationToken)
            ?? throw new DomainException($"Merchant {request.MerchantId} not found");

        // EN: Reject sets status to Rejected - need to add this method to Domain
        // VI: Reject đặt status thành Rejected - cần thêm method vào Domain
        merchant.Suspend(request.Reason); // Using Suspend as rejection for now

        _merchantRepository.Update(merchant);
        await _merchantRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation(
            "Merchant {MerchantId} rejected by Admin {AdminId}. Reason: {Reason}",
            request.MerchantId, request.RejectedBy, request.Reason);

        return new RejectMerchantResult(
            merchant.Id,
            merchant.Status.Name,
            request.Reason,
            DateTime.UtcNow);
    }
}
