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

import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.pay.combine.dto.PayCombineCloseRequestDTO;
import com.jeesharp.business.modules.pay.combine.dto.PayCombineTransactionResultDTO;
import com.jeesharp.business.modules.pay.combine.support.PayWechatCombineTransactionClient;
import com.jeesharp.business.modules.pay.direct.support.PayWechatDirectTransactionClient;
import com.jeesharp.business.modules.pay.dto.PayWechatTransactionOpsRequestDTO;
import com.jeesharp.business.modules.pay.dto.PayWechatTransactionOpsResultDTO;
import com.jeesharp.business.modules.pay.partner.dto.PayPartnerCloseRequestDTO;
import com.jeesharp.business.modules.pay.partner.dto.PayPartnerTransactionResultDTO;
import com.jeesharp.business.modules.pay.partner.support.PayWechatPartnerTransactionClient;
import com.jeesharp.business.modules.pay.paywechatconfig.enums.WechatPayRouteTypeEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * 微信查单/关单路由器：按 {@code payRouteType} 委托 DIRECT / PARTNER / COMBINE Client，与预下单路由成对。
 *
 * @author jeesharp
 * @since 2026-06-12
 */
@Service
@RequiredArgsConstructor
public class PayWechatTransactionOpsService {

    private final PayWechatDirectTransactionClient directTransactionClient;
    private final PayWechatPartnerTransactionClient partnerTransactionClient;
    private final PayWechatCombineTransactionClient combineTransactionClient;

    public PayWechatTransactionOpsResultDTO query(PayWechatTransactionOpsRequestDTO request) {
        WechatPayRouteTypeEnum routeType = resolveRouteType(request);
        return switch (routeType) {
            case PARTNER -> fromPartner(partnerTransactionClient.queryByOutTradeNo(
                    request.getPlatformTenantId(),
                    requireSubMchId(request),
                    requireOutTradeNo(request)));
            case COMBINE -> fromCombine(combineTransactionClient.queryByOutTradeNo(
                    request.getPlatformTenantId(),
                    requireCombineOutTradeNo(request)));
            default -> directTransactionClient.queryByOutTradeNo(
                    request.getPlatformTenantId(),
                    requireOutTradeNo(request));
        };
    }

    public PayWechatTransactionOpsResultDTO close(PayWechatTransactionOpsRequestDTO request) {
        WechatPayRouteTypeEnum routeType = resolveRouteType(request);
        return switch (routeType) {
            case PARTNER -> {
                PayPartnerCloseRequestDTO closeReq = new PayPartnerCloseRequestDTO();
                closeReq.setPlatformTenantId(request.getPlatformTenantId());
                closeReq.setOutTradeNo(requireOutTradeNo(request));
                closeReq.setSubMchId(requireSubMchId(request));
                yield fromPartner(partnerTransactionClient.close(closeReq));
            }
            case COMBINE -> {
                PayCombineCloseRequestDTO closeReq = new PayCombineCloseRequestDTO();
                closeReq.setPlatformTenantId(request.getPlatformTenantId());
                closeReq.setCombineOutTradeNo(requireCombineOutTradeNo(request));
                yield fromCombine(combineTransactionClient.close(closeReq));
            }
            default -> directTransactionClient.close(
                    request.getPlatformTenantId(),
                    requireOutTradeNo(request));
        };
    }

    public static PayWechatTransactionOpsRequestDTO fromPayOrderRoute(
            String platformTenantId,
            String payRouteType,
            String outTradeNo,
            String subMchId,
            String combineOutTradeNo) {
        PayWechatTransactionOpsRequestDTO dto = new PayWechatTransactionOpsRequestDTO();
        dto.setPlatformTenantId(platformTenantId);
        dto.setPayRouteType(payRouteType);
        dto.setOutTradeNo(outTradeNo);
        dto.setSubMchId(subMchId);
        dto.setCombineOutTradeNo(combineOutTradeNo);
        return dto;
    }

    private static WechatPayRouteTypeEnum resolveRouteType(PayWechatTransactionOpsRequestDTO request) {
        WechatPayRouteTypeEnum routeType = WechatPayRouteTypeEnum.fromValue(request.getPayRouteType());
        return routeType != null ? routeType : WechatPayRouteTypeEnum.DIRECT;
    }

    private static String requireOutTradeNo(PayWechatTransactionOpsRequestDTO request) {
        if (StrUtil.isBlank(request.getOutTradeNo())) {
            throw new IllegalArgumentException("out_trade_no 不能为空");
        }
        return request.getOutTradeNo().trim();
    }

    private static String requireSubMchId(PayWechatTransactionOpsRequestDTO request) {
        if (StrUtil.isBlank(request.getSubMchId())) {
            throw new IllegalArgumentException("partner 查关单须 sub_mchid");
        }
        return request.getSubMchId().trim();
    }

    private static String requireCombineOutTradeNo(PayWechatTransactionOpsRequestDTO request) {
        String combineNo = StrUtil.blankToDefault(request.getCombineOutTradeNo(), request.getOutTradeNo());
        if (StrUtil.isBlank(combineNo)) {
            throw new IllegalArgumentException("combine_out_trade_no 不能为空");
        }
        return combineNo.trim();
    }

    private static PayWechatTransactionOpsResultDTO fromPartner(PayPartnerTransactionResultDTO source) {
        PayWechatTransactionOpsResultDTO result = new PayWechatTransactionOpsResultDTO();
        result.setSuccess(source.getSuccess());
        result.setTradeState(source.getTradeState());
        result.setErrorMsg(source.getErrorMsg());
        result.setRawResponse(source.getRawResponse());
        return result;
    }

    private static PayWechatTransactionOpsResultDTO fromCombine(PayCombineTransactionResultDTO source) {
        PayWechatTransactionOpsResultDTO result = new PayWechatTransactionOpsResultDTO();
        result.setSuccess(source.getSuccess());
        result.setCombineState(source.getCombineState());
        result.setErrorMsg(source.getErrorMsg());
        result.setRawResponse(source.getRawResponse());
        return result;
    }
}
