package com.ylx.massage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylx.common.constant.HttpStatus;
import com.ylx.common.constant.MassageConstants;
import com.ylx.common.core.domain.R;
import com.ylx.common.core.domain.model.WxLoginUser;
import com.ylx.common.exception.ServiceException;
import com.ylx.common.utils.SecurityUtils;
import com.ylx.massage.domain.*;
import com.ylx.massage.domain.dto.*;
import com.ylx.massage.domain.vo.*;
import com.ylx.massage.enums.*;
import com.ylx.massage.mapper.AfterSaleOrderMapper;
import com.ylx.massage.mapper.ProductMapper;
import com.ylx.massage.mapper.ProductOrderInfoMapper;
import com.ylx.massage.mapper.ProductOrderItemMapper;
import com.ylx.massage.mapper.ProductSkuMapper;
import com.ylx.massage.service.*;
import com.ylx.massage.utils.OrderNumberGenerator;
import com.ylx.point.enums.TaskNameEnum;
import com.ylx.point.service.IPointAccountService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * 商品订单信息Service实现类
 */
@Service
@Slf4j
public class ProductOrderInfoServiceImpl extends ServiceImpl<ProductOrderInfoMapper, ProductOrderInfo> implements IProductOrderInfoService {

    @Autowired
    private ProductOrderInfoMapper productOrderInfoMapper;

    @Autowired
    private ProductOrderItemMapper productOrderItemMapper;

    @Autowired
    private OrderNumberGenerator orderNumberGenerator;

    @Autowired
    private ProductMapper productMapper;

    @Resource
    private TRechargeService rechargeService;

    @Resource
    private TWxUserService wxUserService;

    @Resource
    private TConsumptionLogService consumptionLogService;

    @Autowired
    private ProductSkuMapper productSkuMapper;

    @Autowired
    private AfterSaleOrderMapper afterSaleOrderMapper;

    @Resource
    private IAfterSaleOrderService afterSaleOrderService;

    @Resource
    private IPointAccountService pointAccountService;

    /**
     * 创建商品订单
     *
     * @param request 订单创建请求
     * @return String 订单编号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createProductOrder(ProductOrderCreateRequest request) {
        // 当前登录用户信息
        WxLoginUser wxLoginUser = SecurityUtils.getWxLoginUser();
        // 设置用户ID
        request.setOpenId(wxLoginUser.getCOpenid());

        // 1. 参数校验
        validateRequest(request);

        // 2. 生成订单编号
        String orderNo = orderNumberGenerator.generateNextOrderNumber(OrderNumberGenerator.KEY_PREFIX_PRODUCTORDER);
        log.info("创建商品订单，订单编号：{}", orderNo);

        // 3. 构建订单主表信息
        ProductOrderInfo orderInfo = buildOrderInfo(request, orderNo);

        // 4. 保存订单主表
        int insertResult = productOrderInfoMapper.insert(orderInfo);
        if (insertResult <= 0) {
            throw new ServiceException("订单创建失败");
        }
        log.info("订单主表保存成功，订单编号：{}", orderNo);

        // 5. 构建订单商品明细
        ProductOrderItem orderItem = buildOrderItem(request, orderInfo);

        // 6. 保存订单商品明细
        int itemInsertResult = productOrderItemMapper.insert(orderItem);
        if (itemInsertResult <= 0) {
            throw new ServiceException("订单商品明细创建失败");
        }
        log.info("订单商品明细保存成功，订单编号：{}", orderNo);
        return orderNo;
    }

    /**
     * 参数校验
     *
     * @param request 订单创建请求
     */
    private void validateRequest(ProductOrderCreateRequest request) {
        if (request == null) {
            throw new ServiceException("订单请求不能为空");
        }
        if (StringUtils.isBlank(request.getUserName())) {
            throw new ServiceException("用户姓名不能为空");
        }
        if (StringUtils.isBlank(request.getUserPhone())) {
            throw new ServiceException("用户电话不能为空");
        }
        if (StringUtils.isBlank(request.getUserAddress())) {
            throw new ServiceException("用户地址不能为空");
        }
        if (request.getProductId() == null) {
            throw new ServiceException("商品ID不能为空");
        }
        // 根据商品ID查询商品信息
        Product product = productMapper.selectById(request.getProductId());
        if (product == null) {
            throw new ServiceException("商品不存在");
        }

        if (request.getSkuId() == null) {
            throw new ServiceException("SKU ID不能为空");
        }

        // 校验SKU是否存在
        ProductSku sku = productSkuMapper.selectById(request.getSkuId());
        if (sku == null) {
            throw new ServiceException("skuId不存在");
        }
        //校验skuId是否正确
        if (!sku.getProductId().equals(request.getProductId())) {
            throw new ServiceException("skuId不正确");
        }

        // 校验购买数量是否大于0
        if (request.getQuantity() == null || request.getQuantity() <= 0) {
            throw new ServiceException("购买数量必须大于0");
        }
        if (request.getPayType() == null || (request.getPayType() != 1 && request.getPayType() != 2)) {
            throw new ServiceException("支付方式不正确");
        }
        if (request.getTotalAmount() == null || request.getTotalAmount().compareTo(BigDecimal.ZERO) < 0) {
            throw new ServiceException("总金额不能为空");
        }
        if (request.getPayAmount() == null || request.getPayAmount().compareTo(BigDecimal.ZERO) < 0) {
            throw new ServiceException("支付金额不能为空");
        }
    }

