package com.jeesharp.business.modules.pay.route;

import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.pay.config.weixin.PayWechatCredentialSupport;
import com.jeesharp.business.modules.pay.config.weixin.PayWechatWxPayClientHolder;
import com.jeesharp.business.modules.pay.dto.BasicPayOrderData;
import com.jeesharp.business.modules.pay.dto.PayWechatSubPayItemDTO;
import com.jeesharp.business.modules.pay.paychannelconfig.support.PayChannelTenantSupport;
import com.jeesharp.business.modules.pay.paywechatconfig.entity.PayWechatConfig;
import com.jeesharp.business.modules.pay.paywechatconfig.enums.WechatPayModeEnum;
import com.jeesharp.business.modules.pay.paywechatconfig.enums.WechatPayRouteTypeEnum;
import com.jeesharp.business.modules.pay.route.support.PayWechatSubMerchantRouteSupport;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 解析微信 JSAPI 预下单路由上下文：读 L1 wechat_pay_mode、解析 sub_mchid、确定 DIRECT/PARTNER/COMBINE。
 *
 * @author jeesharp
 * @since 2026-06-12
 */
@Component
@RequiredArgsConstructor
public class PayWechatPayRouteResolver {

    private final PayWechatWxPayClientHolder payWechatWxPayClientHolder;
    private final PayWechatSubMerchantRouteSupport subMerchantRouteSupport;

    public PayWechatPayRouteContext resolve(BasicPayOrderData payOrderData) {
        String tenantId = StrUtil.blankToDefault(payOrderData.getTenantId(), PayChannelTenantSupport.PLATFORM_TENANT_ID);
        PayWechatConfig config = payWechatWxPayClientHolder.requireActiveConfig(tenantId);
        WechatPayModeEnum payMode = WechatPayModeEnum.fromValue(config.getWechatPayMode());

        PayWechatPayRouteContext context = new PayWechatPayRouteContext();
        context.setConfig(config);
        context.setWechatPayMode(payMode);
        context.setPlatformTenantId(tenantId);

        if (payMode == WechatPayModeEnum.DIRECT) {
            context.setPayRouteType(WechatPayRouteTypeEnum.DIRECT);
            return context;
        }

        List<PayWechatSubPayItemDTO> rawItems = payOrderData.getSubPayItems();
        if (rawItems == null || rawItems.isEmpty()) {
            throw new IllegalStateException("PARTNER 模式须传入 subPayItems（商户租户与金额）");
        }

        Map<String, PayWechatPayRouteContext.ResolvedSubPayItem> merged = new LinkedHashMap<>();
        for (PayWechatSubPayItemDTO raw : rawItems) {
            if (raw == null || StrUtil.isBlank(raw.getMerchantTenantId())) {
                continue;
            }
            String merchantTenantId = raw.getMerchantTenantId().trim();
            String subMchId = subMerchantRouteSupport.requireSubMchId(merchantTenantId);
            int amountFen = raw.getAmountFen() == null ? 0 : raw.getAmountFen().intValue();
            if (amountFen < 1) {
                throw new IllegalStateException("子单金额必须大于 0，merchantTenantId=" + merchantTenantId);
            }
            PayWechatPayRouteContext.ResolvedSubPayItem item = merged.computeIfAbsent(subMchId, key -> {
                PayWechatPayRouteContext.ResolvedSubPayItem created = new PayWechatPayRouteContext.ResolvedSubPayItem();
                created.setMerchantTenantId(merchantTenantId);
                created.setSubMchId(subMchId);
                created.setBizOrderId(raw.getBizOrderId());
                created.setDescription(raw.getDescription());
                created.setAttach(raw.getAttach());
                created.setProfitSharing(Boolean.TRUE.equals(raw.getNeedProfitSharing()));
                created.setAmountFen(0);
                return created;
            });
            item.setAmountFen(item.getAmountFen() + amountFen);
            if (Boolean.TRUE.equals(raw.getNeedProfitSharing())) {
                item.setProfitSharing(true);
            }
        }

        if (merged.isEmpty()) {
            throw new IllegalStateException("未能解析任何有效 sub_mchid");
        }

        context.setSubPayItems(new ArrayList<>(merged.values()));
        if (merged.size() == 1) {
            context.setPayRouteType(WechatPayRouteTypeEnum.PARTNER);
        } else {
            context.setPayRouteType(WechatPayRouteTypeEnum.COMBINE);
        }
        return context;
    }

    public boolean isWxEnabled(String tenantId) {
        PayWechatConfig config = payWechatWxPayClientHolder.findActiveConfig(tenantId);
        return config != null && PayWechatCredentialSupport.isWxEnabled(config);
    }
}
