// EN: Command to suspend an active merchant.
// VI: Command để tạm ngưng merchant đang hoạt động.

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

namespace MerchantService.API.Application.Commands.Admin;

/// <summary>
/// EN: Command to suspend a merchant (Admin only).
/// VI: Command để tạm ngưng merchant (chỉ Admin).
/// </summary>
/// <param name="MerchantId">Merchant ID to suspend / ID Merchant cần tạm ngưng</param>
/// <param name="Reason">Reason for suspension / Lý do tạm ngưng</param>
/// <param name="SuspendedBy">Admin user ID / ID Admin tạm ngưng</param>
public record SuspendMerchantCommand(
    Guid MerchantId,
    string Reason,
    Guid SuspendedBy) : IRequest<SuspendMerchantResult>;

/// <summary>
/// EN: Result of merchant suspension.
/// VI: Kết quả tạm ngưng merchant.
/// </summary>
public record SuspendMerchantResult(
    Guid MerchantId,
    string Status,
    string Reason,
    DateTime SuspendedAt);

/// <summary>
/// EN: Handler for SuspendMerchantCommand.
/// VI: Handler cho SuspendMerchantCommand.
/// </summary>
public class SuspendMerchantCommandHandler : IRequestHandler<SuspendMerchantCommand, SuspendMerchantResult>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly ILogger<SuspendMerchantCommandHandler> _logger;

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

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

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

        merchant.Suspend(request.Reason);

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

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

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