    /**
     * 构建订单主表信息
     *
     * @param request 订单创建请求
     * @param orderNo 订单编号
     * @return ProductOrderInfo 订单主表信息
     */
    private ProductOrderInfo buildOrderInfo(ProductOrderCreateRequest request, String orderNo) {
        ProductOrderInfo orderInfo = new ProductOrderInfo();
        orderInfo.setOrderNo(orderNo);
        orderInfo.setOpenId(request.getOpenId());
        orderInfo.setOrderStatus(0); // 待付款
        orderInfo.setPayStatus(0); // 未支付
        orderInfo.setPayType(request.getPayType());
        orderInfo.setTotalAmount(request.getTotalAmount());
        orderInfo.setDiscountAmount(BigDecimal.ZERO); // 优惠金额暂无
        orderInfo.setFreightAmount(request.getFreightAmount() != null ? request.getFreightAmount() : BigDecimal.ZERO);
        orderInfo.setPayAmount(request.getPayAmount());
        orderInfo.setPointsUsed(request.getPointsUsed() != null ? request.getPointsUsed() : 0);
        orderInfo.setUserName(request.getUserName());
        orderInfo.setUserPhone(request.getUserPhone());
        orderInfo.setUserAddress(request.getUserAddress());
        // 快递
        orderInfo.setDeliveryType(1);
        orderInfo.setBuyerRemark(request.getBuyerRemark());
        // 支付超时时间15分钟
        orderInfo.setPayExpireTime(LocalDateTime.now().plusMinutes(15));
        return orderInfo;
    }

    /**
     * 构建订单商品明细
     *
     * @param request   订单创建请求
     * @param orderInfo 订单主表信息
     * @return ProductOrderItem 订单商品明细
     */
    private ProductOrderItem buildOrderItem(ProductOrderCreateRequest request, ProductOrderInfo orderInfo) {
        ProductOrderItem orderItem = new ProductOrderItem();
        orderItem.setOrderId(orderInfo.getId());
        orderItem.setOrderNo(orderInfo.getOrderNo());
        orderItem.setProductId(request.getProductId());
        orderItem.setProductName(request.getName());
        orderItem.setSkuId(request.getSkuId());
        // 将SKU规格信息转为JSON
        if (request.getSpecNameValueList() != null && !request.getSpecNameValueList().isEmpty()) {
            orderItem.setSkuSpec(JSONUtil.toJsonStr(request.getSpecNameValueList()));
        }
        orderItem.setSkuImage(request.getProductMainImage());
        // 单价 = 总金额 / 数量
        orderItem.setPrice(request.getTotalAmount().intValue() / request.getQuantity());
        orderItem.setQuantity(request.getQuantity());
        orderItem.setTotalAmount(request.getTotalAmount());
        orderItem.setDiscountAmount(BigDecimal.ZERO); // 优惠金额暂无
        orderItem.setActualAmount(request.getPayAmount());
        orderItem.setRefundStatus(0); // 无退款
        return orderItem;
    }

