// EN: Handler for GetMerchantProfileQuery.
// VI: Handler cho GetMerchantProfileQuery.

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

namespace MerchantService.API.Application.Queries.Merchants;

/// <summary>
/// EN: Handler for getting current merchant's profile.
/// VI: Handler để lấy profile của merchant hiện tại.
/// </summary>
public class GetMerchantProfileQueryHandler : IRequestHandler<GetMerchantProfileQuery, MerchantProfileDto?>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly IShopRepository _shopRepository;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public GetMerchantProfileQueryHandler(
        IMerchantRepository merchantRepository,
        IShopRepository shopRepository,
        IHttpContextAccessor httpContextAccessor)
    {
        _merchantRepository = merchantRepository;
        _shopRepository = shopRepository;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task<MerchantProfileDto?> Handle(GetMerchantProfileQuery request, CancellationToken cancellationToken)
    {
        var userIdClaim = _httpContextAccessor.HttpContext?.User.FindFirst("sub")?.Value
            ?? _httpContextAccessor.HttpContext?.User.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value;
        
        if (string.IsNullOrEmpty(userIdClaim) || !Guid.TryParse(userIdClaim, out var userId))
        {
            return null;
        }

        var merchant = await _merchantRepository.GetByUserIdAsync(userId, cancellationToken);
        if (merchant == null)
        {
            return null;
        }

        var shops = await _shopRepository.GetByMerchantIdAsync(merchant.Id, cancellationToken);

        return MapToDto(merchant, shops.Count);
    }

    private static MerchantProfileDto MapToDto(Merchant merchant, int shopCount)
    {
        return new MerchantProfileDto
        {
            Id = merchant.Id,
            UserId = merchant.UserId,
            BusinessName = merchant.BusinessName,
            Type = merchant.Type.Name,
            Status = merchant.Status.Name,
            VerificationStatus = merchant.VerificationStatus.Name,
            BusinessInfo = new BusinessInfoDto
            {
                TaxId = merchant.BusinessInfo.TaxId,
                BusinessLicenseNumber = merchant.BusinessInfo.BusinessLicenseNumber,
                CompanyRegistrationNumber = merchant.BusinessInfo.CompanyRegistrationNumber,
                EstablishedDate = merchant.BusinessInfo.EstablishedDate,
                IsComplete = merchant.BusinessInfo.IsCompleteForVerification
            },
            SettlementConfig = new SettlementConfigDto
            {
                BankAccount = new BankAccountDto
                {
                    BankCode = merchant.SettlementConfig.BankAccount.BankCode,
                    BankName = merchant.SettlementConfig.BankAccount.BankName,
                    AccountNumber = !string.IsNullOrEmpty(merchant.SettlementConfig.BankAccount.AccountNumber)
                        ? $"****{merchant.SettlementConfig.BankAccount.AccountNumber[^4..]}"
                        : null,
                    AccountHolderName = merchant.SettlementConfig.BankAccount.AccountHolderName
                },
                CommissionRate = merchant.SettlementConfig.CommissionRate,
                SettlementCycle = SettlementCycle.FromValue<SettlementCycle>(merchant.SettlementConfig.SettlementCycleId).Name,
                AutoSettlement = merchant.SettlementConfig.AutoSettlement,
                IsComplete = merchant.SettlementConfig.IsComplete
            },
            VerifiedAt = merchant.VerifiedAt,
            CreatedAt = merchant.CreatedAt,
            UpdatedAt = merchant.UpdatedAt,
            ShopCount = shopCount
        };
    }
}

/// <summary>
/// EN: Handler for getting merchant by ID.
/// VI: Handler để lấy merchant theo ID.
/// </summary>
public class GetMerchantByIdQueryHandler : IRequestHandler<GetMerchantByIdQuery, MerchantProfileDto?>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly IShopRepository _shopRepository;

    public GetMerchantByIdQueryHandler(
        IMerchantRepository merchantRepository,
        IShopRepository shopRepository)
    {
        _merchantRepository = merchantRepository;
        _shopRepository = shopRepository;
    }

    public async Task<MerchantProfileDto?> Handle(GetMerchantByIdQuery request, CancellationToken cancellationToken)
    {
        var merchant = await _merchantRepository.GetByIdAsync(request.MerchantId, cancellationToken);
        if (merchant == null)
        {
            return null;
        }

        var shops = await _shopRepository.GetByMerchantIdAsync(merchant.Id, cancellationToken);

        return new MerchantProfileDto
        {
            Id = merchant.Id,
            UserId = merchant.UserId,
            BusinessName = merchant.BusinessName,
            Type = merchant.Type.Name,
            Status = merchant.Status.Name,
            VerificationStatus = merchant.VerificationStatus.Name,
            VerifiedAt = merchant.VerifiedAt,
            CreatedAt = merchant.CreatedAt,
            UpdatedAt = merchant.UpdatedAt,
            ShopCount = shops.Count
        };
    }
}
