package com.jeesharp.business.modules.finance.merchantreceivable.application;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.finance.api.dto.MerchantReceivableBriefDTO;
import com.jeesharp.business.modules.finance.merchantreceivable.convert.MerchantReceivableConvert;
import com.jeesharp.business.modules.finance.merchantreceivable.entity.MerchantReceivable;
import com.jeesharp.business.modules.finance.merchantreceivable.enums.MerchantReceivableEntryTypeEnum;
import com.jeesharp.business.modules.finance.merchantreceivable.enums.MerchantReceivableSummaryGroupByEnum;
import com.jeesharp.business.modules.finance.merchantreceivable.service.MerchantReceivableService;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.MerchantReceivableExportVO;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.MerchantReceivableInfoVO;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.MerchantReceivableListVO;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.MerchantReceivableQueryVO;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.MerchantReceivableSettlementQueryVO;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.MerchantReceivableSettlementSummaryVO;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.PlatformCommissionPeriodSummaryVO;
import com.jeesharp.business.modules.finance.platformrevenue.enums.PlatformRevenuePeriodTypeEnum;
import com.jeesharp.business.modules.finance.platformrevenue.service.PlatformRevenueService;
import com.jeesharp.business.modules.finance.platformrevenue.support.PlatformRevenueConstants;
import com.jeesharp.business.modules.finance.platformrevenue.vo.PlatformRevenueQueryVO;
import com.jeesharp.business.modules.finance.api.MerchantSettleConfigApi;
import com.jeesharp.business.modules.finance.merchantsettle.enums.SettleModeEnum;
import com.jeesharp.business.modules.finance.merchantsettle.vo.MerchantSettleConfigSnapshotVO;
import com.jeesharp.business.modules.finance.payorder.entity.PayOrder;
import com.jeesharp.business.modules.finance.payorder.service.PayOrderService;
import com.jeesharp.business.modules.finance.payorder.support.PayOrderWechatRouteSupport;
import com.jeesharp.business.modules.finance.payrefund.entity.PayRefundOrder;
import com.jeesharp.business.modules.finance.payrefund.service.PayRefundOrderService;
import com.jeesharp.business.modules.finance.paymentrecord.enums.PayRecordBizSceneEnum;
import com.jeesharp.business.modules.finance.api.dto.PaySettleBizOrderSnapshot;
import com.jeesharp.business.modules.finance.settle.PaySettleMergePayRules;
import com.jeesharp.business.modules.finance.settle.support.PaySettleBizOrderResolver;
import com.jeesharp.framework.exception.BizErrorException;
import com.jeesharp.framework.pojo.Page;
import com.jeesharp.framework.pojo.query.PageRespVO;
import com.jeesharp.framework.utils.WebFrameworkUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 商户应收账应用服务：平台代收场景下支付记应收、退款记冲减，并提供查询与汇总。
 *
 * @author jeesharp
 * @since 2026-06-11
 */
@Slf4j
@Service
@AllArgsConstructor
@Transactional(readOnly = true)
public class MerchantReceivableApplicationService {

    private static final DateTimeFormatter DAY_KEY_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private final MerchantReceivableService merchantReceivableService;
    private final PlatformRevenueService platformRevenueService;
    private final MerchantSettleConfigApi merchantSettleConfigApi;
    private final PayOrderService payOrderService;
    private final PayRefundOrderService payRefundOrderService;
    private final PaySettleBizOrderResolver paySettleBizOrderResolver;

    public MerchantReceivableInfoVO get(String id) {
        MerchantReceivable entity = merchantReceivableService.get(id);
        if (entity == null) {
            throw new BizErrorException("应收流水不存在");
        }
        MerchantReceivableInfoVO vo = MerchantReceivableConvert.INSTANCE.toInfoVO(entity);
        enrichDisplayFields(vo, entity);
        return vo;
    }

    public PageRespVO<MerchantReceivableListVO> findPage(Page<MerchantReceivable> page, MerchantReceivableQueryVO query) {
        resolveQueryAssociations(query);
        Page<MerchantReceivable> result = merchantReceivableService.findPage(page, query);
        PageRespVO<MerchantReceivableListVO> pageVo = MerchantReceivableConvert.INSTANCE.toPageRespVO(result);
        enrichListDisplayFields(pageVo.getRecords(), result.getRecords());
        return pageVo;
    }

