package com.gxwebsoft.shop.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.config.CertificateProperties;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.CertificateLoader;
import com.gxwebsoft.common.core.utils.WechatCertAutoConfig;
import com.gxwebsoft.common.core.utils.WechatPayConfigValidator;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.shop.entity.ShopOrderDelivery;
import com.gxwebsoft.shop.entity.ShopUserAddress;
import com.gxwebsoft.shop.service.*;
import com.gxwebsoft.shop.service.impl.KuaiDi100Impl;
import com.gxwebsoft.shop.task.OrderAutoCancelTask;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.param.ShopOrderParam;
import com.gxwebsoft.shop.dto.OrderCreateRequest;
import com.gxwebsoft.shop.dto.OrderPrepayRequest;
import com.gxwebsoft.shop.dto.UpdatePaymentStatusRequest;
import com.gxwebsoft.payment.service.PaymentService;
import com.gxwebsoft.payment.dto.PaymentResponse;
import com.gxwebsoft.payment.enums.PaymentType;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.system.entity.User;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.Operation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 订单控制器
 *
 * @author 科技小王子
 * @since 2025-01-11 10:45:12
 */
@Tag(name = "订单管理")
@RestController
@RequestMapping("/api/shop/shop-order")
public class ShopOrderController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(ShopOrderController.class);
    @Resource
    private ShopOrderService shopOrderService;
    @Resource
    private ShopOrderGoodsService shopOrderGoodsService;
    @Resource
    private OrderBusinessService orderBusinessService;
    @Resource
    private OrderCancelService orderCancelService;
    @Resource
    private OrderAutoCancelTask orderAutoCancelTask;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ConfigProperties conf;
    @Resource
    private CertificateProperties certConfig;
    @Resource
    private CertificateLoader certificateLoader;
    @Resource
    private WechatCertAutoConfig wechatCertAutoConfig;
    @Resource
    private WechatPayConfigValidator wechatPayConfigValidator;
    @Value("${spring.profiles.active}")
    String active;
    @Resource
    private KuaiDi100Impl kuaiDi100;
    @Resource
    private ShopExpressService expressService;
    @Resource
    private ShopUserAddressService shopUserAddressService;
    @Resource
    private ShopOrderDeliveryService shopOrderDeliveryService;
    @Resource
    private ShopWechatShippingSyncService shopWechatShippingSyncService;
    @Resource
    private PaymentService paymentService;
    @Resource
    private ShopStoreFenceService shopStoreFenceService;

    @Operation(summary = "分页查询订单")
    @GetMapping("/page")
    public ApiResult<PageResult<ShopOrder>> page(ShopOrderParam param) {
        // 使用关联查询
        return success(shopOrderService.pageRel(param));
    }

    @Operation(summary = "查询全部订单")
    @GetMapping()
    public ApiResult<List<ShopOrder>> list(ShopOrderParam param) {
        // 使用关联查询
        return success(shopOrderService.listRel(param));
    }

    @PreAuthorize("hasAuthority('shop:shopOrder:list')")
    @Operation(summary = "根据id查询订单")
    @GetMapping("/{id}")
    public ApiResult<ShopOrder> get(@PathVariable("id") Integer id) {
        // 使用关联查询
        return success(shopOrderService.getByIdRel(id));
    }

    @Operation(summary = "添加订单")
    @PostMapping()
    public ApiResult<?> save(@RequestBody OrderCreateRequest request) {
        User loginUser = getLoginUser();
        if (loginUser == null) {
            return fail("用户未登录");
        }

        try {
            Map<String, String> wxOrderInfo = orderBusinessService.createOrder(request, loginUser);
            return success("下单成功", wxOrderInfo);
        } catch (Exception e) {
            logger.error("创建订单失败 - 用户ID：{}，请求：{}", loginUser.getUserId(), request, e);
            return fail(e.getMessage());
        }
    }

    @Operation(summary = "添加订单(兼容旧版本)")
    @PostMapping("/legacy")
    public ApiResult<?> saveLegacy(@RequestBody ShopOrder shopOrder) {
        // 记录当前登录用户id
        User loginUser = getLoginUser();
        if (loginUser != null) {
            shopOrder.setUserId(loginUser.getUserId());
            shopOrder.setOpenid(loginUser.getOpenid());
            shopOrder.setPayUserId(loginUser.getUserId());
            if (shopOrder.getTenantId() == null) {
                shopOrder.setTenantId(loginUser.getTenantId());
            }

            // 下单时间 & 订单过期时间：默认下单后10分钟过期（用于发起支付等场景校验）
            LocalDateTime now = LocalDateTime.now();
            if (shopOrder.getCreateTime() == null) {
                shopOrder.setCreateTime(now);
            }
            if (shopOrder.getUpdateTime() == null) {
                shopOrder.setUpdateTime(now);
            }
            shopOrder.setExpirationTime(shopOrder.getCreateTime().plusMinutes(60));

            if (shopOrder.getOrderNo() == null) {
                shopOrder.setOrderNo(Long.toString(IdUtil.getSnowflakeNextId()));
            }
            if (shopOrder.getComments() == null) {
                shopOrder.setComments("暂无");
            }
            // 微信支付(商品金额不能为0)
            if (shopOrder.getTotalPrice().compareTo(BigDecimal.ZERO) == 0) {
                return fail("商品金额不能为0");
            }
            // 百色中学项目捐赠金额不能低于20元
            if (shopOrder.getTenantId().equals(10324) && shopOrder.getTotalPrice().compareTo(new BigDecimal("10")) < 0) {
                return fail("捐款金额最低不能少于10元，感谢您的爱心捐赠^_^");
            }
            // 测试支付
            if (loginUser.getPhone().equals("13737128880")) {
                shopOrder.setPrice(new BigDecimal("0.01"));
                shopOrder.setTotalPrice(new BigDecimal("0.01"));
            }

            // 下单时校验配送范围（电子围栏）：不信任前端传经纬度，使用 addressId 反查地址表坐标
            try {
                // 自提/无需物流跳过
                boolean needFenceCheck = !(shopOrder.getSelfTakeMerchantId() != null && shopOrder.getSelfTakeMerchantId() > 0)
                        && !(shopOrder.getDeliveryType() != null && shopOrder.getDeliveryType().equals(1));
                if (needFenceCheck && shopOrder.getAddressId() == null) {
                    if (shopStoreFenceService.hasEnabledFences(shopOrder.getTenantId())) {
                        return fail("请先选择收货地址");
                    }
                }
                if (needFenceCheck && shopOrder.getAddressId() != null) {
                    ShopUserAddress address = shopUserAddressService.getById(shopOrder.getAddressId());
                    if (address == null || address.getUserId() == null || !address.getUserId().equals(loginUser.getUserId())) {
                        return fail("收货地址不存在");
                    }
                    if (address.getTenantId() != null && shopOrder.getTenantId() != null && !address.getTenantId().equals(shopOrder.getTenantId())) {
                        return fail("收货地址不存在");
                    }
                    if (StrUtil.isBlank(address.getLat()) || StrUtil.isBlank(address.getLng())) {
                        return fail("收货地址坐标缺失，请重新选择收货地址");
                    }
                    double lat = Double.parseDouble(address.getLat().trim());
                    double lng = Double.parseDouble(address.getLng().trim());
                    shopOrder.setAddressLat(address.getLat());
                    shopOrder.setAddressLng(address.getLng());
                    shopStoreFenceService.validatePointInEnabledFences(shopOrder.getTenantId(), lng, lat);
                }
            } catch (Exception e) {
                // BusinessException message 直接透出；其他异常做兜底
                return fail(e.getMessage() == null ? "收货地址不在配送范围内" : e.getMessage());
            }

            if (shopOrderService.save(shopOrder)) {
                return success("下单成功", shopOrderService.createWxOrder(shopOrder));
            }
        }
        return fail("添加失败");
    }

    @Operation(summary = "发起支付/重新支付（兼容 pay/prepay/repay）")
    @PostMapping({"/pay", "/prepay", "/repay"})
    public ApiResult<?> prepay(@RequestBody OrderPrepayRequest request) {
        User loginUser = getLoginUser();
        if (loginUser == null) {
            return fail("用户未登录");
        }

        // 允许从请求显式传 tenantId（兼容一些历史调用），否则优先从请求头/登录态推断
        Integer tenantId = request != null ? request.getTenantId() : null;
        if (tenantId == null) {
            tenantId = ObjectUtil.defaultIfNull(getTenantId(), loginUser.getTenantId());
        }

        if (request == null || (request.getOrderId() == null && StrUtil.isBlank(request.getOrderNo()))) {
            return fail("orderId 或 orderNo 不能为空");
        }

        ShopOrder order;
        if (request.getOrderId() != null) {
            order = shopOrderService.getById(request.getOrderId());
        } else {
            if (tenantId == null) {
                return fail("tenantId 不能为空");
            }
            order = shopOrderService.getByOrderNo(request.getOrderNo(), tenantId);
        }
        if (order == null) {
            return fail("订单不存在");
        }

        // 校验租户（避免用别的租户订单号撞库）
        if (tenantId != null && order.getTenantId() != null && !tenantId.equals(order.getTenantId())) {
            return fail("订单不存在");
        }

        // 普通用户只能操作自己的订单；管理员可越权（复用取消权限判断即可）
        if (!loginUser.getUserId().equals(order.getUserId()) && !hasOrderCancelAuthority()) {
            return fail("无权限操作此订单");
        }

        // 业务状态校验：这些错误需要明确返回（code!=0），避免前端误判为接口不支持而降级走创建订单
        if (Boolean.TRUE.equals(order.getPayStatus())) {
            return fail("订单已支付");
        }
        if (order.getDeleted() != null && order.getDeleted() == 1) {
            return fail("订单已删除");
        }
        if (order.getOrderStatus() != null) {
            // 2=已取消；6=退款成功；7=客户端申请退款；其他非0状态也视为不可再次发起支付
            if (!Objects.equals(order.getOrderStatus(), 0)) {
                return fail("订单状态不允许发起支付");
            }
        }
        if (order.getExpirationTime() != null && order.getExpirationTime().isBefore(LocalDateTime.now())) {
            return fail("订单已过期");
        }

        // 补齐 createWxOrder 所需字段（注意：openid 在 ShopOrder 上是非持久化字段，查询出来为空）
        Integer payType = request.getPayType() != null ? request.getPayType() : order.getPayType();
        if (payType == null) {
            payType = 1;
        }
        if (!Objects.equals(payType, 1) && !Objects.equals(payType, 102)) {
            return fail("该订单不支持发起微信支付");
        }
        order.setPayType(payType);
        order.setPayUserId(loginUser.getUserId());
        order.setOpenid(loginUser.getOpenid());
        if (order.getPayPrice() == null) {
            order.setPayPrice(ObjectUtil.defaultIfNull(order.getTotalPrice(), BigDecimal.ZERO));
        }
        if (StrUtil.isBlank(order.getComments())) {
            order.setComments("订单支付");
        }

        try {
            Map<String, String> wxOrderInfo = shopOrderService.createWxOrder(order);
            return success(wxOrderInfo);
        } catch (Exception e) {
            logger.error("发起支付失败 - userId={}, orderId={}, orderNo={}",
                    loginUser.getUserId(), order.getOrderId(), order.getOrderNo(), e);
            return fail("发起支付失败：" + e.getMessage());
        }
    }

    @PreAuthorize("hasAuthority('shop:shopOrder:update')")
    @Operation(summary = "修改订单")
    @PutMapping()
    public ApiResult<?> update(@RequestBody ShopOrder shopOrder) throws Exception {
        if (shopOrder == null) {
            return fail("订单不存在");
        }
        // 退款相关操作单独走退款接口，便于做财务权限隔离
        if (Objects.equals(shopOrder.getOrderStatus(), 4)
                || Objects.equals(shopOrder.getOrderStatus(), 5)
                || Objects.equals(shopOrder.getOrderStatus(), 6)
                || Objects.equals(shopOrder.getOrderStatus(), 7)) {
            return fail("退款相关操作请使用退款接口: PUT /api/shop/shop-order/refund");
        }
        ShopOrder shopOrderNow = shopOrderService.getById(shopOrder.getOrderId());
        if (shopOrderNow == null) {
            return fail("订单不存在");
        }
        // 发货状态从“未发货(10)”变更为“已发货(20)”时，记录发货信息
        if (Objects.equals(shopOrderNow.getDeliveryStatus(), 10) && Objects.equals(shopOrder.getDeliveryStatus(), 20)) {
            // 1) 无需物流/自提：不走快递100下单，直接置为已发货并同步到微信后台
            if (shopOrder.getExpressId() == null || shopOrder.getExpressId() == 0) {
                ShopOrderDelivery shopOrderDelivery = new ShopOrderDelivery();
                shopOrderDelivery.setOrderId(shopOrder.getOrderId());
                shopOrderDelivery.setDeliveryMethod(20);
                shopOrderDelivery.setSendName(shopOrder.getSendName());
                shopOrderDelivery.setSendPhone(shopOrder.getSendPhone());
                shopOrderDelivery.setSendAddress(shopOrder.getSendAddress());
                shopOrderDeliveryService.save(shopOrderDelivery);

                ShopOrder patch = new ShopOrder();
                patch.setOrderId(shopOrder.getOrderId());
                patch.setDeliveryStatus(20);
                patch.setDeliveryTime(LocalDateTime.now());
                shopOrderService.updateById(patch);

                // 同步到微信后台（发货信息录入）
                ShopOrder syncOrder = shopOrderNow;
                syncOrder.setDeliveryStatus(20);
                syncOrder.setDeliveryTime(patch.getDeliveryTime());
                try {
                    shopWechatShippingSyncService.uploadNoLogisticsShippingInfo(syncOrder);
                } catch (Exception e) {
                    logger.warn("同步微信发货信息失败(无需物流，不影响发货成功) - orderId={}", shopOrder.getOrderId(), e);
                }
            } else {
                // 2) 实物快递：创建发货单并走快递100电子面单，发货成功后同步微信后台
                ShopOrderDelivery shopOrderDelivery = new ShopOrderDelivery();
                shopOrderDelivery.setOrderId(shopOrder.getOrderId());
                shopOrderDelivery.setDeliveryMethod(30);
                shopOrderDelivery.setExpressId(shopOrder.getExpressId());
                shopOrderDelivery.setSendName(shopOrder.getSendName());
                shopOrderDelivery.setSendPhone(shopOrder.getSendPhone());
                shopOrderDelivery.setSendAddress(shopOrder.getSendAddress());
                shopOrderDeliveryService.save(shopOrderDelivery);

                // 需要用订单的持久化字段（例如 addressId/tenantId/userId/transactionId），同时补齐临时的发货地址
                ShopOrder orderForDelivery = shopOrderNow;
                orderForDelivery.setSendAddress(shopOrder.getSendAddress());
                shopOrderDeliveryService.setExpress(getLoginUser(), shopOrderDelivery, orderForDelivery);
        }

        }
        if (shopOrderService.updateById(shopOrder)) {
            // 如果订单上带了快递单号（常见于后台手工修正/补录），同步到发货单表，避免发货单还是旧单号
            if (StrUtil.isNotBlank(shopOrder.getExpressNo()) && shopOrder.getOrderId() != null) {
                try {
                    List<ShopOrderDelivery> deliveryList = shopOrderDeliveryService.list(
                            new LambdaQueryWrapper<ShopOrderDelivery>()
                                    .eq(ShopOrderDelivery::getOrderId, shopOrder.getOrderId())
                    );
                    if (deliveryList == null || deliveryList.isEmpty()) {
                        ShopOrderDelivery delivery = new ShopOrderDelivery();
                        delivery.setOrderId(shopOrder.getOrderId());
                        delivery.setTenantId(ObjectUtil.defaultIfNull(shopOrder.getTenantId(), shopOrderNow.getTenantId()));
                        delivery.setExpressId(ObjectUtil.defaultIfNull(shopOrder.getExpressId(), shopOrderNow.getExpressId()));
                        delivery.setExpressNo(shopOrder.getExpressNo());
                        // 10手动录入 / 20无需物流
                        if (delivery.getExpressId() == null || delivery.getExpressId() == 0) {
                            delivery.setDeliveryMethod(20);
                        } else {
                            delivery.setDeliveryMethod(10);
                        }
                        delivery.setSendName(ObjectUtil.defaultIfNull(shopOrder.getSendName(), shopOrderNow.getSendName()));
                        delivery.setSendPhone(ObjectUtil.defaultIfNull(shopOrder.getSendPhone(), shopOrderNow.getSendPhone()));
                        delivery.setSendAddress(ObjectUtil.defaultIfNull(shopOrder.getSendAddress(), shopOrderNow.getSendAddress()));
                        shopOrderDeliveryService.save(delivery);
                    } else {
                        for (ShopOrderDelivery d : deliveryList) {
                            if (d == null || d.getDeliveryId() == null) {
                                continue;
                            }
                            ShopOrderDelivery patch = new ShopOrderDelivery();
                            patch.setDeliveryId(d.getDeliveryId());
                            patch.setExpressNo(shopOrder.getExpressNo());
                            shopOrderDeliveryService.updateById(patch);
                        }
                    }
                } catch (Exception e) {
                    logger.warn("同步更新发货单运单号失败 - orderId={}, expressNo={}",
                            shopOrder.getOrderId(), shopOrder.getExpressNo(), e);
                }
            }
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('shop:shopOrder:refund')")
    @Operation(summary = "订单退款操作(申请退款/同意退款)", description = "orderStatus=4 申请退款；orderStatus=6 同意退款并发起原路退款")
    @PutMapping("/refund")
    public ApiResult<?> refund(@RequestBody ShopOrder req) {
        if (req == null || req.getOrderId() == null || req.getOrderStatus() == null) {
            return fail("orderId 和 orderStatus 不能为空");
        }
        if (!Objects.equals(req.getOrderStatus(), 4) && !Objects.equals(req.getOrderStatus(), 6)) {
            return fail("orderStatus 仅支持 4(申请退款) 或 6(同意退款)");
        }

        ShopOrder current = shopOrderService.getById(req.getOrderId());
        if (current == null) {
            return fail("订单不存在");
        }

        // 申请退款：只记录申请时间/原因/金额（如有）
        if (Objects.equals(req.getOrderStatus(), 4)) {
            // 未支付订单不允许进入退款流程（否则会出现“取消订单/超时取消后变成退款申请中”的严重脏状态）
            if (!Boolean.TRUE.equals(current.getPayStatus())) {
                return fail("订单未支付，无法申请退款");
            }
            if (Objects.equals(current.getOrderStatus(), 2)) {
                return fail("订单已取消，无法申请退款");
            }
            if (Objects.equals(current.getOrderStatus(), 4)
                    || Objects.equals(current.getOrderStatus(), 5)
                    || Objects.equals(current.getOrderStatus(), 6)
                    || Objects.equals(current.getOrderStatus(), 7)) {
                return fail("订单已在退款流程中，请勿重复申请");
            }

            ShopOrder patch = new ShopOrder();
            patch.setOrderId(req.getOrderId());
            patch.setOrderStatus(4);
            patch.setRefundApplyTime(LocalDateTime.now());
            if (StrUtil.isNotBlank(req.getRefundReason())) {
                patch.setRefundReason(req.getRefundReason());
            }
            if (req.getRefundMoney() != null) {
                patch.setRefundMoney(req.getRefundMoney());
            }
            if (shopOrderService.updateById(patch)) {
                return success("申请退款成功");
            }
            return fail("申请退款失败");
        }

        // 同意退款：发起原路退款并更新退款信息
        try {
            if (!Boolean.TRUE.equals(current.getPayStatus())) {
                return fail("订单未支付，无法退款");
            }
            if (StrUtil.isNotBlank(current.getRefundOrder())) {
                logger.warn("订单已经退款过，订单号: {}, 退款单号: {}", current.getOrderNo(), current.getRefundOrder());
                return fail("订单已退款，请勿重复操作");
            }

            String refundNo = "RF" + IdUtil.getSnowflakeNextId();

            BigDecimal refundAmount = req.getRefundMoney();
            if (refundAmount == null || refundAmount.compareTo(BigDecimal.ZERO) <= 0) {
                refundAmount = current.getTotalPrice();
            }
            if (refundAmount.compareTo(current.getTotalPrice()) > 0) {
                return fail("退款金额不能大于订单金额");
            }

            PaymentType paymentType = PaymentType.WECHAT_NATIVE;
            if (current.getPayType() != null) {
                // 支付方式：0余额支付，1微信支付，2支付宝支付，3银联支付，4现金支付，5POS机支付，6免费，7积分支付
                paymentType = PaymentType.getByCode(current.getPayType());
                if (paymentType == PaymentType.WECHAT) {
                    paymentType = PaymentType.WECHAT_NATIVE;
                }
            }

            logger.info("开始处理订单退款 - 订单号: {}, 退款单号: {}, 退款金额: {}, 支付方式: {}",
                current.getOrderNo(), refundNo, refundAmount, paymentType);

            PaymentResponse refundResponse = paymentService.refund(
                current.getOrderNo(),
                refundNo,
                paymentType,
                current.getTotalPrice(),
                refundAmount,
                StrUtil.isNotBlank(req.getRefundReason()) ? req.getRefundReason() : "用户申请退款",
                current.getTenantId()
            );

            if (!Boolean.TRUE.equals(refundResponse.getSuccess())) {
                logger.error("订单退款失败 - 订单号: {}, 错误: {}", current.getOrderNo(), refundResponse.getErrorMessage());
                return fail("退款失败: " + refundResponse.getErrorMessage());
            }

            ShopOrder patch = new ShopOrder();
            patch.setOrderId(req.getOrderId());
            patch.setRefundOrder(refundNo);
            patch.setRefundMoney(refundAmount);
            patch.setRefundTime(LocalDateTime.now());
            patch.setOrderStatus(6);
            if (StrUtil.isNotBlank(req.getRefundReason())) {
                patch.setRefundReason(req.getRefundReason());
            }

            if (!shopOrderService.updateById(patch)) {
                logger.error("退款已成功但订单更新失败 - orderId={}, orderNo={}, refundNo={}", current.getOrderId(), current.getOrderNo(), refundNo);
                return fail("退款成功，但订单状态更新失败，请联系管理员");
            }

            logger.info("订单退款请求成功 - 订单号: {}, 退款单号: {}, 微信退款单号: {}",
                current.getOrderNo(), refundNo, refundResponse.getTransactionId());
            return success("退款成功");

        } catch (Exception e) {
            logger.error("处理订单退款异常 - 订单号: {}, 错误: {}", current.getOrderNo(), e.getMessage(), e);
            return fail("退款处理异常: " + e.getMessage());
        }
    }

    @Operation(summary = "删除订单")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
        if (shopOrderService.removeById(id)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @Operation(summary = "批量添加订单")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<ShopOrder> list) {
        if (shopOrderService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @Operation(summary = "批量修改订单")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopOrder> batchParam) {
        if (batchParam != null && batchParam.getData() != null) {
            Integer status = batchParam.getData().getOrderStatus();
            // 退款相关操作单独走退款接口，避免绕过财务权限
            if (Objects.equals(status, 4)
                    || Objects.equals(status, 5)
                    || Objects.equals(status, 6)
                    || Objects.equals(status, 7)) {
                return fail("退款相关操作请使用退款接口: PUT /api/shop/shop-order/refund");
            }
        }
        if (batchParam.update(shopOrderService, "order_id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @Operation(summary = "批量删除订单")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (shopOrderService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @Operation(summary = "修复订单")
    @PutMapping("/repair")
    public ApiResult<?> repair(@RequestBody ShopOrder shopOrder) {
        final ShopOrder order = shopOrderService.getByOutTradeNo(shopOrder.getOrderNo());
        if (order != null) {
            shopOrderService.queryOrderByOutTradeNo(order);
            return success("修复成功");
        }
        return fail("修复失败");
    }

    @Operation(summary = "统计订单总金额")
    @GetMapping("/total")
    public ApiResult<BigDecimal> total() {
        return success(shopOrderService.total());
    }

    @Operation(summary = "取消订单")
    @PutMapping("/cancel/{id}")
    public ApiResult<?> cancelOrder(@PathVariable("id") Integer id) {
        try {
            User loginUser = getLoginUser();
            if (loginUser == null) {
                return fail("用户未登录");
            }

            ShopOrder order = shopOrderService.getById(id);
            if (order == null) {
                return fail("订单不存在");
            }

            // 检查订单是否属于当前用户（非管理员用户）
            if (!loginUser.getUserId().equals(order.getUserId()) &&
                    !hasOrderCancelAuthority()) {
                return fail("无权限取消此订单");
            }

            // 检查订单状态
            if (order.getPayStatus() != null && order.getPayStatus()) {
                return fail("订单已支付，无法取消");
            }

            if (order.getOrderStatus() != null && order.getOrderStatus() != 0) {
                return fail("订单状态不允许取消");
            }

            // 标记为用户主动取消（定时任务/系统取消会走默认文案）
            order.setCancelReason("用户取消");
            boolean success = orderCancelService.cancelOrder(order);
            if (success) {
                return success("订单取消成功");
            } else {
                return fail("订单取消失败");
            }

        } catch (Exception e) {
            logger.error("取消订单失败，订单ID：{}", id, e);
            return fail("取消订单失败：" + e.getMessage());
        }
    }

    @PreAuthorize("hasAuthority('shop:shopOrder:manage')")
    @Operation(summary = "手动触发订单自动取消任务（管理员）")
    @PostMapping("/auto-cancel/trigger")
    public ApiResult<?> triggerAutoCancelTask() {
        try {
            orderAutoCancelTask.manualCancelExpiredOrders();
            return success("自动取消任务已触发");
        } catch (Exception e) {
            logger.error("触发自动取消任务失败", e);
            return fail("触发失败：" + e.getMessage());
        }
    }

    @PreAuthorize("hasAuthority('shop:shopOrder:manage')")
    @Operation(summary = "获取自动取消任务状态（管理员）")
    @GetMapping("/auto-cancel/status")
    public ApiResult<?> getAutoCancelTaskStatus() {
        try {
            String status = orderAutoCancelTask.getTaskStatus();
            return success(status);
        } catch (Exception e) {
            logger.error("获取自动取消任务状态失败", e);
            return fail("获取状态失败：" + e.getMessage());
        }
    }

    @Schema(description = "异步通知11")
    @PostMapping("/notify/{tenantId}")
    public String wxNotify(@RequestHeader Map<String, String> header, @RequestBody String body, @PathVariable("tenantId") Integer tenantId) {
        logger.info("异步通知*************** = " + tenantId);

        // 获取支付配置信息用于解密
        String key = "Payment:1:".concat(tenantId.toString());
        Payment payment = redisUtil.get(key, Payment.class);

        // 检查支付配置
        if (ObjectUtil.isEmpty(payment)) {
            throw new RuntimeException("未找到租户支付配置信息，租户ID: " + tenantId);
        }

        logger.info("开始处理微信支付异步通知 - 租户ID: {}", tenantId);
        logger.info("支付配置信息 - 商户号: {}, 应用ID: {}", payment.getMchId(), payment.getAppId());

        // 验证微信支付配置
        WechatPayConfigValidator.ValidationResult validation = wechatPayConfigValidator.validateWechatPayConfig(payment, tenantId);
        if (!validation.isValid()) {
            logger.error("❌ 微信支付配置验证失败: {}", validation.getErrors());
            logger.info("📋 配置诊断报告:\n{}", wechatPayConfigValidator.generateDiagnosticReport(payment, tenantId));
            throw new RuntimeException("微信支付配置验证失败: " + validation.getErrors());
        }
        logger.info("✅ 微信支付配置验证通过");

        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(header.get("wechatpay-serial"))
                .nonce(header.get("wechatpay-nonce"))
                .signature(header.get("wechatpay-signature"))
                .timestamp(header.get("wechatpay-timestamp"))
                .body(body)
                .build();

        // 创建通知配置 - 使用与下单方法相同的证书配置逻辑
        NotificationConfig config;
        try {
            if (active.equals("dev")) {
                // 开发环境 - 构建包含租户号的私钥路径
                String tenantCertPath = "dev/wechat/" + tenantId;
                String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();

                logger.info("开发环境异步通知证书路径: {}", privateKeyPath);
                logger.info("租户ID: {}, 证书目录: {}", tenantId, tenantCertPath);

                // 检查证书文件是否存在
                if (!certificateLoader.certificateExists(privateKeyPath)) {
                    logger.error("证书文件不存在: {}", privateKeyPath);
                    throw new RuntimeException("证书文件不存在: " + privateKeyPath);
                }

                String privateKey = certificateLoader.loadCertificatePath(privateKeyPath);

                // 使用验证器获取有效的 APIv3 密钥
                String apiV3Key = wechatPayConfigValidator.getValidApiV3Key(payment);

                logger.info("私钥文件加载成功: {}", privateKey);
                logger.info("使用APIv3密钥来源: {}", payment.getApiKey() != null && !payment.getApiKey().trim().isEmpty() ? "数据库配置" : "配置文件默认");
                logger.info("APIv3密钥长度: {}", apiV3Key != null ? apiV3Key.length() : 0);
                logger.info("商户证书序列号: {}", payment.getMerchantSerialNumber());

                // 使用自动证书配置
                config = new RSAAutoCertificateConfig.Builder()
                        .merchantId(payment.getMchId())
                        .privateKeyFromPath(privateKey)
                        .merchantSerialNumber(payment.getMerchantSerialNumber())
                        .apiV3Key(apiV3Key)
                        .build();

                logger.info("✅ 开发环境使用自动证书配置创建通知解析器成功");
            } else {
                // 生产环境 - 使用自动证书配置
                final String certRootPath = certConfig.getCertRootPath();
                logger.info("生产环境证书根路径: {}", certRootPath);

                String privateKeyRelativePath = payment.getApiclientKey();
                logger.info("数据库中的私钥相对路径: {}", 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;

                logger.info("生产环境私钥完整路径: {}", privateKeyFullPath);
                String privateKey = certificateLoader.loadCertificatePath(privateKeyFullPath);
                String apiV3Key = payment.getApiKey();

                // 使用自动证书配置
                config = new RSAAutoCertificateConfig.Builder()
                        .merchantId(payment.getMchId())
                        .privateKeyFromPath(privateKey)
                        .merchantSerialNumber(payment.getMerchantSerialNumber())
                        .apiV3Key(apiV3Key)
                        .build();

                logger.info("✅ 生产环境使用自动证书配置创建通知解析器成功");
            }
        } catch (Exception e) {
            logger.error("❌ 创建通知配置失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e);
            logger.error("🔍 错误详情: {}", e.getMessage());
            logger.error("💡 请检查:");
            logger.error("1. 证书文件是否存在且路径正确");
            logger.error("2. APIv3密钥是否配置正确");
            logger.error("3. 商户证书序列号是否正确");
            logger.error("4. 网络连接是否正常");
            throw new RuntimeException("微信支付通知配置失败: " + e.getMessage(), e);
        }

        // 初始化 NotificationParser
        NotificationParser parser = new NotificationParser(config);
        logger.info("✅ 通知解析器创建成功，准备解析异步通知");

        // 以支付通知回调为例，验签、解密并转换成 Transaction
        try {
            logger.info("开始解析微信支付异步通知...");
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            logger.info("✅ 异步通知解析成功 - 交易状态: {}, 商户订单号: {}",
                    transaction.getTradeStateDesc(), transaction.getOutTradeNo());

            if (StrUtil.equals("支付成功", transaction.getTradeStateDesc())) {
                final String outTradeNo = transaction.getOutTradeNo();
                final String transactionId = transaction.getTransactionId();
                final Integer total = transaction.getAmount().getTotal();
                final String tradeStateDesc = transaction.getTradeStateDesc();
                final Transaction.TradeStateEnum tradeState = transaction.getTradeState();
                final Transaction.TradeTypeEnum tradeType = transaction.getTradeType();
                System.out.println("transaction = " + transaction);
                System.out.println("tradeStateDesc = " + tradeStateDesc);
                System.out.println("tradeType = " + tradeType);
                System.out.println("tradeState = " + tradeState);
                System.out.println("outTradeNo = " + outTradeNo);
                System.out.println("amount = " + total);
                // 1. 查询要处理的订单
                ShopOrder order = shopOrderService.getByOutTradeNo(outTradeNo);
                logger.info("查询要处理的订单order = " + order);
                // 2. 已支付则跳过
                if (order.getPayStatus().equals(true)) {
                    return "SUCCESS";
                }
                // 2. 未支付则处理更新订单状态
                if (order.getPayStatus().equals(false)) {
                    // 5. TODO 处理订单状态
                    order.setPayTime(LocalDateTime.now());
                    order.setExpirationTime(order.getCreateTime());
                    order.setPayStatus(true);
                    order.setTransactionId(transactionId);
                    order.setPayPrice(new BigDecimal(NumberUtil.decimalFormat("0.00", total * 0.01)));
                    order.setExpirationTime(LocalDateTime.now().plusYears(10));
                    System.out.println("实际付款金额 = " + order.getPayPrice());
                    // 更新订单状态并处理支付成功后的业务逻辑（包括累加商品销量）
                    shopOrderService.updateByOutTradeNo(order);
                    return "SUCCESS";
                }
            }
        } catch (Exception e) {
            logger.error("❌ 处理微信支付异步通知失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e);
            logger.error("🔍 异常详情: {}", e.getMessage());
            logger.error("💡 可能的原因:");
            logger.error("1. 证书配置错误或证书文件损坏");
            logger.error("2. 微信支付平台证书已过期");
            logger.error("3. 签名验证失败");
            logger.error("4. 请求参数格式错误");

            // 返回失败，微信会重试
            return "fail";
        }

        logger.warn("⚠️ 异步通知处理完成但未找到匹配的支付成功状态");
        return "fail";
    }

    @Operation(summary = "更新订单支付状态", description = "用户支付成功后主动同步订单状态")
    @PutMapping("/payment-status")
    public ApiResult<?> updateOrderPaymentStatus(@RequestBody UpdatePaymentStatusRequest request) {
        logger.info("收到更新订单支付状态请求: orderNo={}, paymentStatus={}, transactionId={}",
                request.getOrderNo(), request.getPaymentStatus(), request.getTransactionId());

        final User loginUser = getLoginUser();
        if (loginUser == null) {
            return fail("请先登录");
        }

        try {
            // 参数验证
            if (StrUtil.isBlank(request.getOrderNo())) {
                return fail("订单号不能为空");
            }

            // 查询订单
            ShopOrder order = shopOrderService.getByOrderNo(request.getOrderNo(), loginUser.getTenantId());
            if (order == null) {
                return fail("订单不存在");
            }

            // 权限验证：只能更新自己的订单
            if (!order.getUserId().equals(loginUser.getUserId())) {
                return fail("无权限操作此订单");
            }

            // 如果订单已经是支付成功状态，直接返回成功
            if (order.getPayStatus()) {
                logger.info("订单已经是支付成功状态，无需更新: orderNo={}", request.getOrderNo());
                return success("订单状态已是最新");
            }

            // 调用支付状态同步服务
            boolean updated = shopOrderService.syncPaymentStatus(
                    request.getOrderNo(),
                    request.getPaymentStatus(),
                    request.getTransactionId(),
                    request.getPayTime(),
                    loginUser.getTenantId()
            );

            if (updated) {
                logger.info("订单支付状态更新成功: orderNo={}, paymentStatus={}",
                        request.getOrderNo(), request.getPaymentStatus());
                return success("订单状态更新成功");
            } else {
                logger.warn("订单支付状态更新失败: orderNo={}", request.getOrderNo());
                return fail("订单状态更新失败");
            }

        } catch (Exception e) {
            logger.error("更新订单支付状态异常: orderNo={}, error={}", request.getOrderNo(), e.getMessage(), e);
            return fail("更新订单状态失败: " + e.getMessage());
        }
    }

    /**
     * 检查是否有订单取消权限
     */
    private boolean hasOrderCancelAuthority() {
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication == null) {
                return false;
            }

            // 检查是否有管理员权限
            return authentication.getAuthorities().stream()
                    .anyMatch(authority ->
                            authority.getAuthority().equals("shop:shopOrder:cancel") ||
                                    authority.getAuthority().equals("shop:shopOrder:update") ||
                                    authority.getAuthority().equals("ROLE_ADMIN") ||
                                    authority.getAuthority().equals("shop:shopOrder:manage"));
        } catch (Exception e) {
            logger.warn("检查订单取消权限时发生异常", e);
            return false;
        }
    }

}
