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

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

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;

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

    public async Task<MerchantProfileDto?> Handle(GetMerchantProfileQuery request, CancellationToken cancellationToken)
    {
        // EN: Use user ID passed from the controller
        // VI: Dùng user ID được truyền từ controller
        var merchant = await _merchantRepository.GetByUserIdAsync(request.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)
    {
        // EN: Use TypeId/StatusId/VerificationStatusId to resolve Enumeration names,
        //     because navigation properties (_type, _status, _verificationStatus) are Ignored in EF config.
        // VI: Dùng TypeId/StatusId/VerificationStatusId để resolve tên Enumeration,
        //     vì navigation properties (_type, _status, _verificationStatus) bị Ignore trong EF config.
        var typeName = Enumeration.FromValue<MerchantType>(merchant.TypeId)?.Name ?? "Unknown";
        var statusName = Enumeration.FromValue<MerchantStatus>(merchant.StatusId)?.Name ?? "Unknown";
        var verificationName = Enumeration.FromValue<VerificationStatus>(merchant.VerificationStatusId)?.Name ?? "Unknown";

        var dto = new MerchantProfileDto
        {
            Id = merchant.Id,
            UserId = merchant.UserId,
            BusinessName = merchant.BusinessName,
            Type = typeName,
            Status = statusName,
            VerificationStatus = verificationName,
            VerifiedAt = merchant.VerifiedAt,
            CreatedAt = merchant.CreatedAt,
            UpdatedAt = merchant.UpdatedAt,
            ShopCount = shopCount,
            SubscriptionPlanId = merchant.SubscriptionPlanId
        };

        if (merchant.BusinessInfo != null)
        {
            dto.BusinessInfo = new BusinessInfoDto
            {
                TaxId = merchant.BusinessInfo.TaxId,
                BusinessLicenseNumber = merchant.BusinessInfo.BusinessLicenseNumber,
                CompanyRegistrationNumber = merchant.BusinessInfo.CompanyRegistrationNumber,
                EstablishedDate = merchant.BusinessInfo.EstablishedDate,
                IsComplete = merchant.BusinessInfo.IsCompleteForVerification
            };
        }

        if (merchant.SettlementConfig != null)
        {
            dto.SettlementConfig = new SettlementConfigDto
            {
                CommissionRate = merchant.SettlementConfig.CommissionRate,
                SettlementCycle = SettlementCycle.FromValue<SettlementCycle>(merchant.SettlementConfig.SettlementCycleId).Name,
                AutoSettlement = merchant.SettlementConfig.AutoSettlement,
                IsComplete = merchant.SettlementConfig.IsComplete
            };

            if (merchant.SettlementConfig.BankAccount != null)
            {
                dto.SettlementConfig.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
                };
            }
        }

        return dto;
    }
}

/// <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 = Enumeration.FromValue<MerchantType>(merchant.TypeId)?.Name ?? "Unknown",
            Status = Enumeration.FromValue<MerchantStatus>(merchant.StatusId)?.Name ?? "Unknown",
            VerificationStatus = Enumeration.FromValue<VerificationStatus>(merchant.VerificationStatusId)?.Name ?? "Unknown",
            VerifiedAt = merchant.VerifiedAt,
            CreatedAt = merchant.CreatedAt,
            UpdatedAt = merchant.UpdatedAt,
            ShopCount = shops.Count,
            SubscriptionPlanId = merchant.SubscriptionPlanId
        };
    }
}