    /**
     * 支付订单
     *
     * @param productOrderPayRequest 订单支付请求
     * @return R 订单支付结果
     * @throws Exception
     */
    @Override
    public R payOrder(ProductOrderPayRequest productOrderPayRequest) throws Exception {
        // 1、校验订单是否存在
        LambdaQueryWrapper<ProductOrderInfo> lambdaQueryWrapper = new LambdaQueryWrapper<ProductOrderInfo>().eq(ProductOrderInfo::getOrderNo, productOrderPayRequest.getOrderNo());
        ProductOrderInfo orderInfo = productOrderInfoMapper.selectOne(lambdaQueryWrapper);
        if (orderInfo == null) {
            throw new ServiceException("订单不存在");
        }
        // 2、校验订单状态是否为待付款
        if (orderInfo.getOrderStatus() != 0) {
            throw new ServiceException("订单状态错误");
        }
        // 3、校验支付方式是否正确
        if (orderInfo.getPayType() != productOrderPayRequest.getPayType()) {
            throw new ServiceException("支付方式不正确");
        }

        // 4、校验支付金额是否正确
        if(productOrderPayRequest.getPayType().equals(MassageConstants.INTEGER_ONE) || productOrderPayRequest.getPayType().equals(MassageConstants.INTEGER_TWO)){
            if (orderInfo.getTotalAmount().compareTo(productOrderPayRequest.getTotalPrice()) != 0) {
                throw new ServiceException("支付金额错误");
            }
        }

        //5、如果支付方式为积分支付，那么只需要校验支付的积分
        if (productOrderPayRequest.getPayType().equals(MassageConstants.INTEGER_THREE)) {
            if (orderInfo.getPointsUsed() != productOrderPayRequest.getPointsToPay()) {
                throw new ServiceException("支付积分不正确");
            }
        }

        //6、判断支付方式
        if (productOrderPayRequest.getPayType().equals(MassageConstants.INTEGER_ONE)) {
            //微信支付
            R resp = rechargeService.getPay(orderInfo.getOrderNo(), orderInfo.getTotalAmount(), orderInfo.getOpenId(), BillTypeEnum.WX_PAY.getInfo(), PayTypeEnum.WX_PAY.getCode().toString());
            return resp;
        } else if (productOrderPayRequest.getPayType().equals(MassageConstants.INTEGER_TWO)) {
            //余额支付
            TWxUser user = wxUserService.getByOpenId(orderInfo.getOpenId());
            if (null == user) {
                throw new ServiceException("用户不存在");
            }
            if (user.getdBalance().compareTo(orderInfo.getTotalAmount()) < MassageConstants.INTEGER_ZERO) {
                throw new ServiceException("账户金额不够请充值");
            } else {
                orderPayManage(user, orderInfo);
                return R.ok();
            }
        }else{
            //积分支付
            pointAccountService.deductPoints(orderInfo.getOpenId(), orderInfo.getPointsUsed(), orderInfo.getOrderNo(), TaskNameEnum.GOODS_CONSUME.getInfo());
            return R.ok();
        }
    }

    /**
     * 订单支付管理
     *
     * @param user
     * @param orderInfo
     */
    @Transactional(rollbackFor = Exception.class)
    public void orderPayManage(TWxUser user, ProductOrderInfo orderInfo) {
        // 更新用户金额 及下单此时
        TWxUser paramUser = new TWxUser();
        paramUser.setId(user.getId());
        paramUser.setcOpenid(user.getcOpenid());
        // 余额支付
        if (orderInfo.getPayType().equals(MassageConstants.INTEGER_TWO)) {
            paramUser.setdBalance(user.getdBalance().subtract(orderInfo.getTotalAmount()));
        }
        paramUser.setdMoney(user.getdMoney().add(orderInfo.getTotalAmount()));
        paramUser.setnNum(user.getnNum() + MassageConstants.INTEGER_ONE);
        wxUserService.updateById(paramUser);

        //增加消费记录
        TConsumptionLog tConsumptionLog = new TConsumptionLog();
        tConsumptionLog.setAmount(orderInfo.getTotalAmount().negate());
        tConsumptionLog.setBillNo(orderInfo.getOrderNo());
        tConsumptionLog.setOpenId(orderInfo.getOpenId());
        if (orderInfo.getPayType().equals(MassageConstants.INTEGER_TWO)) {
            tConsumptionLog.setBillType(BillTypeEnum.BALANCE_PAYMENT.getCode());
            tConsumptionLog.setNote("余额支付");
        } else if (orderInfo.getPayType().equals(MassageConstants.INTEGER_ONE)) {
            tConsumptionLog.setBillType(BillTypeEnum.WX_PAY.getCode());
            tConsumptionLog.setNote("微信支付");
        }
        consumptionLogService.save(tConsumptionLog);

        ProductOrderInfo productOrderInfo = new ProductOrderInfo();
        productOrderInfo.setId(orderInfo.getId());
        productOrderInfo.setPayType(orderInfo.getPayType());
        //更新订单状态为待发货
        productOrderInfo.setOrderStatus(ProductOrderStatusEnum.WAIT_DELIVERY.getCode());
        productOrderInfo.setPayTime(LocalDateTime.now());
        //更新订单表
        updateById(productOrderInfo);
    }

