// EN: Command to permanently ban a merchant.
// VI: Command để cấm vĩnh viễn một merchant.

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

namespace MerchantService.API.Application.Commands.Admin;

/// <summary>
/// EN: Command to permanently ban a merchant (Admin only).
/// VI: Command để cấm vĩnh viễn merchant (chỉ Admin).
/// </summary>
/// <param name="MerchantId">Merchant ID to ban / ID Merchant cần cấm</param>
/// <param name="Reason">Reason for ban / Lý do cấm</param>
/// <param name="BannedBy">Admin user ID / ID Admin thực hiện cấm</param>
public record BanMerchantCommand(
    Guid MerchantId,
    string Reason,
    Guid BannedBy) : IRequest<BanMerchantResult>;

/// <summary>
/// EN: Result of merchant ban.
/// VI: Kết quả cấm merchant.
/// </summary>
public record BanMerchantResult(
    Guid MerchantId,
    string Status,
    string Reason,
    DateTime BannedAt);

/// <summary>
/// EN: Handler for BanMerchantCommand.
/// VI: Handler cho BanMerchantCommand.
/// </summary>
public class BanMerchantCommandHandler : IRequestHandler<BanMerchantCommand, BanMerchantResult>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly ILogger<BanMerchantCommandHandler> _logger;

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

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

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

        merchant.Ban(request.Reason);

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

        _logger.LogWarning(
            "Merchant {MerchantId} BANNED by Admin {AdminId}. Reason: {Reason}",
            request.MerchantId, request.BannedBy, request.Reason);

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