package com.gxwebsoft.shop.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.context.TenantContext;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.config.CertificateProperties;
import com.gxwebsoft.common.core.utils.*;
import com.gxwebsoft.common.core.service.PaymentCacheService;
import com.gxwebsoft.common.core.service.EnvironmentAwarePaymentService;
import com.gxwebsoft.common.core.config.SpringContextUtil;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.shop.entity.*;
import com.gxwebsoft.shop.service.*;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import lombok.extern.slf4j.Slf4j;
import com.gxwebsoft.common.system.service.PaymentService;
import com.gxwebsoft.common.system.service.SettingService;
import com.gxwebsoft.payment.constants.WechatPayType;
import com.gxwebsoft.shop.mapper.ShopOrderMapper;
import com.gxwebsoft.shop.param.ShopOrderParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAConfig;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
// Native支付的类将使用完全限定名避免冲突
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 订单Service实现
 *
 * @author 科技小王子
 * @since 2025-01-11 10:45:12
 */
@Slf4j
@Service
public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder> implements ShopOrderService {
    @Value("${spring.profiles.active}")
    String active;
    @Resource
    private ConfigProperties config;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ShopOrderGoodsService shopOrderGoodsService;
    @Resource
    private ShopGoodsService shopGoodsService;
    @Resource
    private PaymentService paymentService;
    @Resource
    private SettingService settingService;
    @Resource
    private CertificateProperties certConfig;
    @Resource
    private CertificateLoader certificateLoader;
    @Resource
    private PaymentCacheService paymentCacheService;
    @Resource
    private WechatCertAutoConfig wechatCertAutoConfig;
    @Resource
    private WechatPayDiagnostic wechatPayDiagnostic;
    @Resource
    private WechatPayCertificateDiagnostic certificateDiagnostic;
    @Resource
    private ShopOrderUpdate10550Service shopOrderUpdate10550Service;
    @Resource
    private ShopUserCouponService shopUserCouponService;
    @Resource
    private ShopOrderDeliveryService shopOrderDeliveryService;
    @Resource
    private ShopExpressService shopExpressService;
    @Resource
    private ShopGoodsSkuService shopGoodsSkuService;

    private static final long USER_ORDER_STATS_CACHE_SECONDS = 60L;
    private static final long WECHAT_PREPAY_SNAPSHOT_TTL_MINUTES = 30L;
    private static final String WECHAT_PREPAY_SNAPSHOT_KEY_PREFIX = "wxpay:prepay:snapshot:";
    private static final int DEDUCT_STOCK_TYPE_PAY = 20; // 付款减库存

    @Data
    private static class WechatPrepaySnapshot {
        private String outTradeNo;
        private String appid;
        private String mchid;
        private String openid;
        private Integer total; // 分
        private String description;
        private String notifyUrl;
        private String attach;
        private String wechatPayType;
    }

    private static String trimTrailingSlashes(String url) {
        if (url == null) {
            return null;
        }
        String u = url.trim();
        while (u.endsWith("/")) {
            u = u.substring(0, u.length() - 1);
        }
        return u;
    }

    private static String ensureTenantSuffix(String baseUrl, Integer tenantId) {
        if (StrUtil.isBlank(baseUrl) || tenantId == null) {
            return baseUrl;
        }
        String base = trimTrailingSlashes(baseUrl);
        String suffix = "/" + tenantId;
        if (base.endsWith(suffix)) {
            return base;
        }
        return base + suffix;
    }

    private static String baseApiUrlFromNotifyUrl(String notifyUrl) {
        if (StrUtil.isBlank(notifyUrl)) {
            return null;
        }
        String u = trimTrailingSlashes(notifyUrl);
        if (u.endsWith("/api")) {
            return u;
        }
        int idx = u.indexOf("/api/");
        if (idx >= 0) {
            return u.substring(0, idx + "/api".length());
        }
        // Fallback: treat notifyUrl itself as base.
        return u;
    }

    private String prepaySnapshotKey(Payment payment, String outTradeNo) {
        return WECHAT_PREPAY_SNAPSHOT_KEY_PREFIX + payment.getMchId() + ":" + outTradeNo;
    }

    private WechatPrepaySnapshot getPrepaySnapshot(Payment payment, String outTradeNo) {
        try {
            return redisUtil.get(prepaySnapshotKey(payment, outTradeNo), WechatPrepaySnapshot.class);
        } catch (Exception e) {
            // 缓存不可用时不影响支付主流程
            log.warn("读取微信预下单快照失败 - outTradeNo={}, mchId={}", outTradeNo, payment != null ? payment.getMchId() : null, e);
            return null;
        }
    }

    private void savePrepaySnapshot(Payment payment, WechatPrepaySnapshot snapshot) {
        if (payment == null || snapshot == null || StrUtil.isBlank(snapshot.getOutTradeNo())) {
            return;
        }
        try {
            redisUtil.set(prepaySnapshotKey(payment, snapshot.getOutTradeNo()), snapshot, WECHAT_PREPAY_SNAPSHOT_TTL_MINUTES, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.warn("保存微信预下单快照失败 - outTradeNo={}, mchId={}", snapshot.getOutTradeNo(), payment.getMchId(), e);
        }
    }

    private static boolean isIdempotencyParamMismatch(Throwable t) {
        Throwable cur = t;
        while (cur != null) {
            if (cur instanceof ServiceException) {
                ServiceException se = (ServiceException) cur;
                String code = se.getErrorCode();
                String msg = se.getErrorMessage();
                String body = se.getResponseBody();
                if ("INVALID_REQUEST".equals(code) && ((msg != null && msg.contains("请求重入")) || (body != null && body.contains("请求重入")))) {
                    return true;
                }
            }
            String m = cur.getMessage();
            if (m != null && m.contains("INVALID_REQUEST") && m.contains("请求重入")) {
                return true;
            }
            cur = cur.getCause();
        }
        return false;
    }

    private static Integer toFen(BigDecimal amountYuan) {
        if (amountYuan == null) {
            return null;
        }
        // 微信支付金额字段使用整数分，这里按两位小数四舍五入再转分
        BigDecimal fen = amountYuan.setScale(2, RoundingMode.HALF_UP).movePointRight(2);
        return fen.intValueExact();
    }

    private String defaultShopOrderNotifyUrl(Payment payment, Integer tenantId) {
        String base = payment != null ? trimTrailingSlashes(payment.getNotifyUrl()) : null;
        if (StrUtil.isBlank(base) || tenantId == null) {
            return null;
        }
        // If DB notifyUrl is already a notify endpoint (recommended), just append tenantId if missing.
        if (base.contains("/notify")) {
            return ensureTenantSuffix(base, tenantId);
        }
        // If DB notifyUrl is just the API gateway base, append the standard notify path.
        return base + "/shop/shop-order/notify/" + tenantId;
    }

    private String legacySystemWxPayNotifyUrl(Payment payment, Integer tenantId) {
        String base = baseApiUrlFromNotifyUrl(payment != null ? payment.getNotifyUrl() : null);
        if (StrUtil.isBlank(base) || tenantId == null) {
            return null;
        }
        return base + "/system/wx-pay/notify/" + tenantId;
    }

    private String legacyShopWxPayNotifyUrl(Integer tenantId) {
        // 旧代码曾使用 /api/shop/wx-pay/notify/{tenantId}
        if (tenantId == null) {
            return null;
        }
        return "http://jimei-api.natapp1.cc/api/shop/wx-pay/notify/" + tenantId;
    }

    private String devShopOrderNotifyUrl(Integer tenantId) {
        if (tenantId == null) {
            return null;
        }
        return "http://jimei-api.natapp1.cc/api/shop/shop-order/notify/" + tenantId;
    }

    private List<String> buildNotifyUrlCandidates(ShopOrder order, Payment payment, WechatPrepaySnapshot snapshot) {
        LinkedHashSet<String> urls = new LinkedHashSet<>();
        if (snapshot != null && StrUtil.isNotBlank(snapshot.getNotifyUrl())) {
            urls.add(trimTrailingSlashes(snapshot.getNotifyUrl()));
        }

        // 回调地址优先从数据库支付配置读取
        String paymentNotify = defaultShopOrderNotifyUrl(payment, order.getTenantId());
        if (StrUtil.isNotBlank(paymentNotify)) {
            urls.add(paymentNotify);
        }

        // 兼容历史回调地址（用于已创建订单的“重新支付”重入校验）
        String legacySystem = legacySystemWxPayNotifyUrl(payment, order.getTenantId());
        if (StrUtil.isNotBlank(legacySystem)) {
            urls.add(legacySystem);
        }

        if ("dev".equals(active)) {
            String devNotify = devShopOrderNotifyUrl(order.getTenantId());
            if (StrUtil.isNotBlank(devNotify)) {
                urls.add(devNotify);
            }
            String devLegacy = legacyShopWxPayNotifyUrl(order.getTenantId());
            if (StrUtil.isNotBlank(devLegacy)) {
                urls.add(devLegacy);
            }
        }

        return new ArrayList<>(urls);
    }


    @Override
    public PageResult<ShopOrder> pageRel(ShopOrderParam param) {
        PageParam<ShopOrder, ShopOrderParam> page = new PageParam<>(param);
        page.setDefaultOrder("sort_number asc, create_time desc");
        List<ShopOrder> list = baseMapper.selectPageRel(page, param);

        // 整理订单数据
        if (!CollectionUtils.isEmpty(list)) {
            final Set<Integer> orderIds = list.stream().map(ShopOrder::getOrderId).collect(Collectors.toSet());
            final List<ShopOrderGoods> goodsList = shopOrderGoodsService.list(new LambdaQueryWrapper<ShopOrderGoods>().in(ShopOrderGoods::getOrderId, orderIds));
            final Map<Integer, List<ShopOrderGoods>> collect = goodsList.stream().collect(Collectors.groupingBy(ShopOrderGoods::getOrderId));
            list.forEach(d -> {
                d.setOrderGoods(collect.get(d.getOrderId()));

                // 确保 realName 字段有值，优先使用关联查询的结果，如果为空则使用订单表中的 realName
                if (StrUtil.isBlank(d.getRealName())) {
                    log.debug("订单 {} 的 realName 为空，尝试从其他字段获取", d.getOrderId());
                    // 可以根据业务需求添加其他逻辑，比如从 nickname 或其他字段获取
                }
                if (d.getDeliveryStatus() > 10 && d.getDeliveryType().equals(0)) {
                    ShopOrderDelivery shopOrderDelivery = shopOrderDeliveryService.getByOrderId(d.getOrderId());
                    if (shopOrderDelivery != null) {
                        ShopExpress shopExpress = shopExpressService.getById(shopOrderDelivery.getExpressId());
                        if (shopExpress != null) {
                            shopOrderDelivery.setExpressName(shopExpress.getExpressName());
                        }
                    }
                    d.setShopOrderDelivery(shopOrderDelivery);
                }
            });
        }
        return new PageResult<>(list, page.getTotal());
    }

    @Override
    public List<ShopOrder> listRel(ShopOrderParam param) {
        List<ShopOrder> list = baseMapper.selectListRel(param);
        // 排序
        PageParam<ShopOrder, ShopOrderParam> page = new PageParam<>();
        page.setDefaultOrder("sort_number asc, create_time desc");
        return page.sortRecords(list);
    }

    @Override
    public ShopOrder getByIdRel(Integer orderId) {
        ShopOrderParam param = new ShopOrderParam();
        param.setOrderId(orderId);
        return param.getOne(baseMapper.selectListRel(param));
    }

    @Override
    public com.gxwebsoft.shop.dto.UserOrderStats getUserOrderStats(Integer userId, Integer tenantId, Integer type) {
        if (userId == null) {
            // 保持调用方逻辑简单：未登录场景由 controller 处理，这里返回全 0
            return new com.gxwebsoft.shop.dto.UserOrderStats();
        }

        String cacheKey = "ShopOrder:UserOrderStats:"
            + (tenantId == null ? "0" : tenantId)
            + ":" + userId
            + ":" + (type == null ? "all" : type);

        com.gxwebsoft.shop.dto.UserOrderStats cached = redisUtil.get(cacheKey, com.gxwebsoft.shop.dto.UserOrderStats.class);
        if (cached != null) {
            return cached;
        }

        Map<String, Object> raw = baseMapper.selectUserOrderStats(userId, tenantId, type);
        if (raw == null) {
            raw = Collections.emptyMap();
        }
        com.gxwebsoft.shop.dto.UserOrderStats stats = new com.gxwebsoft.shop.dto.UserOrderStats();
        stats.setTotal(getLong(raw, "total"));
        stats.setWaitPay(getLong(raw, "waitPay"));
        stats.setWaitDeliver(getLong(raw, "waitDeliver"));
        stats.setWaitVerify(getLong(raw, "waitVerify"));
        stats.setWaitReceive(getLong(raw, "waitReceive"));
        stats.setWaitComment(getLong(raw, "waitComment"));
        stats.setCompleted(getLong(raw, "completed"));
        stats.setRefund(getLong(raw, "refund"));
        stats.setDeleted(getLong(raw, "deleted"));
        stats.setCanceled(getLong(raw, "canceled"));

        Map<String, Long> statusFilter = new HashMap<>();
        statusFilter.put("0", stats.getWaitPay());
        statusFilter.put("1", stats.getWaitDeliver());
        statusFilter.put("2", stats.getWaitVerify());
        statusFilter.put("3", stats.getWaitReceive());
        statusFilter.put("4", stats.getWaitComment());
        statusFilter.put("5", stats.getCompleted());
        statusFilter.put("6", stats.getRefund());
        statusFilter.put("7", stats.getDeleted());
        statusFilter.put("8", stats.getCanceled());
        stats.setStatusFilter(statusFilter);

        redisUtil.set(cacheKey, stats, USER_ORDER_STATS_CACHE_SECONDS, TimeUnit.SECONDS);
        return stats;
    }

    private static Long getLong(Map<String, Object> raw, String key) {
        Object value = raw.get(key);
        if (value == null) {
            value = raw.get(key.toUpperCase(Locale.ROOT));
        }
        if (value == null) {
            value = raw.get(key.toLowerCase(Locale.ROOT));
        }
        return toLong(value);
    }

    private static Long toLong(Object value) {
        if (value == null) {
            return 0L;
        }
        if (value instanceof Number) {
            return ((Number) value).longValue();
        }
        try {
            return Long.parseLong(String.valueOf(value));
        } catch (Exception e) {
            return 0L;
        }
    }

    @Override
    public HashMap<String, String> createWxOrder(ShopOrder order) {
        Payment payment = null;  // 声明在try块外面，这样catch块也能访问
        try {
            System.out.println("=== 开始创建微信支付订单 ===");
            System.out.println("订单号: " + order.getOrderNo());
            System.out.println("租户ID: " + order.getTenantId());
            System.out.println("支付类型: " + order.getPayType());
            System.out.println("订单金额: " + order.getTotalPrice());
            System.out.println("用户OpenID: " + order.getOpenid());

            // 检查订单基本信息
            if (order.getTenantId() == null) {
                throw new RuntimeException("订单租户ID为null");
            }
            if (order.getOrderNo() == null || order.getOrderNo().trim().isEmpty()) {
                throw new RuntimeException("订单号为空");
            }
            if (order.getTotalPrice() == null) {
                throw new RuntimeException("订单金额为null");
            }
            // 如果商品仅有一个则更新formId
            if (order.getOrderGoods() != null && order.getOrderGoods().size() == 1) {
                order.setFormId(order.getOrderGoods().get(0).getGoodsId());
            }

            // 根据支付类型检查OpenID
            if (order.getPayType().equals(1)) {
                // JSAPI支付需要OpenID
                if (order.getOpenid() == null || order.getOpenid().trim().isEmpty()) {
                    throw new RuntimeException("JSAPI支付必须传openid");
                }
            }

            // 后台微信支付配置信息
            payment = getPayment(order);
            System.out.println("支付配置: " + (payment != null ? "已获取" : "未获取"));

            if (payment == null) {
                throw new RuntimeException("支付配置为null，租户ID: " + order.getTenantId());
            }

            // 检查支付配置的关键字段
            if (payment.getAppId() == null || payment.getAppId().trim().isEmpty()) {
                throw new RuntimeException("支付配置中应用ID为null或空");
            }
            if (payment.getMchId() == null || payment.getMchId().trim().isEmpty()) {
                throw new RuntimeException("支付配置中商户号为null或空");
            }

            // 返回的订单数据
            final HashMap<String, String> orderInfo = new HashMap<>();

            // 根据支付类型选择不同的处理逻辑
            if (order.getPayType().equals(102)) {
                // Native支付处理（兼容旧的102类型）
                System.out.println("⚠️ 检测到使用废弃的微信Native支付类型(102)，建议升级到微信支付(1)");
                order.setWechatPayType(WechatPayType.NATIVE);
                return createNativePayOrder(order, payment);
            } else if (order.getPayType().equals(1)) {
                // 微信支付处理 - 根据是否有openid判断使用JSAPI还是Native
                String wechatType = WechatPayType.getAutoType(order.getOpenid());
                order.setWechatPayType(wechatType);

                if (WechatPayType.JSAPI.equals(wechatType)) {
                    // 有openid，使用JSAPI支付
                    return createJsapiPayOrder(order, payment);
                } else {
                    // 无openid，使用Native支付
                    return createNativePayOrder(order, payment);
                }
            } else {
                // 其他支付方式暂时使用JSAPI处理
                return createJsapiPayOrder(order, payment);
            }

        } catch (Exception e) {
            System.err.println("=== 创建微信支付订单失败 ===");
            System.err.println("错误信息: " + e.getMessage());
            System.err.println("错误类型: " + e.getClass().getName());

            // 特殊处理签名验证失败的情况
            if (e.getMessage() != null && e.getMessage().contains("signature is incorrect")) {
                System.err.println("🔍 签名验证失败诊断:");
                System.err.println("1. 检查商户证书序列号是否正确");
                System.err.println("2. 检查APIv3密钥是否正确");
                System.err.println("3. 检查私钥文件是否正确");
                System.err.println("4. 检查微信支付平台证书是否过期");
                System.err.println("5. 建议使用自动证书配置避免证书管理问题");
                System.err.println("当前支付配置:");
                System.err.println("租户ID: " + order.getTenantId());
                System.err.println("商户号: " + (payment != null ? payment.getMchId() : "null"));
                System.err.println("应用ID: " + (payment != null ? payment.getAppId() : "null"));
            }

            throw new RuntimeException("创建微信支付订单失败：" + e.getMessage(), e);
        }
    }

    /**
     * 创建Native支付订单
     */
    private HashMap<String, String> createNativePayOrder(ShopOrder order, Payment payment) throws Exception {
        System.out.println("=== 使用Native支付模式 ===");

        // 构建Native支付服务
        Config wxPayConfig = getWxPayConfig(order);
        NativePayService nativeService = new NativePayService.Builder().config(wxPayConfig).build();

        // 订单金额（转换为分）- 优先使用 payPrice，避免与 JSAPI 金额字段不一致导致重入校验失败
        BigDecimal payAmount = order.getPayPrice() != null ? order.getPayPrice() : order.getTotalPrice();
        Integer money = toFen(payAmount);
        if (money == null) {
            throw new RuntimeException("订单金额为null");
        }

        // 测试环境使用1分钱
        if ("dev".equals(active)) {
            money = 1;
        }

        // 构建Native支付请求
        com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest request =
            new com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest();
        com.wechat.pay.java.service.payments.nativepay.model.Amount amount =
            new com.wechat.pay.java.service.payments.nativepay.model.Amount();
        amount.setTotal(money);
        amount.setCurrency("CNY");
        request.setAmount(amount);

        request.setAppid(payment.getAppId());
        request.setMchid(payment.getMchId());

        // 微信支付description字段限制127字节，需要截断处理
        String description = com.gxwebsoft.common.core.utils.WechatPayUtils.processDescription(order.getComments());
        request.setDescription(description);
        request.setOutTradeNo(order.getOrderNo());
        request.setAttach(order.getTenantId().toString());

        System.out.println("=== 关键信息确认 ===");
        System.out.println("发送给微信的订单号(OutTradeNo): " + order.getOrderNo());
        System.out.println("商户号(MchId): " + payment.getMchId());
        System.out.println("应用ID(AppId): " + payment.getAppId());

        String outTradeNo = order.getOrderNo();
        WechatPrepaySnapshot snapshot = getPrepaySnapshot(payment, outTradeNo);
        if (snapshot == null) {
            snapshot = new WechatPrepaySnapshot();
            snapshot.setOutTradeNo(outTradeNo);
            snapshot.setWechatPayType(WechatPayType.NATIVE);
            snapshot.setAppid(payment.getAppId());
            snapshot.setMchid(payment.getMchId());
            snapshot.setAttach(order.getTenantId().toString());
            snapshot.setTotal(money);
            snapshot.setDescription(description);
            // notifyUrl 在下面根据重试结果回填
        } else {
            // 使用快照中的关键字段，确保重入时参数一致
            if (snapshot.getTotal() != null) {
                amount.setTotal(snapshot.getTotal());
            }
            if (StrUtil.isNotBlank(snapshot.getDescription())) {
                request.setDescription(snapshot.getDescription());
            }
            if (StrUtil.isNotBlank(snapshot.getAttach())) {
                request.setAttach(snapshot.getAttach());
            }
            if (StrUtil.isNotBlank(snapshot.getAppid())) {
                request.setAppid(snapshot.getAppid());
            }
            if (StrUtil.isNotBlank(snapshot.getMchid())) {
                request.setMchid(snapshot.getMchid());
            }
        }

        // 开发环境固定使用1分钱（与历史行为保持一致）
        if ("dev".equals(active)) {
            amount.setTotal(1);
            request.setAmount(amount);
            snapshot.setTotal(1);
        }

        // 回调地址：优先用快照；若重入提示参数不一致，则尝试历史回调地址
        Exception last = null;
        String notifyUrlUsed = null;
        for (String notifyUrl : buildNotifyUrlCandidates(order, payment, snapshot)) {
            if (StrUtil.isBlank(notifyUrl)) {
                continue;
            }
            request.setNotifyUrl(notifyUrl);
            try {
                System.out.println("=== 发起Native支付请求 ===");
                System.out.println("请求参数: " + request);

                com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse response = nativeService.prepay(request);
                notifyUrlUsed = notifyUrl;

                System.out.println("=== Native支付响应成功 ===");
                System.out.println("二维码URL: " + response.getCodeUrl());

                snapshot.setNotifyUrl(notifyUrlUsed);
                snapshot.setTotal(amount.getTotal());
                snapshot.setDescription(request.getDescription());
                savePrepaySnapshot(payment, snapshot);

                final HashMap<String, String> orderInfo = new HashMap<>();
                orderInfo.put("provider", "wxpay");
                orderInfo.put("codeUrl", response.getCodeUrl());  // Native支付返回二维码URL
                orderInfo.put("orderNo", order.getOrderNo());
                orderInfo.put("payType", WechatPayType.NATIVE);
                orderInfo.put("wechatPayType", WechatPayType.NATIVE);

                return orderInfo;
            } catch (Exception e) {
                last = e;
                if (!isIdempotencyParamMismatch(e)) {
                    throw e;
                }
                log.warn("Native预下单重入参数不一致，尝试切换notifyUrl重试 - outTradeNo={}, notifyUrl={}", outTradeNo, notifyUrl, e);
            }
        }
        if (last != null) {
            throw last;
        }
        throw new RuntimeException("创建Native支付订单失败：notifyUrl为空");
    }

    /**
     * 创建JSAPI支付订单（原有逻辑）
     */
    private HashMap<String, String> createJsapiPayOrder(ShopOrder order, Payment payment) throws Exception {
        System.out.println("=== 使用JSAPI支付模式 ===");

        // JSAPI支付必须有OpenID
        if (order.getOpenid() == null || order.getOpenid().trim().isEmpty()) {
            throw new RuntimeException("JSAPI支付必须传openid");
        }

        // 构建JSAPI支付服务
        JsapiServiceExtension service = getWxService(order);
        System.out.println("微信支付服务构建完成");

        // 订单金额（分）
        BigDecimal payAmount = order.getPayPrice() != null ? order.getPayPrice() : order.getTotalPrice();
        Integer money = toFen(payAmount);
        if (money == null) {
            throw new RuntimeException("订单金额为null");
        }

        System.out.println("=== 构建支付请求参数 ===");

        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(money);
        amount.setCurrency("CNY");
        request.setAmount(amount);

        System.out.println("设置应用ID: " + payment.getAppId());
        request.setAppid(payment.getAppId());

        System.out.println("设置商户号: " + payment.getMchId());
        request.setMchid(payment.getMchId());

        // 微信支付description字段限制127字节，需要截断处理
        String rawDescription = StrUtil.isNotBlank(order.getComments()) ? order.getComments() : "订单支付";
        String description = com.gxwebsoft.common.core.utils.WechatPayUtils.processDescription(rawDescription);
        System.out.println("设置描述: " + description);
        request.setDescription(description);

        System.out.println("设置订单号: " + order.getOrderNo());
        request.setOutTradeNo(order.getOrderNo());

        System.out.println("设置附加数据: " + order.getTenantId().toString());
        request.setAttach(order.getTenantId().toString());

        final Payer payer = new Payer();
        System.out.println("设置用户OpenID: " + order.getOpenid());
        payer.setOpenid(order.getOpenid());
        request.setPayer(payer);
        String outTradeNo = order.getOrderNo();
        WechatPrepaySnapshot snapshot = getPrepaySnapshot(payment, outTradeNo);
        if (snapshot == null) {
            snapshot = new WechatPrepaySnapshot();
            snapshot.setOutTradeNo(outTradeNo);
            snapshot.setWechatPayType(WechatPayType.JSAPI);
            snapshot.setAppid(payment.getAppId());
            snapshot.setMchid(payment.getMchId());
            snapshot.setOpenid(order.getOpenid());
            snapshot.setAttach(order.getTenantId().toString());
            snapshot.setTotal(amount.getTotal());
            snapshot.setDescription(request.getDescription());
            // notifyUrl 在下面根据重试结果回填
        } else {
            // 使用快照中的关键字段，确保重入时参数一致
            if (snapshot.getTotal() != null) {
                amount.setTotal(snapshot.getTotal());
                request.setAmount(amount);
            }
            if (StrUtil.isNotBlank(snapshot.getDescription())) {
                request.setDescription(snapshot.getDescription());
            }
            if (StrUtil.isNotBlank(snapshot.getAttach())) {
                request.setAttach(snapshot.getAttach());
            }
            if (StrUtil.isNotBlank(snapshot.getOpenid())) {
                payer.setOpenid(snapshot.getOpenid());
                request.setPayer(payer);
            }
            if (StrUtil.isNotBlank(snapshot.getAppid())) {
                request.setAppid(snapshot.getAppid());
            }
            if (StrUtil.isNotBlank(snapshot.getMchid())) {
                request.setMchid(snapshot.getMchid());
            }
        }

        // 测试环境使用1分钱（快照优先）
        if ("dev".equals(active)) {
            amount.setTotal(1);
            request.setAmount(amount);
            snapshot.setTotal(1);
        }

        Exception last = null;
        String notifyUrlUsed = null;
        for (String notifyUrl : buildNotifyUrlCandidates(order, payment, snapshot)) {
            if (StrUtil.isBlank(notifyUrl)) {
                continue;
            }
            request.setNotifyUrl(notifyUrl);
            try {
                System.out.println("=== 发起微信支付请求 ===");
                System.out.println("请求参数: " + request);

                PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
                notifyUrlUsed = notifyUrl;

                System.out.println("=== 微信支付响应成功 ===");
                System.out.println("预支付ID: " + response.getPackageVal());

                snapshot.setNotifyUrl(notifyUrlUsed);
                snapshot.setTotal(request.getAmount().getTotal());
                snapshot.setDescription(request.getDescription());
                snapshot.setOpenid(request.getPayer() != null ? request.getPayer().getOpenid() : null);
                snapshot.setAppid(request.getAppid());
                snapshot.setMchid(request.getMchid());
                snapshot.setAttach(request.getAttach());
                savePrepaySnapshot(payment, snapshot);

                final HashMap<String, String> orderInfo = new HashMap<>();
                orderInfo.put("provider", "wxpay");
                orderInfo.put("timeStamp", response.getTimeStamp());
                orderInfo.put("nonceStr", response.getNonceStr());
                orderInfo.put("package", response.getPackageVal());
                orderInfo.put("signType", "RSA");
                orderInfo.put("paySign", response.getPaySign());
                orderInfo.put("orderNo", order.getOrderNo());
                orderInfo.put("payType", WechatPayType.JSAPI);
                orderInfo.put("wechatPayType", WechatPayType.JSAPI);
                return orderInfo;
            } catch (Exception e) {
                last = e;
                if (!isIdempotencyParamMismatch(e)) {
                    throw e;
                }
                log.warn("JSAPI预下单重入参数不一致，尝试切换notifyUrl重试 - outTradeNo={}, notifyUrl={}", outTradeNo, notifyUrl, e);
            }
        }
        if (last != null) {
            throw last;
        }
        throw new RuntimeException("创建JSAPI支付订单失败：notifyUrl为空");
    }

    @Override
    public ShopOrder getByOutTradeNo(String outTradeNo) {
        return baseMapper.getByOutTradeNo(outTradeNo);
    }

    /**
     * 修复订单支付状态
     *
     * @param shopOrder
     */
    @Override
    public Boolean queryOrderByOutTradeNo(ShopOrder shopOrder) {
        // 后台微信支付配置信息
        final Payment payment = getPayment(shopOrder);
        QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
        queryRequest.setMchid(payment.getMchId());
        queryRequest.setOutTradeNo(shopOrder.getOrderNo());
	        // 构建service
	        JsapiServiceExtension service = getWxService(shopOrder);
	        try {
	            Transaction result = service.queryOrderByOutTradeNo(queryRequest);
	            if (Transaction.TradeStateEnum.SUCCESS.equals(result.getTradeState())) {
	                if (Boolean.TRUE.equals(shopOrder.getPayStatus())) {
	                    // 已是支付成功状态，避免重复触发支付成功后的业务逻辑（销量/库存等）
	                    return true;
	                }
	                shopOrder.setPayStatus(true);
	                LocalDateTime payTime = null;
	                String successTime = result.getSuccessTime();
	                if (successTime != null && !successTime.isBlank()) {
	                    try {
	                        // WeChat returns RFC3339 time with offset, e.g. 2018-06-08T10:34:56+08:00
	                        payTime = OffsetDateTime.parse(successTime).toLocalDateTime();
	                    } catch (Exception ex) {
	                        log.warn("解析微信支付successTime失败，使用当前时间兜底 - outTradeNo={}, successTime={}",
	                            shopOrder.getOrderNo(), successTime, ex);
	                    }
	                }
	                if (payTime == null) {
	                    if (successTime == null || successTime.isBlank()) {
	                        log.warn("微信支付查询返回SUCCESS但successTime为空，使用当前时间兜底 - outTradeNo={}", shopOrder.getOrderNo());
	                    }
	                    payTime = LocalDateTime.now();
	                }
	                shopOrder.setPayTime(payTime);
	                if (shopOrder.getOrderStatus().equals(2)) {
	                    shopOrder.setOrderStatus(0);
	                }
	                shopOrder.setTransactionId(result.getTransactionId());
	                updateById(shopOrder);
	                handlePaymentSuccess(shopOrder);
	                return true;
	            }
	        } catch (ServiceException e) {
            // API返回失败, 例如ORDER_NOT_EXISTS
            System.out.printf("code=[%s], message=[%s]\n", e.getErrorCode(), e.getErrorMessage());
            System.out.printf("reponse body=[%s]\n", e.getResponseBody());
        }
        return false;
    }

    @Override
    public void updateByOutTradeNo(ShopOrder order) {
        order.setExpirationTime(null);
        baseMapper.updateByOutTradeNo(order);

        // 处理支付成功后的业务逻辑
        handlePaymentSuccess(order);

        if (order.getTenantId().equals(10550)) {
            shopOrderUpdate10550Service.update(order);
        }
    }

    /**
     * 处理支付成功后的业务逻辑
     */
    private void handlePaymentSuccess(ShopOrder order) {
        try {
            // 0. 付款减库存：支付成功后扣库存（下单时不扣）
            deductStockAfterPaidIfNeeded(order);

            // 1. 使用优惠券
            if (order.getCouponId() != null && order.getCouponId() > 0) {
                markCouponAsUsed(order);
            }

            // 2. 累计商品销量
            updateGoodsSales(order);

            log.info("支付成功后业务逻辑处理完成 - 订单号：{}", order.getOrderNo());
        } catch (Exception e) {
            log.error("处理支付成功后业务逻辑失败 - 订单号：{}", order.getOrderNo(), e);
            // 不抛出异常，避免影响支付回调的成功响应
        }
    }

    /**
     * 付款减库存：支付成功后按商品设置扣减库存。
     *
     * 注意：此处使用忽略租户隔离 + 显式 tenantId 条件，避免支付回调没有 tenantId header 时更新失败。
     * 若扣减失败（库存不足/数据缺失），仅记录日志，不阻断支付回调主流程。
     */
    private void deductStockAfterPaidIfNeeded(ShopOrder order) {
        if (order == null || order.getOrderId() == null || order.getTenantId() == null) {
            return;
        }

        final List<ShopOrderGoods> orderGoodsList = shopOrderGoodsService.getListByOrderIdIgnoreTenant(order.getOrderId());
        if (CollectionUtils.isEmpty(orderGoodsList)) {
            return;
        }

        TenantContext.runIgnoreTenant(() -> {
            for (ShopOrderGoods og : orderGoodsList) {
                if (og == null || og.getGoodsId() == null) {
                    continue;
                }
                int qty = og.getTotalNum() == null ? 0 : og.getTotalNum();
                if (qty <= 0) {
                    continue;
                }

                ShopGoods goods = shopGoodsService.getById(og.getGoodsId());
                Integer deductStockType = goods != null ? goods.getDeductStockType() : null;
                if (deductStockType == null || deductStockType != DEDUCT_STOCK_TYPE_PAY) {
                    continue;
                }

                try {
                    if (og.getSkuId() != null && og.getSkuId() > 0) {
                        // 多规格：扣 SKU 库存
                        boolean updated = shopGoodsSkuService.update(
                            new LambdaUpdateWrapper<ShopGoodsSku>()
                                .eq(ShopGoodsSku::getId, og.getSkuId())
                                .eq(ShopGoodsSku::getTenantId, order.getTenantId())
                                .apply("IFNULL(stock,0) >= {0}", qty)
                                .setSql("stock = IFNULL(stock,0) - " + qty)
                        );
                        if (!updated) {
                            log.warn("支付成功后扣SKU库存失败 - tenantId={}, orderId={}, skuId={}, goodsId={}, qty={}",
                                order.getTenantId(), order.getOrderId(), og.getSkuId(), og.getGoodsId(), qty);
                            // 兜底：库存不足时至少将库存置0，避免出现“明明已售出但库存仍大于0”的情况
                            shopGoodsSkuService.update(
                                new LambdaUpdateWrapper<ShopGoodsSku>()
                                    .eq(ShopGoodsSku::getId, og.getSkuId())
                                    .eq(ShopGoodsSku::getTenantId, order.getTenantId())
                                    .apply("IFNULL(stock,0) < {0}", qty)
                                    .setSql("stock = 0")
                            );
                        }
                    } else {
                        // 单规格：扣商品库存
                        boolean updated = shopGoodsService.update(
                            new LambdaUpdateWrapper<ShopGoods>()
                                .eq(ShopGoods::getGoodsId, og.getGoodsId())
                                .eq(ShopGoods::getTenantId, order.getTenantId())
                                .apply("IFNULL(stock,0) >= {0}", qty)
                                .setSql("stock = IFNULL(stock,0) - " + qty)
                        );
                        if (!updated) {
                            log.warn("支付成功后扣商品库存失败 - tenantId={}, orderId={}, goodsId={}, qty={}",
                                order.getTenantId(), order.getOrderId(), og.getGoodsId(), qty);
                            // 兜底：库存不足时至少将库存置0，避免出现“明明已售出但库存仍大于0”的情况
                            shopGoodsService.update(
                                new LambdaUpdateWrapper<ShopGoods>()
                                    .eq(ShopGoods::getGoodsId, og.getGoodsId())
                                    .eq(ShopGoods::getTenantId, order.getTenantId())
                                    .apply("IFNULL(stock,0) < {0}", qty)
                                    .setSql("stock = 0")
                            );
                        }
                    }
                } catch (Exception e) {
                    log.warn("支付成功后扣库存异常 - tenantId={}, orderId={}, goodsId={}, skuId={}, qty={}",
                        order.getTenantId(), order.getOrderId(), og.getGoodsId(), og.getSkuId(), qty, e);
                }
            }
        });
    }

    /**
     * 标记优惠券为已使用
     */
    private void markCouponAsUsed(ShopOrder order) {
        try {
            // 注入 CouponStatusService 并使用其 useCoupon 方法
            // couponStatusService.useCoupon(order.getCouponId().longValue(), order.getOrderId(), order.getOrderNo());

            // 临时保持原有逻辑，建议后续重构
            ShopUserCoupon coupon = shopUserCouponService.getById(order.getCouponId());
            if (coupon != null) {
                coupon.markAsUsed(order.getOrderId(), order.getOrderNo());
                shopUserCouponService.updateById(coupon);
                log.info("优惠券标记为已使用 - 优惠券ID：{}，订单号：{}", order.getCouponId(), order.getOrderNo());
            }
        } catch (Exception e) {
            log.error("标记优惠券为已使用失败 - 优惠券ID：{}，订单号：{}", order.getCouponId(), order.getOrderNo(), e);
        }
    }

    /**
     * 累计商品销量
     */
    private void updateGoodsSales(ShopOrder order) {
        try {
            // 获取订单商品列表（忽略租户隔离）
            final List<ShopOrderGoods> orderGoodsList = shopOrderGoodsService.getListByOrderIdIgnoreTenant(order.getOrderId());

            if (orderGoodsList.isEmpty()) {
                log.warn("订单商品列表为空 - 订单号：{}", order.getOrderNo());
                return;
            }

            // 累计每个商品的销量
            for (ShopOrderGoods orderGoods : orderGoodsList) {
                updateSingleGoodsSales(orderGoods);
            }

            log.info("商品销量累计完成 - 订单号：{}，商品数量：{}", order.getOrderNo(), orderGoodsList.size());
        } catch (Exception e) {
            log.error("累计商品销量失败 - 订单号：{}", order.getOrderNo(), e);
        }
    }

    /**
     * 累计单个商品的销量
     * 使用新的addSaleCount方法，忽略租户隔离确保更新成功
     */
    private void updateSingleGoodsSales(ShopOrderGoods orderGoods) {
        try {
            if (orderGoods.getGoodsId() == null || orderGoods.getTotalNum() == null || orderGoods.getTotalNum() <= 0) {
                log.warn("商品销量累计参数无效 - 商品ID：{}，购买数量：{}",
                    orderGoods.getGoodsId(), orderGoods.getTotalNum());
                return;
            }

            // 使用新的addSaleCount方法，忽略租户隔离
            boolean updated = shopGoodsService.addSaleCount(orderGoods.getGoodsId(), orderGoods.getTotalNum());

            if (updated) {
                log.info("商品销量累计成功 - 商品ID：{}，商品名称：{}，购买数量：{}",
                    orderGoods.getGoodsId(), orderGoods.getGoodsName(), orderGoods.getTotalNum());
            } else {
                log.warn("商品销量累计失败 - 商品ID：{}，商品名称：{}，购买数量：{}",
                    orderGoods.getGoodsId(), orderGoods.getGoodsName(), orderGoods.getTotalNum());
            }
        } catch (Exception e) {
            log.error("累计单个商品销量异常 - 商品ID：{}，商品名称：{}，购买数量：{}",
                orderGoods.getGoodsId(), orderGoods.getGoodsName(), orderGoods.getTotalNum(), e);
        }
    }

    /**
     * 读取微信支付配置
     * 生产环境优先从缓存读取 Payment:1* 格式的商户信息
     * 开发环境自动使用本地回调地址
     *
     * @param order
     * @return
     */
    public Payment getPayment(ShopOrder order) {
        // 先清除可能的错误缓存
//      paymentCacheService.removePaymentConfig(order.getPayType().toString(), order.getTenantId());

        // 使用环境感知的支付配置服务
        Payment payment;
        try {
            // 尝试使用环境感知服务
            EnvironmentAwarePaymentService envPaymentService =
                SpringContextUtil.getBean(EnvironmentAwarePaymentService.class);
            payment = envPaymentService.getEnvironmentAwarePaymentConfig(order.getPayType(), order.getTenantId());
        } catch (Exception e) {
            // 如果环境感知服务不可用，回退到原有方式
            log.warn("环境感知支付服务不可用，使用原有配置方式: {}", e.getMessage());
            payment = paymentCacheService.getPaymentConfig(order.getPayType(), order.getTenantId());
        }

        // 添加详细的支付配置检查
        System.out.println("=== 支付配置检查 ===");
        System.out.println("订单支付类型: " + order.getPayType());
        System.out.println("租户ID: " + order.getTenantId());

        if (payment == null) {
            throw new RuntimeException("未找到支付配置，支付类型: " + order.getPayType() + ", 租户ID: " + order.getTenantId());
        }

        System.out.println("支付配置ID: " + payment.getId());
        System.out.println("支付方式名称: " + payment.getName());
        System.out.println("支付类型: " + payment.getType());
        System.out.println("支付代码: " + payment.getCode());
        System.out.println("应用ID: " + payment.getAppId());
        System.out.println("商户号: " + payment.getMchId());
        System.out.println("API密钥: " + (payment.getApiKey() != null ? "已配置(长度:" + payment.getApiKey().length() + ")" : "未配置"));
        System.out.println("商户证书序列号: " + payment.getMerchantSerialNumber());
        System.out.println("状态: " + payment.getStatus());

        return payment;
    }

    /**
     * 构建微信支付
     *
     * @param order
     * @return
     */
    public JsapiServiceExtension getWxService(ShopOrder order) {
        try {
            final Payment payment = getPayment(order);

            // 提前声明所有需要的变量，避免重复定义
            String privateKey;
            String apiclientCert = null;
            String pubKey = null;
            String tenantCertPath = null;
            String privateKeyPath = null;
            String pubKeyPath = null;
            String apiclientCertPath = null;
            String apiclientCertFile = null;
            String pubKeyFile = null;

            // 运行配置诊断
            System.out.println("=== 运行微信支付配置诊断 ===");
            wechatPayDiagnostic.diagnosePaymentConfig(payment, null, active);

            // 运行证书诊断
            System.out.println("=== 运行证书诊断 ===");
            WechatPayCertificateDiagnostic.DiagnosticResult diagnosticResult =
                    certificateDiagnostic.diagnoseCertificateConfig(payment, order.getTenantId(), active);
            System.out.println(diagnosticResult.getFullReport());



            // 构建微信支付配置
            Config config = null;
            if (active.equals("dev")) {
                // 开发环境使用自动证书配置
                // 首先初始化私钥路径
                tenantCertPath = "dev/wechat/" + order.getTenantId();
                privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
                privateKey = certificateLoader.loadCertificatePath(privateKeyPath);
                System.out.println("开发环境私钥路径: " + privateKeyPath);
                System.out.println("开发环境私钥加载成功: " + privateKey);

                // 检查数据库配置是否完整
                if (payment.getMchId() == null || payment.getMchId().trim().isEmpty()) {
                    throw new RuntimeException("数据库中商户号(mchId)未配置");
                }
                if (payment.getMerchantSerialNumber() == null || payment.getMerchantSerialNumber().trim().isEmpty()) {
                    throw new RuntimeException("数据库中商户证书序列号(merchantSerialNumber)未配置");
                }
                if (payment.getApiKey() == null || payment.getApiKey().trim().isEmpty()) {
                    throw new RuntimeException("数据库中API密钥(apiKey)未配置");
                }

                System.out.println("=== 使用数据库支付配置 ===");
                System.out.println("商户号: " + payment.getMchId());
                System.out.println("序列号: " + payment.getMerchantSerialNumber());
                System.out.println("API密钥: 已配置(长度:" + payment.getApiKey().length() + ")");

                // 临时使用RSA配置替代自动证书配置，避免404错误
                System.out.println("=== 注意：使用RSA配置替代自动证书配置 ===");
                System.out.println("原因：商户平台可能未开启API安全功能或未申请微信支付公钥");

                // 首先检查是否配置了公钥，如果有则优先使用公钥模式
                if (payment.getPubKey() != null && !payment.getPubKey().isEmpty() &&
                        payment.getPubKeyId() != null && !payment.getPubKeyId().isEmpty()) {

                    try {
                        // 开发环境固定使用 wechatpay_public_key.pem
                        pubKeyPath = tenantCertPath + "/wechatpay_public_key.pem";

                        System.out.println("开发环境公钥文件路径: " + pubKeyPath);

                        // 检查公钥文件是否存在
                        if (certificateLoader.certificateExists(pubKeyPath)) {
                            System.out.println("=== 检测到公钥配置，使用RSA公钥模式 ===");
                            System.out.println("公钥文件: " + payment.getPubKey());
                            System.out.println("公钥ID: " + payment.getPubKeyId());

                            pubKeyFile = certificateLoader.loadCertificatePath(pubKeyPath);
                            System.out.println("✅ 开发环境公钥文件加载成功: " + pubKeyFile);

                            config = new RSAPublicKeyConfig.Builder()
                                    .merchantId(payment.getMchId())
                                    .privateKeyFromPath(privateKey)
                                    .publicKeyFromPath(pubKeyFile)
                                    .publicKeyId(payment.getPubKeyId())
                                    .merchantSerialNumber(payment.getMerchantSerialNumber())
                                    .apiV3Key(payment.getApiKey())
                                    .build();
                            System.out.println("✅ 开发环境RSA公钥配置成功");
                        } else {
                            System.out.println("⚠️ 开发环境公钥文件不存在，跳过公钥模式: " + pubKeyPath);
                            // 跳过公钥配置，继续后续的自动证书配置
                        }
                    } catch (Exception e) {
                        System.err.println("❌ 开发环境公钥配置检查失败: " + e.getMessage());
                        // 跳过公钥配置，继续后续的自动证书配置
                    }
                }

                // 如果没有公钥配置或公钥文件不存在，尝试自动证书配置
                if (config == null) {
                    // 没有公钥配置，尝试自动证书配置
                    try {
                        System.out.println("=== 尝试创建自动证书配置 ===");
                        System.out.println("商户号: " + payment.getMchId());
                        System.out.println("私钥路径: " + privateKey);
                        System.out.println("序列号: " + payment.getMerchantSerialNumber());
                        System.out.println("API密钥长度: " + (payment.getApiKey() != null ? payment.getApiKey().length() : 0));

                        config = wechatCertAutoConfig.createAutoConfig(
                                payment.getMchId(),
                                privateKey,
                                payment.getMerchantSerialNumber(),
                                payment.getApiKey()
                        );
                        System.out.println("✅ 开发环境自动证书配置成功");
                    } catch (Exception e) {
                        System.err.println("❌ 自动证书配置失败: " + e.getMessage());
                        System.err.println("错误类型: " + e.getClass().getName());
                        e.printStackTrace();

                        // 检查是否是证书相关的错误
                        if (e.getMessage() != null && (
                                e.getMessage().contains("certificate") ||
                                        e.getMessage().contains("X509Certificate") ||
                                        e.getMessage().contains("getSerialNumber") ||
                                        e.getMessage().contains("404") ||
                                        e.getMessage().contains("API安全"))) {

                            System.err.println("🔍 证书问题诊断:");
                            System.err.println("1. 检查商户平台是否已开启API安全功能");
                            System.err.println("2. 检查是否已申请使用微信支付公钥");
                            System.err.println("3. 检查网络连接是否正常");
                            System.err.println("4. 检查商户证书序列号是否正确");
                            System.err.println("5. 参考文档：https://pay.weixin.qq.com/doc/v3/merchant/4012153196");

                            // 开发环境回退到基础RSA配置
                            System.err.println("⚠️ 开发环境回退到基础RSA配置...");
                            try {
                                // 方案1：尝试使用RSA证书配置（需要商户证书文件）
                                apiclientCertPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getApiclientCertFile();

                                if (certificateLoader.certificateExists(apiclientCertPath)) {
                                    apiclientCertFile = certificateLoader.loadCertificatePath(apiclientCertPath);
                                    System.out.println("方案1: 使用RSA证书配置作为回退方案");
                                    System.out.println("商户证书路径: " + apiclientCertFile);

                                    try {
                                        config = new RSAConfig.Builder()
                                                .merchantId(payment.getMchId())
                                                .privateKeyFromPath(privateKey)
                                                .merchantSerialNumber(payment.getMerchantSerialNumber())
                                                .wechatPayCertificatesFromPath(apiclientCertFile)
                                                .build();
                                        System.out.println("✅ 开发环境RSA证书配置成功");
                                    } catch (Exception rsaException) {
                                        System.err.println("RSA证书配置失败: " + rsaException.getMessage());
                                        throw rsaException;
                                    }
                                } else {
                                    System.err.println("❌ 商户证书文件不存在: " + apiclientCertPath);
                                    System.err.println("⚠️ 尝试方案2: 使用最小化配置...");

                                    // 方案2：使用最小化的RSA配置（仅私钥和序列号）
                                    try {
                                        // 创建一个最基础的配置，不依赖平台证书
                                        config = new com.wechat.pay.java.core.RSAConfig.Builder()
                                                .merchantId(payment.getMchId())
                                                .privateKeyFromPath(privateKey)
                                                .merchantSerialNumber(payment.getMerchantSerialNumber())
                                                .build();
                                        System.out.println("✅ 开发环境最小化RSA配置成功");
                                    } catch (Exception minimalException) {
                                        System.err.println("最小化配置也失败: " + minimalException.getMessage());
                                        throw new RuntimeException("所有配置方案都失败，请检查私钥文件和商户配置", e);
                                    }
                                }
                            } catch (Exception fallbackException) {
                                System.err.println("❌ 手动证书配置失败: " + fallbackException.getMessage());
                                fallbackException.printStackTrace();

                                // 最后的回退：抛出详细错误信息
                                System.err.println("=== 最终错误诊断 ===");
                                System.err.println("1. 自动证书配置失败原因: " + e.getMessage());
                                System.err.println("2. 手动证书配置失败原因: " + fallbackException.getMessage());
                                System.err.println("3. 建议解决方案:");
                                System.err.println("   - 检查微信商户平台是否开启API安全功能");
                                System.err.println("   - 确认已申请使用微信支付公钥");
                                System.err.println("   - 验证商户证书序列号是否正确");
                                System.err.println("   - 检查私钥文件是否完整且格式正确");

                                throw new RuntimeException("微信支付配置失败，请检查商户平台API安全设置和证书配置。原始错误: " + e.getMessage() + ", 回退错误: " + fallbackException.getMessage(), e);
                            }
                        } else {
                            throw new RuntimeException("微信支付配置失败：" + e.getMessage(), e);
                        }
                    }
                }
            } else {
                // 生产环境 - 首先初始化私钥
                final String certRootPath = certConfig.getCertRootPath();
                System.out.println("生产环境证书根路径: " + certRootPath);

                String privateKeyRelativePath = payment.getApiclientKey();
                System.out.println("数据库中的私钥相对路径: " + privateKeyRelativePath);

                // 生产环境已经没有/file目录，所有路径都直接拼接到根路径
                String privateKeyFullPath;
                // 处理数据库中可能存在的历史路径格式
                String cleanPath = privateKeyRelativePath;
                if (privateKeyRelativePath.startsWith("/file/")) {
                    // 去掉历史的 /file/ 前缀
                    cleanPath = privateKeyRelativePath.substring(6);
                } else if (privateKeyRelativePath.startsWith("file/")) {
                    // 去掉历史的 file/ 前缀
                    cleanPath = privateKeyRelativePath.substring(5);
                }
                // 确保路径以 / 开头
                if (!cleanPath.startsWith("/")) {
                    cleanPath = "/" + cleanPath;
                }
                privateKeyFullPath = certRootPath + cleanPath;

                System.out.println("生产环境私钥完整路径: " + privateKeyFullPath);
                privateKey = certificateLoader.loadCertificatePath(privateKeyFullPath);
                System.out.println("✅ 生产环境私钥加载完成: " + privateKey);

                // 生产环境也优先检查公钥配置
                if (payment.getPubKey() != null && !payment.getPubKey().isEmpty() &&
                        payment.getPubKeyId() != null && !payment.getPubKeyId().isEmpty()) {

                    System.out.println("=== 生产环境检测到公钥配置，使用RSA公钥模式 ===");
                    System.out.println("公钥文件路径: " + payment.getPubKey());
                    System.out.println("公钥ID: " + payment.getPubKeyId());

                    try {
                        // 生产环境处理公钥路径
                        String pubKeyRelativePath = payment.getPubKey();
                        System.out.println("数据库中的公钥相对路径: " + pubKeyRelativePath);

                        // 生产环境已经没有/file目录，所有路径都直接拼接到根路径
                        String pubKeyFullPath;
                        // 处理数据库中可能存在的历史路径格式
                        String cleanPubPath = pubKeyRelativePath;
                        if (pubKeyRelativePath.startsWith("/file/")) {
                            // 去掉历史的 /file/ 前缀
                            cleanPubPath = pubKeyRelativePath.substring(6);
                        } else if (pubKeyRelativePath.startsWith("file/")) {
                            // 去掉历史的 file/ 前缀
                            cleanPubPath = pubKeyRelativePath.substring(5);
                        }
                        // 确保路径以 / 开头
                        if (!cleanPubPath.startsWith("/")) {
                            cleanPubPath = "/" + cleanPubPath;
                        }
                        pubKeyFullPath = certRootPath + cleanPubPath;

                        System.out.println("生产环境公钥完整路径: " + pubKeyFullPath);
                        pubKeyFile = certificateLoader.loadCertificatePath(pubKeyFullPath);
                        System.out.println("✅ 生产环境公钥文件加载成功: " + pubKeyFile);

                        config = new RSAPublicKeyConfig.Builder()
                                .merchantId(payment.getMchId())
                                .privateKeyFromPath(privateKey)
                                .publicKeyFromPath(pubKeyFile)
                                .publicKeyId(payment.getPubKeyId())
                                .merchantSerialNumber(payment.getMerchantSerialNumber())
                                .apiV3Key(payment.getApiKey())
                                .build();
                        System.out.println("✅ 生产环境RSA公钥配置成功");
                    } catch (Exception pubKeyException) {
                        System.err.println("❌ 生产环境RSA公钥配置失败: " + pubKeyException.getMessage());
                        pubKeyException.printStackTrace();
                        throw new RuntimeException("生产环境RSA公钥配置失败: " + pubKeyException.getMessage(), pubKeyException);
                    }
                } else {
                    // 没有公钥配置，使用自动证书配置
                    System.out.println("=== 生产环境使用自动证书配置 ===");
                    System.out.println("商户号: " + payment.getMchId());
                    System.out.println("序列号: " + payment.getMerchantSerialNumber());
                    System.out.println("API密钥: 已配置(长度:" + payment.getApiKey().length() + ")");

                    try {
                        // 优先使用自动证书配置，避免证书过期和序列号不匹配问题
                        config = wechatCertAutoConfig.createAutoConfig(
                                payment.getMchId(),
                                privateKey,
                                payment.getMerchantSerialNumber(),
                                payment.getApiKey()
                        );
                        System.out.println("✅ 生产环境自动证书配置成功");
                    } catch (Exception autoConfigException) {
                        System.err.println("⚠️ 自动证书配置失败，回退到手动证书配置");
                        System.err.println("自动配置错误: " + autoConfigException.getMessage());
                        System.err.println("错误类型: " + autoConfigException.getClass().getName());
                        autoConfigException.printStackTrace();

                        // 检查是否是证书相关的错误
                        if (autoConfigException.getMessage() != null && (
                                autoConfigException.getMessage().contains("certificate") ||
                                        autoConfigException.getMessage().contains("X509Certificate") ||
                                        autoConfigException.getMessage().contains("getSerialNumber") ||
                                        autoConfigException.getMessage().contains("404") ||
                                        autoConfigException.getMessage().contains("API安全"))) {

                            System.err.println("🔍 生产环境证书问题诊断:");
                            System.err.println("1. 检查商户平台是否已开启API安全功能");
                            System.err.println("2. 检查是否已申请使用微信支付公钥");
                            System.err.println("3. 检查网络连接是否正常");
                            System.err.println("4. 检查商户证书序列号是否正确");
                        }

                        try {
                            // 回退到手动证书配置
                            if (payment.getPubKey() != null && !payment.getPubKey().isEmpty()) {
                                System.out.println("使用RSA公钥配置作为回退方案");
                                config = new RSAPublicKeyConfig.Builder()
                                        .merchantId(payment.getMchId())
                                        .privateKeyFromPath(privateKey)
                                        .publicKeyFromPath(pubKey)
                                        .publicKeyId(payment.getPubKeyId())
                                        .merchantSerialNumber(payment.getMerchantSerialNumber())
                                        .apiV3Key(payment.getApiKey())
                                        .build();
                                System.out.println("✅ 生产环境RSA公钥配置成功");
                            } else if (apiclientCert != null && !apiclientCert.isEmpty()) {
                                System.out.println("使用RSA证书配置作为回退方案");
                                config = new RSAConfig.Builder()
                                        .merchantId(payment.getMchId())
                                        .privateKeyFromPath(privateKey)
                                        .merchantSerialNumber(payment.getMerchantSerialNumber())
                                        .wechatPayCertificatesFromPath(apiclientCert)
                                        .build();
                                System.out.println("✅ 生产环境RSA证书配置成功");
                            } else {
                                throw new RuntimeException("生产环境缺少必要的证书文件，无法创建手动证书配置", autoConfigException);
                            }
                        } catch (Exception fallbackException) {
                            System.err.println("❌ 生产环境手动证书配置也失败: " + fallbackException.getMessage());
                            throw new RuntimeException("生产环境微信支付配置失败，请检查商户平台API安全设置和证书配置", autoConfigException);
                        }
                    }
                }
            }

            // 构建service
            return new JsapiServiceExtension.Builder().config(config).build();
        } catch (Exception e) {
            System.err.println("=== 构建微信支付服务失败 ===");
            System.err.println("错误信息: " + e.getMessage());
            System.err.println("错误类型: " + e.getClass().getName());
            e.printStackTrace();
            throw new RuntimeException("构建微信支付服务失败：" + e.getMessage(), e);
        }
    }

    @Override
    public BigDecimal total() {
        try {
            // 使用数据库聚合查询统计订单总金额，性能更高
            BigDecimal total = baseMapper.selectTotalAmount();

            if (total == null) {
                total = BigDecimal.ZERO;
            }

            log.info("统计订单总金额完成，总金额：{}", total);
            return total;

        } catch (Exception e) {
            log.error("统计订单总金额失败", e);
            return BigDecimal.ZERO;
        }
    }

    /**
     * 获取Native支付的微信支付配置
     */
    private Config getWxPayConfig(ShopOrder order) throws Exception {
        try {
            final Payment payment = getPayment(order);
            String privateKey;
            String apiclientCert = null;
            String pubKey = null;

            // 初始化证书路径
            if (active.equals("dev")) {
                // 开发环境 - 构建包含租户号的证书路径
                String tenantCertPath = "dev/wechat/" + order.getTenantId();
                String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();

                System.out.println("开发环境证书路径 - 租户ID: " + order.getTenantId());
                System.out.println("开发环境证书路径 - 私钥: " + privateKeyPath);

                privateKey = certificateLoader.loadCertificatePath(privateKeyPath);
                System.out.println("私钥完整路径: " + privateKey);

                // 尝试加载公钥（如果配置了）
                if (StrUtil.isNotBlank(payment.getPubKey()) && StrUtil.isNotBlank(payment.getPubKeyId())) {
                    try {
                        String pubKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getWechatpayCertFile();
                        pubKey = certificateLoader.loadCertificatePath(pubKeyPath);
                        System.out.println("✅ 开发环境公钥加载成功");
                    } catch (Exception e) {
                        System.out.println("⚠️ 开发环境公钥加载失败，将使用自动证书配置: " + e.getMessage());
                    }
                }
            } else {
                // 生产环境 - 从数据库配置的路径加载
                final String certRootPath = certConfig.getCertRootPath();

                System.out.println("生产环境证书路径 - 租户ID: " + order.getTenantId());
                System.out.println("生产环境证书根路径: " + certRootPath);
                System.out.println("私钥文件名: " + payment.getApiclientKey());

                String privateKeyRelativePath = payment.getApiclientKey();

                // 生产环境已经没有/file目录，所有路径都直接拼接到根路径
                String privateKeyFullPath;
                // 处理数据库中可能存在的历史路径格式
                String cleanPath2 = privateKeyRelativePath;
                if (privateKeyRelativePath.startsWith("/file/")) {
                    // 去掉历史的 /file/ 前缀
                    cleanPath2 = privateKeyRelativePath.substring(6);
                } else if (privateKeyRelativePath.startsWith("file/")) {
                    // 去掉历史的 file/ 前缀
                    cleanPath2 = privateKeyRelativePath.substring(5);
                }
                // 确保路径以 / 开头
                if (!cleanPath2.startsWith("/")) {
                    cleanPath2 = "/" + cleanPath2;
                }
                privateKeyFullPath = certRootPath + cleanPath2;

                System.out.println("私钥完整路径: " + privateKeyFullPath);
                privateKey = certificateLoader.loadCertificatePath(privateKeyFullPath);
                System.out.println("✅ 生产环境私钥加载完成: " + privateKey);

                // 尝试加载公钥（如果配置了）
                if (StrUtil.isNotBlank(payment.getPubKey()) && StrUtil.isNotBlank(payment.getPubKeyId())) {
                    try {
                        String pubKeyRelativePath = payment.getPubKey();
                        System.out.println("数据库中的公钥相对路径: " + pubKeyRelativePath);

                        // 生产环境已经没有/file目录，所有路径都直接拼接到根路径
                        String pubKeyFullPath;
                        // 处理数据库中可能存在的历史路径格式
                        String cleanPubPath2 = pubKeyRelativePath;
                        if (pubKeyRelativePath.startsWith("/file/")) {
                            // 去掉历史的 /file/ 前缀
                            cleanPubPath2 = pubKeyRelativePath.substring(6);
                        } else if (pubKeyRelativePath.startsWith("file/")) {
                            // 去掉历史的 file/ 前缀
                            cleanPubPath2 = pubKeyRelativePath.substring(5);
                        }
                        // 确保路径以 / 开头
                        if (!cleanPubPath2.startsWith("/")) {
                            cleanPubPath2 = "/" + cleanPubPath2;
                        }
                        pubKeyFullPath = certRootPath + cleanPubPath2;

                        System.out.println("生产环境公钥完整路径: " + pubKeyFullPath);
                        pubKey = certificateLoader.loadCertificatePath(pubKeyFullPath);
                        System.out.println("✅ 生产环境公钥加载成功");
                    } catch (Exception e) {
                        System.out.println("⚠️ 生产环境公钥加载失败，将使用自动证书配置: " + e.getMessage());
                    }
                }
            }

            // 根据可用的证书类型选择配置方式
            Config config;
            if (pubKey != null && StrUtil.isNotBlank(payment.getPubKeyId())) {
                // 使用RSA公钥配置（推荐方式）
                System.out.println("🔧 使用RSA公钥配置");
                config = new RSAPublicKeyConfig.Builder()
                        .merchantId(payment.getMchId())
                        .privateKeyFromPath(privateKey)
                        .merchantSerialNumber(payment.getMerchantSerialNumber())
                        .publicKeyFromPath(pubKey)
                        .publicKeyId(payment.getPubKeyId())
                        .apiV3Key(payment.getApiKey())
                        .build();
            } else {
                // 使用自动证书配置
                System.out.println("🔧 使用RSA自动证书配置");
                config = new RSAAutoCertificateConfig.Builder()
                        .merchantId(payment.getMchId())
                        .privateKeyFromPath(privateKey)
                        .merchantSerialNumber(payment.getMerchantSerialNumber())
                        .apiV3Key(payment.getApiKey())
                        .build();
            }

            System.out.println("✅ 微信支付配置构建成功");
            return config;

        } catch (Exception e) {
            System.err.println("❌ 构建微信支付服务失败: " + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("构建微信支付服务失败：" + e.getMessage(), e);
        }
    }

    @Override
    public ShopOrder getByOrderNo(String orderNo, Integer tenantId) {
        return this.lambdaQuery()
                .eq(ShopOrder::getOrderNo, orderNo)
                .eq(ShopOrder::getTenantId, tenantId)
                .one();
    }

    @Override
    public boolean syncPaymentStatus(String orderNo, Integer paymentStatus, String transactionId, String payTime, Integer tenantId) {
        // 查询订单
        ShopOrder order = getByOrderNo(orderNo, tenantId);
        if (order == null) {
            log.warn("同步支付状态失败：订单不存在, orderNo={}, tenantId={}", orderNo, tenantId);
            return false;
        }

        // 如果订单已经是支付成功状态，不需要更新
        if (Boolean.TRUE.equals(order.getPayStatus()) && paymentStatus == 1) {
            log.info("订单已经是支付成功状态，无需更新: orderNo={}", orderNo);
            return true;
        }

        // 更新订单状态
        boolean updated = this.lambdaUpdate()
                .eq(ShopOrder::getOrderNo, orderNo)
                .eq(ShopOrder::getTenantId, tenantId)
                .set(ShopOrder::getPayStatus, paymentStatus == 1)
                .set(transactionId != null, ShopOrder::getTransactionId, transactionId)
                .set(payTime != null, ShopOrder::getPayTime, payTime)
                .set(ShopOrder::getUpdateTime, LocalDateTime.now())
                .update();

        if (updated) {
            log.info("订单支付状态同步成功: orderNo={}, paymentStatus={}, transactionId={}",
                orderNo, paymentStatus, transactionId);
            // paymentStatus=1时，同步触发支付成功后业务逻辑（包括付款减库存/销量等）
            if (paymentStatus != null && paymentStatus == 1) {
                handlePaymentSuccess(order);
            }
        } else {
            log.warn("订单支付状态同步失败: orderNo={}, paymentStatus={}", orderNo, paymentStatus);
        }

        return updated;
    }


}