    /**
     * 分页查询用户商品订单列表
     *
     * @param page   分页参数
     * @param openId 用户openId
     * @return Page<ProductOrderListVo> 订单分页列表
     */
    @Override
    public Page<ProductOrderListVo> getProductOrderList(Page<ProductOrderListVo> page, String openId) {
        //判断openId是否为空
        if (StringUtils.isBlank(openId)) {
            throw new ServiceException("用户openId不能为空");
        }
        Page<ProductOrderListVo> result = productOrderInfoMapper.selectProductOrderListByOpenId(page, openId);

        for (ProductOrderListVo vo : result.getRecords()) {
            // 设置订单状态名称
            vo.setOrderStatusName(ProductOrderStatusEnum.getDescByCode(vo.getOrderStatus()));
            //设置支付状态名称
            vo.setPayStatusName(PaymentStatusEnum.getDescByCode(vo.getPayStatus()));
        }
        return result;
    }

    /**
     * 查询订单详情
     *
     * @param orderNo 订单编号
     * @param openId  用户openId
     * @return ProductOrderDetailResponse 订单详情（结构化响应）
     */
    @Override
    public ProductOrderDetailResponse getProductOrderDetail(String orderNo, String openId) {
        if (StringUtils.isBlank(openId)) {
            throw new ServiceException("用户openId不能为空");
        }
        if (StringUtils.isBlank(orderNo)) {
            throw new ServiceException("订单编号不能为空");
        }
        ProductOrderDetailVo detail = productOrderInfoMapper.selectProductOrderDetailByOrderNoAndOpenId(orderNo, openId);
        if (detail == null) {
            throw new ServiceException("订单不存在");
        }

        // 构建商品信息
        ProductInfoVo productInfo = buildProductInfo(detail);
        // 构建订单信息
        OrderInfoVo orderInfo = buildOrderInfo(detail);
        // 查询并构建售后信息
        AfterSaleInfoVo afterSaleInfo = buildAfterSaleInfo(detail.getId());
        // 组装响应
        ProductOrderDetailResponse response = new ProductOrderDetailResponse();
        response.setProductInfo(productInfo);
        response.setOrderInfo(orderInfo);
        response.setAfterSaleInfo(afterSaleInfo);
        return response;
    }

    /**
     * 构建商品信息
     */
    private ProductInfoVo buildProductInfo(ProductOrderDetailVo detail) {
        ProductInfoVo productInfo = new ProductInfoVo();
        productInfo.setProductId(detail.getProductId());
        productInfo.setProductName(detail.getProductName());
        productInfo.setSkuSpec(detail.getSkuSpec());
        productInfo.setSkuImage(detail.getSkuImage());
        // 根据商品ID查询商品的付款类型
        Product product = productMapper.selectById(detail.getProductId());
        if (product != null) {
            productInfo.setPaymentType(product.getPaymentType());
        }
        productInfo.setServicePromise(product.getServicePromise());
        productInfo.setDeliveryTime(product.getDeliveryTime());
        return productInfo;
    }

