package com.jeesharp.business.modules.finance.settle.support;

import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.finance.api.PaySettleBizOrderProvider;
import com.jeesharp.business.modules.finance.api.dto.PaySettleBizOrderSnapshot;
import com.jeesharp.business.modules.finance.settle.PaySettleMergePayRules;
import com.jeesharp.framework.exception.BizErrorException;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 按业务场景路由 {@link PaySettleBizOrderProvider}，供退款/分账/应收账统一读取子单摘要。
 *
 * @author jeesharp
 * @since 2026-06-11
 */
@Component
@AllArgsConstructor
public class PaySettleBizOrderResolver {

    private final List<PaySettleBizOrderProvider> providers;
    private final GenericPaySettleBizOrderProvider genericPaySettleBizOrderProvider;

    public PaySettleBizOrderSnapshot getOrder(String bizScene, String bizOrderId) {
        requireBizScene(bizScene);
        if (StrUtil.isBlank(bizOrderId)) {
            return null;
        }
        return resolveProvider(bizScene).getOrder(bizOrderId.trim());
    }

    public List<PaySettleBizOrderSnapshot> listSubOrdersForPay(String bizScene, String payBatchId, String bizOrderId) {
        requireBizScene(bizScene);
        return resolveProvider(bizScene).listSubOrdersForPay(payBatchId, bizOrderId);
    }

    public String findFirstOrderIdByOrderNo(String bizScene, String orderNo) {
        requireBizScene(bizScene);
        if (StrUtil.isBlank(orderNo)) {
            return null;
        }
        return resolveProvider(bizScene).findFirstOrderIdByOrderNo(orderNo.trim());
    }

    public String findPayBatchIdByBatchNo(String bizScene, String batchNo) {
        requireBizScene(bizScene);
        if (!PaySettleMergePayRules.supportsMergePayBatch(bizScene) || StrUtil.isBlank(batchNo)) {
            return null;
        }
        return resolveProvider(bizScene).findPayBatchIdByBatchNo(batchNo.trim());
    }

    public Map<String, String> mapOrderNoByIds(String bizScene, Collection<String> bizOrderIds) {
        requireBizScene(bizScene);
        if (bizOrderIds == null || bizOrderIds.isEmpty()) {
            return Collections.emptyMap();
        }
        return resolveProvider(bizScene).mapOrderNoByIds(bizOrderIds);
    }

    public Map<String, String> mapBatchNoByIds(String bizScene, Collection<String> payBatchIds) {
        requireBizScene(bizScene);
        if (!PaySettleMergePayRules.supportsMergePayBatch(bizScene) || payBatchIds == null || payBatchIds.isEmpty()) {
            return Collections.emptyMap();
        }
        return resolveProvider(bizScene).mapBatchNoByIds(payBatchIds);
    }

    private PaySettleBizOrderProvider resolveProvider(String bizScene) {
        for (PaySettleBizOrderProvider provider : providers) {
            if (provider != null && bizScene.equals(provider.bizScene())) {
                return provider;
            }
        }
        return new DelegatingGenericProvider(bizScene, genericPaySettleBizOrderProvider);
    }

    private static void requireBizScene(String bizScene) {
        if (StrUtil.isBlank(bizScene)) {
            throw new BizErrorException("业务场景不能为空");
        }
    }

    /**
     * 将通用兜底适配为 {@link PaySettleBizOrderProvider} 形态，避免可变场景状态。
     */
    private record DelegatingGenericProvider(String bizScene, GenericPaySettleBizOrderProvider delegate)
            implements PaySettleBizOrderProvider {

        @Override
        public String bizScene() {
            return bizScene;
        }

        @Override
        public PaySettleBizOrderSnapshot getOrder(String bizOrderId) {
            return delegate.getOrder(bizScene, bizOrderId);
        }

        @Override
        public List<PaySettleBizOrderSnapshot> listSubOrdersForPay(String payBatchId, String bizOrderId) {
            return delegate.listSubOrdersForPay(bizScene, payBatchId, bizOrderId);
        }

        @Override
        public String findFirstOrderIdByOrderNo(String orderNo) {
            return null;
        }

        @Override
        public String findPayBatchIdByBatchNo(String batchNo) {
            return null;
        }

        @Override
        public Map<String, String> mapOrderNoByIds(Collection<String> bizOrderIds) {
            return new HashMap<>();
        }

        @Override
        public Map<String, String> mapBatchNoByIds(Collection<String> payBatchIds) {
            return new HashMap<>();
        }
    }
}
