// EN: Command to approve a merchant registration.
// VI: Command để phê duyệt đăng ký merchant.

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

namespace MerchantService.API.Application.Commands.Admin;

/// <summary>
/// EN: Command to approve a merchant registration (Admin only).
/// VI: Command để phê duyệt đăng ký merchant (chỉ Admin).
/// </summary>
/// <param name="MerchantId">Merchant ID to approve / ID Merchant cần phê duyệt</param>
/// <param name="ApprovedBy">Admin user ID / ID Admin phê duyệt</param>
public record ApproveMerchantCommand(Guid MerchantId, Guid ApprovedBy) : IRequest<ApproveMerchantResult>;

/// <summary>
/// EN: Result of merchant approval.
/// VI: Kết quả phê duyệt merchant.
/// </summary>
public record ApproveMerchantResult(
    Guid MerchantId,
    string Status,
    DateTime ApprovedAt);

/// <summary>
/// EN: Handler for ApproveMerchantCommand.
/// VI: Handler cho ApproveMerchantCommand.
/// </summary>
public class ApproveMerchantCommandHandler : IRequestHandler<ApproveMerchantCommand, ApproveMerchantResult>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly ILogger<ApproveMerchantCommandHandler> _logger;

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

    public async Task<ApproveMerchantResult> Handle(
        ApproveMerchantCommand request,
        CancellationToken cancellationToken)
    {
        var merchant = await _merchantRepository.GetByIdAsync(request.MerchantId, cancellationToken)
            ?? throw new DomainException($"Merchant {request.MerchantId} not found");

        merchant.Approve(request.ApprovedBy);

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

        _logger.LogInformation(
            "Merchant {MerchantId} approved by Admin {AdminId}",
            request.MerchantId, request.ApprovedBy);

        return new ApproveMerchantResult(
            merchant.Id,
            merchant.Status.Name,
            DateTime.UtcNow);
    }
}