    public List<MerchantReceivableExportVO> findList(MerchantReceivableQueryVO query) {
        resolveQueryAssociations(query);
        List<MerchantReceivable> list = merchantReceivableService.findList(query);
        List<MerchantReceivableExportVO> exportList = MerchantReceivableConvert.INSTANCE.toExportVOList(list);
        enrichExportDisplayFields(exportList, list);
        return exportList;
    }

    public List<MerchantReceivableSettlementSummaryVO> summarize(MerchantReceivableSettlementQueryVO query) {
        if (query == null) {
            return Collections.emptyList();
        }
        return merchantReceivableService.summarizeByMerchant(query);
    }

    /**
     * 当前登录商户本租户账期汇总（强制绑定登录租户，忽略请求中的商户筛选）。
     */
    public MerchantReceivableSettlementSummaryVO summarizeMine(MerchantReceivableSettlementQueryVO query) {
        String tenantId = WebFrameworkUtils.getLoginUserTenantId();
        if (StrUtil.isBlank(tenantId)) {
            throw new BizErrorException("无法识别当前商户租户");
        }
        MerchantReceivableSettlementQueryVO effectiveQuery =
                query == null ? new MerchantReceivableSettlementQueryVO() : query;
        effectiveQuery.setMerchantTenantId(tenantId.trim());
        List<MerchantReceivableSettlementSummaryVO> rows =
                merchantReceivableService.summarizeByMerchant(effectiveQuery);
        if (rows == null || rows.isEmpty()) {
            return emptySettlementSummary(tenantId.trim());
        }
        return rows.get(0);
    }

    /**
     * 平台生成结算单：按指定商户与账期汇总应收，不走登录 dataScope。
     */
    public MerchantReceivableSettlementSummaryVO summarizeForSettlementBill(String merchantTenantId,
            LocalDateTime periodStart, LocalDateTime periodEnd) {
        if (StrUtil.isBlank(merchantTenantId)) {
            throw new BizErrorException("商户租户ID不能为空");
        }
        MerchantReceivableSettlementSummaryVO summary = merchantReceivableService.summarizeByMerchantForSettlement(
                merchantTenantId.trim(), periodStart, periodEnd);
        if (summary == null) {
            return emptySettlementSummary(merchantTenantId.trim());
        }
        return summary;
    }

    /**
     * 解析子单商户 tenant_code（与应收流水一致，无流水时回退商户租户ID）。
     */
    public String resolveTenantCodeByMerchantTenantId(String merchantTenantId) {
        if (StrUtil.isBlank(merchantTenantId)) {
            return null;
        }
        String code = merchantReceivableService.resolveTenantCodeByMerchantTenantId(merchantTenantId.trim());
        return StrUtil.isNotBlank(code) ? code.trim() : merchantTenantId.trim();
    }

    /**
     * 平台视角：按日或按月汇总平台佣金收入趋势。
     * <p>按日且未筛商户时优先读 {@code biz_platform_revenue}，当日数据实时补全。</p>
     */
    public List<PlatformCommissionPeriodSummaryVO> summarizePlatformCommission(
            MerchantReceivableSettlementQueryVO query) {
        if (query == null) {
            query = new MerchantReceivableSettlementQueryVO();
        }
        MerchantReceivableSummaryGroupByEnum groupBy =
                MerchantReceivableSummaryGroupByEnum.fromValue(query.getGroupBy());
        query.setGroupBy(groupBy.getValue());

        if (groupBy == MerchantReceivableSummaryGroupByEnum.MONTH
                || StrUtil.isNotBlank(query.getMerchantTenantId())) {
            return merchantReceivableService.summarizePlatformCommissionByPeriod(query);
        }
        return summarizePlatformCommissionByDayFromRollup(query);
    }