    /**
     * 构建订单信息
     */
    private OrderInfoVo buildOrderInfo(ProductOrderDetailVo detail) {
        OrderInfoVo orderInfo = new OrderInfoVo();
        // 基础订单信息
        orderInfo.setId(detail.getId().toString());
        orderInfo.setOrderNo(detail.getOrderNo());
        orderInfo.setOpenId(detail.getOpenId());
        orderInfo.setOrderStatus(detail.getOrderStatus());
        orderInfo.setOrderStatusName(ProductOrderStatusEnum.getDescByCode(detail.getOrderStatus()));
        orderInfo.setBuyerRemark(detail.getBuyerRemark());
        orderInfo.setDeliveryType(detail.getDeliveryType());
        orderInfo.setCreateTime(detail.getCreateTime());

        // 支付信息
        orderInfo.setPayStatus(detail.getPayStatus());
        orderInfo.setPayType(detail.getPayType());
        orderInfo.setPayTime(detail.getPayTime());
        orderInfo.setPayExpireTime(detail.getPayExpireTime());
        // 计算剩余秒数
        if (detail.getPayExpireTime() != null) {
            long remainSeconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), detail.getPayExpireTime());
            orderInfo.setRemainSeconds(remainSeconds);
        }
        orderInfo.setTotalAmount(detail.getTotalAmount());
        orderInfo.setDiscountAmount(detail.getDiscountAmount());
        orderInfo.setFreightAmount(detail.getFreightAmount());
        orderInfo.setPayAmount(detail.getPayAmount());
        orderInfo.setPointsUsed(detail.getPointsUsed());

        // 地址信息
        orderInfo.setReceiverName(detail.getReceiverName());
        orderInfo.setReceiverPhone(detail.getReceiverPhone());
        orderInfo.setAddressName(detail.getAddressName());

        // 物流信息
        orderInfo.setLogisticsCompany(detail.getLogisticsCompany());
        orderInfo.setLogisticsNo(detail.getLogisticsNo());
        orderInfo.setDeliveryTime(detail.getDeliveryTime());
        orderInfo.setReceiveTime(detail.getReceiveTime());
        return orderInfo;
    }

    /**
     * 构建售后信息
     *
     * @param orderId 订单ID
     * @return AfterSaleInfoVo 售后信息
     */
    private AfterSaleInfoVo buildAfterSaleInfo(Long orderId) {
        AfterSaleInfoVo afterSaleInfo = null;
        // 查询售后订单
        LambdaQueryWrapper<AfterSaleOrder> queryWrapper = new LambdaQueryWrapper<AfterSaleOrder>()
                .eq(AfterSaleOrder::getOrderId, orderId)
                // 关键：添加 不等于取消状态 的条件
                .ne(AfterSaleOrder::getAfterSaleStatus, AfterSaleStatusEnum.CANCELLED.getCode())
                .orderByDesc(AfterSaleOrder::getCreateTime)
                .last("LIMIT 1");
        AfterSaleOrder afterSaleOrder = afterSaleOrderMapper.selectOne(queryWrapper);

        if (ObjectUtil.isNotNull(afterSaleOrder)) {
            afterSaleInfo = new AfterSaleInfoVo();
            afterSaleInfo.setAfterSaleNo(afterSaleOrder.getAfterSaleNo());
            afterSaleInfo.setOrderId(afterSaleOrder.getOrderId());
            afterSaleInfo.setOrderNo(afterSaleOrder.getOrderNo());
            afterSaleInfo.setAfterSaleType(afterSaleOrder.getAfterSaleType());
            afterSaleInfo.setAfterSaleTypeName(getAfterSaleTypeName(afterSaleOrder.getAfterSaleType()));
            afterSaleInfo.setAfterSaleStatus(afterSaleOrder.getAfterSaleStatus());
            afterSaleInfo.setAfterSaleStatusName(AfterSaleStatusEnum.getDescByCode(afterSaleOrder.getAfterSaleStatus()));
            afterSaleInfo.setApplyReason(afterSaleOrder.getApplyReason());
            afterSaleInfo.setApplyDesc(afterSaleOrder.getApplyDesc());
            afterSaleInfo.setApplyImages(afterSaleOrder.getApplyImages());
            afterSaleInfo.setApplyAmount(afterSaleOrder.getApplyAmount());
            afterSaleInfo.setActualRefundAmount(afterSaleOrder.getActualRefundAmount());
            afterSaleInfo.setRefundType(afterSaleOrder.getRefundType());
            afterSaleInfo.setAuditTime(afterSaleOrder.getAuditTime());
            afterSaleInfo.setAuditRemark(afterSaleOrder.getAuditRemark());
            afterSaleInfo.setRejectReason(afterSaleOrder.getRejectReason());
            afterSaleInfo.setRefundTime(afterSaleOrder.getRefundTime());
            afterSaleInfo.setExchangeOrderNo(afterSaleOrder.getExchangeOrderNo());
            afterSaleInfo.setFinishTime(afterSaleOrder.getFinishTime());
            afterSaleInfo.setLogisticsNo(afterSaleOrder.getLogisticsNo());
            afterSaleInfo.setRemark(afterSaleOrder.getRemark());
            afterSaleInfo.setCreateTime(afterSaleOrder.getCreateTime());
        }
        // 如果没有售后信息，返回空对象（Spring会自动初始化为空对象而非null）
        return afterSaleInfo;
    }

    /**
     * 获取售后类型名称
     */
    private String getAfterSaleTypeName(Integer afterSaleType) {
        if (afterSaleType == null) {
            return "";
        }
        return afterSaleType == 1 ? "退货" : "换货";
    }


    /**
     * 取消商品订单
     *
     * @param request 取消订单请求
     * @return R<?> 取消结果
     */
    @Override
    public R<?> cancelOrder(ProductOrderCancelRequest request) {
        // 当前登录用户信息
        WxLoginUser wxLoginUser = SecurityUtils.getWxLoginUser();
        if (wxLoginUser == null) {
            throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
        }

        String orderNo = request.getOrderNo();
        String openId = wxLoginUser.getCOpenid();
        String cancelReason = request.getCancelReason();
        log.info("取消商品订单，订单号：{}，openId：{}，取消原因：{}", orderNo, openId, cancelReason);

        // 1. 查询订单
        LambdaQueryWrapper<ProductOrderInfo> queryWrapper = new LambdaQueryWrapper<ProductOrderInfo>()
                .eq(ProductOrderInfo::getOrderNo, orderNo)
                .eq(ProductOrderInfo::getOpenId, openId);
        ProductOrderInfo order = productOrderInfoMapper.selectOne(queryWrapper);
        if (order == null) {
            throw new ServiceException("订单不存在");
        }

        // 2. 幂等处理：已是已取消状态，直接返回成功
        if (ProductOrderStatusEnum.CANCELLED.getCode().equals(order.getOrderStatus())) {
            log.info("订单已是取消状态，无需重复处理，订单号：{}", orderNo);
            return R.ok("订单已取消");
        }

        // 3. 前置校验：订单状态必须是待付款
        if (!ProductOrderStatusEnum.WAIT_PAY.getCode().equals(order.getOrderStatus())) {
            throw new ServiceException("只有待付款状态的订单才能取消");
        }

        // 4. 关闭微信支付订单（事务外，网络调用）
        try {
            rechargeService.closeWeChatOrder(orderNo);
        } catch (Exception e) {
            log.warn("关闭微信订单异常，继续执行取消流程，订单号：{}，错误：{}", orderNo, e.getMessage());
        }

        // 5. 查询订单商品明细
        LambdaQueryWrapper<ProductOrderItem> itemQueryWrapper = new LambdaQueryWrapper<ProductOrderItem>()
                .eq(ProductOrderItem::getOrderNo, orderNo);
        ProductOrderItem orderItem = productOrderItemMapper.selectOne(itemQueryWrapper);

        // 6. 事务内：释放库存 + 更新订单状态
        releaseStockAndUpdateOrderStatus(order, orderItem, cancelReason);
        log.info("订单取消成功，订单号：{}", orderNo);
        return R.ok("订单取消成功");
    }


    /**
     * 释放库存并更新订单状态（事务内执行）
     *
     * @param order        订单信息
     * @param orderItem    订单商品明细
     * @param cancelReason 取消原因
     */
    @Transactional(rollbackFor = Exception.class)
    public void releaseStockAndUpdateOrderStatus(ProductOrderInfo order, ProductOrderItem orderItem, String cancelReason) {
        // 释放库存
        if (orderItem != null && orderItem.getSkuId() != null && orderItem.getQuantity() != null) {
            int affectedRows = productSkuMapper.releaseStock(orderItem.getSkuId(), orderItem.getQuantity());
            if (affectedRows == 0) {
                throw new ServiceException("库存释放失败，库存不足");
            }
            log.info("库存释放成功，SKU：{}，数量：{}", orderItem.getSkuId(), orderItem.getQuantity());
        }

        // 更新订单状态为已取消
        ProductOrderInfo updateOrder = new ProductOrderInfo();
        updateOrder.setOrderStatus(ProductOrderStatusEnum.CANCELLED.getCode());
        updateOrder.setCancelReason(cancelReason);
        int updateRows = productOrderInfoMapper.update(updateOrder,
                new LambdaQueryWrapper<ProductOrderInfo>()
                        .eq(ProductOrderInfo::getId, order.getId())
                        .eq(ProductOrderInfo::getOrderStatus, ProductOrderStatusEnum.WAIT_PAY.getCode()));
        if (updateRows == 0) {
            throw new ServiceException("订单状态已变更，取消失败");
        }
        log.info("订单状态更新为已取消，订单号：{}", order.getOrderNo());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirmReceipt(ProductOrderOperateDTO dto) {

        // 1. 获取当前登录用户（公共方法提取）
        WxLoginUser loginUser = getCurrentWxLoginUser();

        // 2. 查询并校验订单（公共方法提取）
        ProductOrderInfo productOrderInfo = getAndCheckOrder(dto.getOrderId(), loginUser.getCOpenid());

        // 3. 状态校验：必须是 待收货 才能确认收货
        if (!ProductOrderStatusEnum.WAIT_RECEIVE.getCode().equals(productOrderInfo.getOrderStatus())) {
            throw new ServiceException("订单状态异常，仅待收货状态可确认收货");
        }

        LocalDateTime now = LocalDateTime.now();

        // 4. 修改订单信息
        ProductOrderInfo updateInfo = new ProductOrderInfo();
        updateInfo.setId(productOrderInfo.getId());
        updateInfo.setOrderStatus(ProductOrderStatusEnum.RECEIVED.getCode());
        updateInfo.setReceiveTime(now);
        updateInfo.setUpdateTime(now);
        boolean orderUpdateResult = this.updateById(updateInfo);
        if (!orderUpdateResult) {
            throw new ServiceException("订单状态变更失败");
        }

        // 5. 修改售后单
        // 先查询是否存在符合条件的售后单
        LambdaQueryWrapper<AfterSaleOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AfterSaleOrder::getOrderId, productOrderInfo.getId())
                .eq(AfterSaleOrder::getOpenId, loginUser.getCOpenid())
                .ne(AfterSaleOrder::getAfterSaleStatus, AfterSaleStatusEnum.CANCELLED.getCode());
        
        List<AfterSaleOrder> afterSaleOrders = this.afterSaleOrderService.list(queryWrapper);
        log.info("订单{}的售后单列表：{}", productOrderInfo.getId(), afterSaleOrders);
        
        if (CollectionUtil.isEmpty(afterSaleOrders)) {
            log.warn("订单{}没有符合条件的售后单，跳过售后单状态更新", productOrderInfo.getId());
            // 没有售后单的情况，不抛出异常，直接返回
            return;
        }
        
        // 更新售后单状态
        LambdaUpdateWrapper<AfterSaleOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(AfterSaleOrder::getOrderId, productOrderInfo.getId())
                .eq(AfterSaleOrder::getOpenId, loginUser.getCOpenid())
                .ne(AfterSaleOrder::getAfterSaleStatus, AfterSaleStatusEnum.CANCELLED.getCode())
                .set(AfterSaleOrder::getAfterSaleStatus, AfterSaleStatusEnum.COMPLETED.getCode())
                .set(AfterSaleOrder::getUpdateTime, now);

        boolean afterSaleUpdateResult = this.afterSaleOrderService.update(updateWrapper);
        if (!afterSaleUpdateResult) {
            log.error("售后单状态变更失败，订单ID：{}，售后单列表：{}", productOrderInfo.getId(), afterSaleOrders);
            throw new ServiceException("售后单状态变更失败");
        }
        log.info("售后单状态更新成功，订单ID：{}", productOrderInfo.getId());

    }

    @Override
    public Page<ProductOrderPageItemVo> adminPage(Page<ProductOrderInfo> page, ProductOrderPageDTO dto) {
        return this.productOrderInfoMapper.adminPage(page, dto);
    }

    @Override
    public ProductOrderDetailAdminVo getOrderDetailForAdmin(Long orderId) {

        ProductOrderDetailAdminVo vo = new ProductOrderDetailAdminVo();

        // 1. 订单基础信息
        OrderBaseInfoVo orderBaseInfo = this.productOrderInfoMapper.getOrderBaseInfoById(orderId);
        if (ObjectUtil.isNull(orderBaseInfo)) {
            throw new ServiceException("订单不存在");
        }
        vo.setOrderBaseInfo(orderBaseInfo);

        // 2. 收货人信息
        ReceiverInfoVo receiverInfo = getReceiverInfo(orderBaseInfo);
        vo.setReceiverInfo(receiverInfo);

        // 3. 商品列表
        OrderItemVo itemVo = productOrderItemMapper.getOrderItemVoByOrderId(orderId);
        vo.setOrderItemInfo(itemVo);

        // 4. 售后信息
        OrderAfterSaleVo orderAfterSaleVo = this.afterSaleOrderService.getOrderAfterSaleVo(orderId);
        vo.setAfterSaleInfo(orderAfterSaleVo);

        return vo;
    }

    @Override
    public ProductOrderCountVo adminPageStats() {
        return this.productOrderInfoMapper.getOrderTotalCount();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editLogisticsNo(ProductOrderEditLogisticsNo dto) {

        // 查询并校验订单（公共方法提取）
        ProductOrderInfo productOrderInfo = getAndCheckOrder(dto.getOrderId(), null);

        productOrderInfo.setLogisticsNo(dto.getLogisticsNo());
        productOrderInfo.setUpdateTime(LocalDateTime.now());
        productOrderInfo.setOrderStatus(ProductOrderStatusEnum.WAIT_RECEIVE.getCode());

        this.productOrderInfoMapper.updateById(productOrderInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editConsigneesInfo(ProductOrderOperateDTO dto) {

        // 查询并校验订单（公共方法提取）
        ProductOrderInfo productOrderInfo = getAndCheckOrder(dto.getOrderId(), null);

        // 保证只有在待发货的状态才能修改
        if (ObjectUtil.notEqual(ProductOrderStatusEnum.WAIT_DELIVERY.getCode(), productOrderInfo.getOrderStatus())) {
            throw new ServiceException("订单状态不是待发货状态无权限操作");
        }

        BeanUtil.copyProperties(dto, productOrderInfo);
        productOrderInfo.setUpdateTime(LocalDateTime.now());

        this.productOrderInfoMapper.updateById(productOrderInfo);
    }

    /**
     * 获取当前微信登录的用户信息
     *
     * @return WxLoginUser
     */
    private WxLoginUser getCurrentWxLoginUser() {
        WxLoginUser loginUser = SecurityUtils.getWxLoginUser();
        if (ObjectUtil.isNull(loginUser)) {
            throw new ServiceException("用户未登录或登录已过期");
        }
        return loginUser;
    }

    @Override
    public ProductOrderInfo getAndCheckOrder(Long orderId, String openId) {
        LambdaQueryWrapper<ProductOrderInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProductOrderInfo::getId, orderId);

        if (StrUtil.isNotBlank(openId)) {
            queryWrapper.eq(ProductOrderInfo::getOpenId, openId);
        }

        // 订单是单条，直接用 selectOne 更合理
        ProductOrderInfo orderInfo = this.productOrderInfoMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNull(orderInfo)) {
            throw new ServiceException("订单不存在或无权限操作");
        }
        return orderInfo;
    }

    private ReceiverInfoVo getReceiverInfo(OrderBaseInfoVo vo) {
        ReceiverInfoVo receiverInfo = new ReceiverInfoVo();
        receiverInfo.setReceiverName(vo.getUserName());
        receiverInfo.setReceiverPhone(vo.getUserPhone());
        receiverInfo.setFullAddress(vo.getUserAddress());
        return receiverInfo;
    }

    /**
     * 处理微信支付回调（商品订单）
     * 参照服务订单支付成功逻辑，更新用户表、消费记录表
     *
     * @param orderNo 订单编号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleWxPayCallback(String orderNo) {
        log.info("商品订单微信支付回调开始处理，订单号：{}", orderNo);

        // 1. 查询未支付的商品订单
        LambdaQueryWrapper<ProductOrderInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProductOrderInfo::getOrderNo, orderNo)
                .eq(ProductOrderInfo::getOrderStatus, ProductOrderStatusEnum.WAIT_PAY.getCode());
        ProductOrderInfo orderInfo = productOrderInfoMapper.selectOne(queryWrapper);
        if (orderInfo == null) {
            log.error("商品订单 {} 不存在或已支付", orderNo);
            return;
        }

        // 2. 获取用户信息
        TWxUser user = wxUserService.getByOpenId(orderInfo.getOpenId());
        if (user == null) {
            log.error("商品订单对应的用户不存在，openId：{}", orderInfo.getOpenId());
            throw new ServiceException("用户不存在");
        }

        // 3. 更新用户金额及下单次数
        TWxUser paramUser = new TWxUser();
        paramUser.setId(user.getId());
        paramUser.setcOpenid(user.getcOpenid());
        paramUser.setdMoney(user.getdMoney().add(orderInfo.getTotalAmount()));
        paramUser.setnNum(user.getnNum() + MassageConstants.INTEGER_ONE);
        wxUserService.updateById(paramUser);

        // 4. 增加消费记录
        TConsumptionLog tConsumptionLog = new TConsumptionLog();
        tConsumptionLog.setAmount(orderInfo.getTotalAmount().negate());
        tConsumptionLog.setBillNo(orderInfo.getOrderNo());
        tConsumptionLog.setOpenId(orderInfo.getOpenId());
        tConsumptionLog.setBillType(BillTypeEnum.WX_PAY.getCode());
        tConsumptionLog.setNote("微信支付");
        consumptionLogService.save(tConsumptionLog);

        // 5. 更新商品订单状态：待发货，支付状态：已支付
        ProductOrderInfo updateOrder = new ProductOrderInfo();
        updateOrder.setId(orderInfo.getId());
        updateOrder.setOrderStatus(ProductOrderStatusEnum.WAIT_DELIVERY.getCode());
        updateOrder.setPayStatus(MassageConstants.INTEGER_ONE);
        updateOrder.setPayTime(LocalDateTime.now());
        updateById(updateOrder);
        log.info("商品订单微信支付回调处理完成，订单号：{}，订单状态更新为待发货，支付状态更新为已支付", orderNo);
    }

}