    private List<PlatformCommissionPeriodSummaryVO> summarizePlatformCommissionByDayFromRollup(
            MerchantReceivableSettlementQueryVO query) {
        LocalDate queryStart = toLocalDate(query.getBizTimeStart());
        LocalDate queryEnd = toLocalDate(query.getBizTimeEnd());
        LocalDate today = LocalDate.now();

        List<PlatformCommissionPeriodSummaryVO> rows = new ArrayList<>();
        if (queryStart == null || !queryStart.isAfter(today.minusDays(1))) {
            PlatformRevenueQueryVO revenueQuery = new PlatformRevenueQueryVO();
            revenueQuery.setPeriodType(PlatformRevenuePeriodTypeEnum.DAY.getValue());
            revenueQuery.setPlatformTenantId(PlatformRevenueConstants.DEFAULT_PLATFORM_TENANT_ID);
            if (queryStart != null) {
                revenueQuery.setStatDateStart(queryStart);
            }
            LocalDate tableEnd = queryEnd == null ? today.minusDays(1) : queryEnd;
            if (tableEnd.isAfter(today.minusDays(1))) {
                tableEnd = today.minusDays(1);
            }
            if (queryStart == null || !tableEnd.isBefore(queryStart)) {
                revenueQuery.setStatDateEnd(tableEnd);
                rows.addAll(platformRevenueService.findDailyTrend(revenueQuery));
            }
        }

        if (queryEnd == null || !queryEnd.isBefore(today)) {
            appendTodayLiveCommission(rows, today);
        }
        return rows;
    }

    private void appendTodayLiveCommission(List<PlatformCommissionPeriodSummaryVO> rows, LocalDate today) {
        String todayKey = today.format(DAY_KEY_FORMAT);
        Iterator<PlatformCommissionPeriodSummaryVO> iterator = rows.iterator();
        while (iterator.hasNext()) {
            PlatformCommissionPeriodSummaryVO row = iterator.next();
            if (todayKey.equals(row.getPeriodKey())) {
                iterator.remove();
            }
        }
        MerchantReceivableSettlementQueryVO todayQuery = new MerchantReceivableSettlementQueryVO();
        todayQuery.setGroupBy(MerchantReceivableSummaryGroupByEnum.DAY.getValue());
        todayQuery.setBizTimeStart(today.atStartOfDay());
        todayQuery.setBizTimeEnd(LocalDateTime.now());
        List<PlatformCommissionPeriodSummaryVO> liveRows =
                merchantReceivableService.summarizePlatformCommissionByPeriod(todayQuery);
        if (liveRows != null && !liveRows.isEmpty()) {
            rows.add(0, liveRows.get(0));
        }
    }

    private LocalDate toLocalDate(LocalDateTime dateTime) {
        return dateTime != null ? dateTime.toLocalDate() : null;
    }

    private MerchantReceivableSettlementSummaryVO emptySettlementSummary(String merchantTenantId) {
        MerchantReceivableSettlementSummaryVO vo = new MerchantReceivableSettlementSummaryVO();
        vo.setMerchantTenantId(merchantTenantId);
        vo.setPayCount(0L);
        vo.setRefundCount(0L);
        vo.setPayBaseAmount(BigDecimal.ZERO);
        vo.setRefundBaseAmount(BigDecimal.ZERO);
        vo.setNetCommissionAmount(BigDecimal.ZERO);
        vo.setNetMerchantAmount(BigDecimal.ZERO);
        return vo;
    }

    /**
     * 按商城子订单查询平台代收应收流水摘要。
     */
    public List<MerchantReceivableBriefDTO> listByMallOrderId(String mallOrderId) {
        if (StrUtil.isBlank(mallOrderId)) {
            return Collections.emptyList();
        }
        return merchantReceivableService.findListByMallOrderId(mallOrderId.trim()).stream()
                .map(this::toBriefDTO)
                .toList();
    }

    private MerchantReceivableBriefDTO toBriefDTO(MerchantReceivable entity) {
        MerchantReceivableBriefDTO dto = new MerchantReceivableBriefDTO();
        dto.setEntryType(entity.getEntryType());
        dto.setEntryTypeName(MerchantReceivableEntryTypeEnum.getDescByValue(entity.getEntryType()));
        dto.setSettleMode(entity.getSettleMode());
        dto.setBaseAmount(entity.getBaseAmount());
        dto.setCommissionRate(entity.getCommissionRate());
        dto.setCommissionAmount(entity.getCommissionAmount());
        dto.setMerchantAmount(entity.getMerchantAmount());
        dto.setBizTime(entity.getBizTime());
        return dto;
    }

    /**
     * 商城支付成功后为平台代收子单记应收（幂等）。
     */
    @Transactional(readOnly = false)
    public void recordForMallPay(String financePayOrderId, String payBatchId, String transactionId) {
        if (StrUtil.isBlank(financePayOrderId)) {
            return;
        }
        PayOrder payOrder = payOrderService.get(financePayOrderId);
        if (payOrder == null) {
            return;
        }
        if (!SettleModeEnum.PLATFORM_COLLECT.getValue().equals(payOrder.getSettleMode())) {
            return;
        }
        if (PayOrderWechatRouteSupport.isPartnerMode(payOrder)
                && !PayOrderWechatRouteSupport.hasPartnerPayRoute(payOrder)) {
            return;
        }
        String txnId = StrUtil.blankToDefault(transactionId, payOrder.getThirdPartyTradeNo());
        List<PaySettleBizOrderSnapshot> subOrders = resolveSubOrders(payOrder.getBizScene(), payBatchId, payOrder);
        LocalDateTime bizTime = payOrder.getPayTime() != null ? payOrder.getPayTime() : LocalDateTime.now();
        for (PaySettleBizOrderSnapshot sub : subOrders) {
            if (sub == null || StrUtil.isBlank(sub.getBizOrderId())) {
                continue;
            }
            String subBatchId = StrUtil.blankToDefault(sub.getPayBatchId(), payBatchId);
            recordPayForSubOrder(sub, payOrder, subBatchId, txnId, bizTime, payOrder.getBizScene());
        }
    }

    /**
     * 退款成功后记商户应收冲减（幂等）。
     */
    @Transactional(readOnly = false)
    public void recordForRefund(String payRefundOrderId) {
        if (StrUtil.isBlank(payRefundOrderId)) {
            return;
        }
        recordForRefund(payRefundOrderService.get(payRefundOrderId.trim()));
    }

    /**
     * 退款成功后记商户应收冲减（幂等）。
     */
    @Transactional(readOnly = false)
    public void recordForRefund(PayRefundOrder refundOrder) {
        if (refundOrder == null || StrUtil.isBlank(refundOrder.getId())) {
            return;
        }
        if (merchantReceivableService.findByPayRefundOrderId(refundOrder.getId()) != null) {
            return;
        }
        PayOrder payOrder = payOrderService.get(refundOrder.getFinancePayOrderId());
        if (payOrder == null || !SettleModeEnum.PLATFORM_COLLECT.getValue().equals(payOrder.getSettleMode())) {
            return;
        }
        String merchantTenantId = StrUtil.blankToDefault(refundOrder.getMerchantTenantId(), payOrder.getTenantId());
        MerchantSettleConfigSnapshotVO snapshot = merchantSettleConfigApi.resolveSnapshot(merchantTenantId);
        if (!SettleModeEnum.PLATFORM_COLLECT.getValue().equals(snapshot.getSettleMode())) {
            return;
        }
        BigDecimal baseAmount = refundOrder.getRefundAmount() == null ? BigDecimal.ZERO : refundOrder.getRefundAmount();
        if (baseAmount.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        AmountSplit split = calcAmountSplit(baseAmount, snapshot.getCommissionRate(), true);

        MerchantReceivable entity = new MerchantReceivable();
        entity.setReceivableNo("MR" + IdUtil.getSnowflakeNextIdStr());
        entity.setEntryType(MerchantReceivableEntryTypeEnum.REFUND.getValue());
        entity.setFinancePayOrderId(refundOrder.getFinancePayOrderId());
        entity.setPayBatchId(refundOrder.getPayBatchId());
        entity.setMallOrderId(refundOrder.getMallOrderId());
        entity.setPayRefundOrderId(refundOrder.getId());
        entity.setBizScene(StrUtil.blankToDefault(refundOrder.getBizScene(), PayRecordBizSceneEnum.MALL_ORDER.getCode()));
        entity.setMerchantTenantId(merchantTenantId);
        entity.setSettleMode(SettleModeEnum.PLATFORM_COLLECT.getValue());
        entity.setTransactionId(refundOrder.getTransactionId());
        entity.setOutTradeNo(refundOrder.getOutTradeNo());
        entity.setBaseAmount(baseAmount.negate());
        entity.setCommissionRate(snapshot.getCommissionRate() != null ? snapshot.getCommissionRate() : BigDecimal.ZERO);
        entity.setCommissionAmount(split.commissionAmount());
        entity.setMerchantAmount(split.merchantAmount());
        entity.setBizTime(refundOrder.getRefundTime() != null ? refundOrder.getRefundTime() : LocalDateTime.now());
        entity.setTenantId(merchantTenantId);
        merchantReceivableService.save(entity);
    }

    private void recordPayForSubOrder(PaySettleBizOrderSnapshot sub, PayOrder payOrder, String payBatchId,
            String transactionId, LocalDateTime bizTime, String bizScene) {
        if (merchantReceivableService.findByMallOrderIdAndEntryType(sub.getBizOrderId(),
                MerchantReceivableEntryTypeEnum.PAY.getValue()) != null) {
            return;
        }
        MerchantSettleConfigSnapshotVO snapshot = merchantSettleConfigApi.resolveSnapshot(sub.getTenantId());
        if (!SettleModeEnum.PLATFORM_COLLECT.getValue().equals(snapshot.getSettleMode())) {
            return;
        }
        BigDecimal baseAmount = resolvePayAmount(sub);
        if (baseAmount.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        AmountSplit split = calcAmountSplit(baseAmount, snapshot.getCommissionRate(), false);

        MerchantReceivable entity = new MerchantReceivable();
        entity.setReceivableNo("MR" + IdUtil.getSnowflakeNextIdStr());
        entity.setEntryType(MerchantReceivableEntryTypeEnum.PAY.getValue());
        entity.setFinancePayOrderId(payOrder.getId());
        entity.setPayBatchId(payBatchId);
        entity.setMallOrderId(sub.getBizOrderId());
        entity.setBizScene(StrUtil.blankToDefault(bizScene, PayRecordBizSceneEnum.MALL_ORDER.getCode()));
        entity.setMerchantTenantId(sub.getTenantId());
        entity.setSettleMode(SettleModeEnum.PLATFORM_COLLECT.getValue());
        entity.setTransactionId(transactionId);
        entity.setOutTradeNo(payOrder.getOutTradeNo());
        entity.setBaseAmount(baseAmount);
        entity.setCommissionRate(snapshot.getCommissionRate() != null ? snapshot.getCommissionRate() : BigDecimal.ZERO);
        entity.setCommissionAmount(split.commissionAmount());
        entity.setMerchantAmount(split.merchantAmount());
        entity.setBizTime(bizTime);
        entity.setTenantId(sub.getTenantId());
        merchantReceivableService.save(entity);
    }

    private List<PaySettleBizOrderSnapshot> resolveSubOrders(String bizScene, String payBatchId, PayOrder payOrder) {
        return paySettleBizOrderResolver.listSubOrdersForPay(bizScene, payBatchId, payOrder.getBizOrderId());
    }

    private static BigDecimal resolvePayAmount(PaySettleBizOrderSnapshot order) {
        if (order.getPayAmount() != null && order.getPayAmount().compareTo(BigDecimal.ZERO) > 0) {
            return order.getPayAmount();
        }
        return order.getTotalAmount() == null ? BigDecimal.ZERO : order.getTotalAmount();
    }

    private static AmountSplit calcAmountSplit(BigDecimal baseAmount, BigDecimal commissionRate, boolean negate) {
        BigDecimal base = baseAmount == null ? BigDecimal.ZERO : baseAmount;
        BigDecimal rate = commissionRate == null ? BigDecimal.ZERO : commissionRate;
        BigDecimal commission = base.multiply(rate).setScale(2, RoundingMode.HALF_UP);
        BigDecimal merchant = base.subtract(commission);
        if (negate) {
            commission = commission.negate();
            merchant = merchant.negate();
        }
        return new AmountSplit(commission, merchant);
    }

    private void resolveQueryAssociations(MerchantReceivableQueryVO query) {
        if (query == null) {
            return;
        }
        String bizScene = PayRecordBizSceneEnum.MALL_ORDER.getCode();
        if (StrUtil.isNotBlank(query.getOrderNo()) && StrUtil.isBlank(query.getMallOrderId())) {
            String orderId = paySettleBizOrderResolver.findFirstOrderIdByOrderNo(bizScene, query.getOrderNo());
            if (StrUtil.isNotBlank(orderId)) {
                query.setMallOrderId(orderId);
            }
        }
        if (StrUtil.isNotBlank(query.getBatchNo()) && StrUtil.isBlank(query.getPayBatchId())) {
            String batchId = paySettleBizOrderResolver.findPayBatchIdByBatchNo(bizScene, query.getBatchNo());
            if (StrUtil.isNotBlank(batchId)) {
                query.setPayBatchId(batchId);
            }
        }
    }

    private void enrichListDisplayFields(List<MerchantReceivableListVO> voList, List<MerchantReceivable> entities) {
        if (voList == null || entities == null || voList.isEmpty()) {
            return;
        }
        Map<String, String> orderNoMap = loadOrderNoMap(entities);
        Map<String, String> batchNoMap = loadBatchNoMap(entities);
        for (int i = 0; i < voList.size() && i < entities.size(); i++) {
            MerchantReceivableListVO vo = voList.get(i);
            MerchantReceivable entity = entities.get(i);
            vo.setOrderNo(orderNoMap.get(entity.getMallOrderId()));
            vo.setBatchNo(batchNoMap.get(entity.getPayBatchId()));
        }
    }

    private void enrichDisplayFields(MerchantReceivableInfoVO vo, MerchantReceivable entity) {
        if (vo == null || entity == null) {
            return;
        }
        String bizScene = StrUtil.blankToDefault(entity.getBizScene(), PayRecordBizSceneEnum.MALL_ORDER.getCode());
        if (StrUtil.isNotBlank(entity.getMallOrderId())) {
            PaySettleBizOrderSnapshot mallOrder = paySettleBizOrderResolver.getOrder(bizScene, entity.getMallOrderId());
            if (mallOrder != null) {
                vo.setOrderNo(mallOrder.getOrderNo());
            }
        }
        if (PaySettleMergePayRules.supportsMergePayBatch(bizScene) && StrUtil.isNotBlank(entity.getPayBatchId())) {
            Map<String, String> batchMap = paySettleBizOrderResolver.mapBatchNoByIds(bizScene,
                    List.of(entity.getPayBatchId()));
            vo.setBatchNo(batchMap.get(entity.getPayBatchId()));
        }
    }

    private void enrichExportDisplayFields(List<MerchantReceivableExportVO> voList, List<MerchantReceivable> entities) {
        if (voList == null || entities == null || voList.isEmpty()) {
            return;
        }
        Map<String, String> orderNoMap = loadOrderNoMap(entities);
        Map<String, String> batchNoMap = loadBatchNoMap(entities);
        for (int i = 0; i < voList.size() && i < entities.size(); i++) {
            MerchantReceivableExportVO vo = voList.get(i);
            MerchantReceivable entity = entities.get(i);
            vo.setOrderNo(orderNoMap.get(entity.getMallOrderId()));
            vo.setBatchNo(batchNoMap.get(entity.getPayBatchId()));
            vo.setMerchantTenantId(entity.getMerchantTenantId());
            vo.setTransactionId(entity.getTransactionId());
        }
    }

    private Map<String, String> loadOrderNoMap(List<MerchantReceivable> entities) {
        if (entities == null || entities.isEmpty()) {
            return new HashMap<>();
        }
        return paySettleBizOrderResolver.mapOrderNoByIds(PayRecordBizSceneEnum.MALL_ORDER.getCode(), entities.stream()
                .map(MerchantReceivable::getMallOrderId)
                .filter(StrUtil::isNotBlank)
                .toList());
    }

    private Map<String, String> loadBatchNoMap(List<MerchantReceivable> entities) {
        if (entities == null || entities.isEmpty()) {
            return new HashMap<>();
        }
        return paySettleBizOrderResolver.mapBatchNoByIds(PayRecordBizSceneEnum.MALL_ORDER.getCode(), entities.stream()
                .filter(e -> PaySettleMergePayRules.supportsMergePayBatch(
                        StrUtil.blankToDefault(e.getBizScene(), PayRecordBizSceneEnum.MALL_ORDER.getCode())))
                .map(MerchantReceivable::getPayBatchId)
                .filter(StrUtil::isNotBlank)
                .toList());
    }

    private record AmountSplit(BigDecimal commissionAmount, BigDecimal merchantAmount) {
    }
}
