package com.yiqi.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yiqi.activity.domain.ActivityRechargeItem;
import com.yiqi.app.domain.AppUser;
import com.yiqi.app.service.IAppUserPointLogService;
import com.yiqi.app.service.IAppUserService;
import com.yiqi.common.exception.ServiceException;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yiqi.activity.service.IActivityRechargeItemService;
import com.yiqi.activity.service.impl.ActivityInfoServiceImpl;
import com.yiqi.app.domain.AppCouponItem;
import com.yiqi.app.service.IAppCouponItemService;
import com.yiqi.common.core.domain.R;
import com.yiqi.common.utils.CurrencyUtil;
import com.yiqi.common.utils.pay.PayCodeUtils;
import com.yiqi.delay.DelayQueueCache;
import com.yiqi.lock.RedisLockUtil;
import com.yiqi.order.domain.vo.*;
import com.yiqi.order.domain.vo.weapp.AppPayRespVO;
import com.yiqi.order.dto.RechargePackageInfo;
import com.yiqi.order.service.IOrderRechargeCouponRelationService;
import com.yiqi.app.service.IAppUserBillMstrService;
import com.yiqi.common.core.domain.AuthHolder;
import com.yiqi.common.enums.*;
import com.yiqi.common.exception.GlobalException;
import com.yiqi.common.utils.DateUtils;
import com.yiqi.common.utils.OrderNoUtils;
import com.yiqi.common.utils.SecurityUtils;
import com.yiqi.order.domain.*;
import com.yiqi.order.domain.dto.*;
import com.yiqi.order.mapper.OrderRechargeMapper;
import com.yiqi.order.service.*;
import com.yiqi.order.domain.OrderRechargeRefund;
import com.yiqi.recharge.domain.RechargePasswordCard;
import com.yiqi.recharge.domain.RechargeType;
import com.yiqi.recharge.domain.dto.BillMstrOrderDTO;
import com.yiqi.recharge.domain.dto.ConsumeOrderDTO;
import com.yiqi.order.service.IOrderRechargeRefundService;
import com.yiqi.recharge.service.IRechargeCardBatchRecordService;
import com.yiqi.recharge.service.IRechargePasswordCardService;
import com.yiqi.recharge.service.IRechargeTypeService;
import com.yiqi.system.domain.SysStore;
import com.yiqi.system.service.ISysStoreService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 充值订单Service业务层处理
 *
 * @author ruoyi
 * @date 2023-09-27
 */
@Service
public class OrderRechargeServiceImpl extends ServiceImpl<OrderRechargeMapper, OrderRecharge> implements IOrderRechargeService {
    @Autowired
    private OrderNoUtils orderNoUtils;
    @Autowired
    IOrderRechargeInstalmentService orderRechargeInstalmentService;
    @Autowired
    IRechargePasswordCardService rechargePasswordCardService;
    @Autowired
    IRechargeCardBatchRecordService rechargeCardBatchRecordService;
    @Autowired
    IRechargeTypeService rechargeTypeService;
    @Autowired
    private IAppUserService appUserService;
    @Autowired
    private RedisLockUtil redisLockUtil;

    @Autowired
    private ISysStoreService sysStoreService;

    @Autowired
    private IAppUserBillMstrService appUserBillMstrService;
    @Autowired
    private IAppCouponItemService appCouponItemService;
    @Autowired
    private IPayService payService;
    @Autowired
    private DelayQueueCache delayQueueCache;
    @Autowired
    private IOrderPayInfoService orderPayInfoService;
    @Autowired
    private ActivityInfoServiceImpl activityInfoService;
    @Autowired
    private IActivityRechargeItemService activityRechargeItemService;
    @Autowired
    private IOrderRechargeCouponRelationService orderRechargeCouponRelationService;

    private static final Logger log = LoggerFactory.getLogger(OrderRechargeServiceImpl.class);
    @Autowired
    private IOrderRechargeRefundService orderRechargeRefundService;
    @Autowired
    private IAppUserBillMstrService billMstrOrderService;
    @Autowired
    private IAppUserPointLogService appUserPointLogService;

    /**
     * 查询充值订单
     *
     * @param id 充值订单主键
     * @return 充值订单
     */
    @Override
    public OrderRecharge selectOrderRechargeById(Long id) {
        OrderRecharge orderRecharge = baseMapper.selectOrderRechargeById(id);
        AppUser appUser = appUserService.selectAppUserById(orderRecharge.getAppUserId());
        if (appUser != null) {
            orderRecharge.setAppUserName(appUser.getNickName());
            orderRecharge.setAppUserPhone(appUser.getPhoneNumber());
        }
        SysStore sysStore = sysStoreService.getById(orderRecharge.getStoreId());
        if (sysStore != null) {
            orderRecharge.setStoreName(sysStore.getName());
        }
        if (!orderRecharge.getOrderStatus().equals("0")) {
            RechargePasswordCard rechargePasswordCard = rechargePasswordCardService.selectRechargePasswordCardByOrderNo(orderRecharge.getOrderNo());
            orderRecharge.setRechargePasswordCard(rechargePasswordCard);
        }
        List<OrderRechargeInstalment> orderRechargeInstalments = getPayDetailById(id, null);
        orderRecharge.setOrderRechargeInstalments(orderRechargeInstalments);
        return orderRecharge;
    }

    @Override
    public List<OrderRechargeRefundListVO> refundRechargeOrderList(OrderRechargeRefundQueryDTO orderRechargeRefundQueryDTO) {
        if (!SecurityUtils.getLoginUser().getSourceType().equals(SourceType.MANAGER.getCode())) {
            orderRechargeRefundQueryDTO.setSourceType(SecurityUtils.getLoginUser().getSourceType());
        }
        if (StrUtil.isEmpty(String.valueOf(orderRechargeRefundQueryDTO.getOrgId()))) {
            orderRechargeRefundQueryDTO.setOrgId(SecurityUtils.getLoginUser().getOrgId());
        } else {
            orderRechargeRefundQueryDTO.setOrgId(orderRechargeRefundQueryDTO.getOrgId());
        }
        return baseMapper.refundRechargeOrderList(orderRechargeRefundQueryDTO);
    }

    /**
     * 查询充值订单列表
     *
     * @param orderRechargeQueryDTO 充值订单
     * @return 充值订单
     */
    @Override
    public List<OrderRechargeListVO> selectOrderRechargeList(OrderRechargeQueryDTO orderRechargeQueryDTO) {
        if (StrUtil.isEmpty(String.valueOf(orderRechargeQueryDTO.getOrgId()))) {
            orderRechargeQueryDTO.setOrgId(SecurityUtils.getLoginUser().getOrgId());
        } else {
            orderRechargeQueryDTO.setOrgId(orderRechargeQueryDTO.getOrgId());
        }
        return baseMapper.selectOrderRechargeList(orderRechargeQueryDTO);
    }

    /**
     * 查询充值订单列表
     *
     * @param orderRechargeListVO 充值订单
     * @return 充值订单
     */
    @Override
    public List<OrderRechargeListVO> selectRefundList(OrderRechargeListVO orderRechargeListVO) {
        return baseMapper.selectRefundList(orderRechargeListVO);
    }

    /**
     * 修改充值订单
     *
     * @param orderRecharge 充值订单
     * @return 结果
     */
    @Override
    public int updateOrderRecharge(OrderRecharge orderRecharge) {
        orderRecharge.setUpdateTime(DateUtils.getNowDate());
        return baseMapper.updateById(orderRecharge);
    }

    /**
     * 拒绝退卡
     *
     * @param orderRechargeRefund 退卡
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int refundRechargeNo(OrderRechargeRefund orderRechargeRefund) {
        orderRechargeRefund.setRefundStatus(RechargeRefundStatusType.REFUND_REFUSE.getCode());

        OrderRecharge orderRecharge = this.getOne(new QueryWrapper<OrderRecharge>().lambda().eq(OrderRecharge::getOrderNo, orderRechargeRefund.getOrderNo()));
        if (orderRecharge == null) {
            throw new GlobalException("充值订单不存在");
        }
        RechargePasswordCard rechargePasswordCard = rechargePasswordCardService.getOne(new QueryWrapper<RechargePasswordCard>().lambda()
                .eq(RechargePasswordCard::getOrderNo, orderRecharge.getOrderNo())
                .eq(RechargePasswordCard::getDelFlag, DeleteStatus.OK.getCode()), Boolean.FALSE);
        if (rechargePasswordCard == null) {
            log.info("充值订单{}" + orderRechargeRefund.getOrderNo() + "操作退款，未找到该笔订单对应的充值卡记录");
            throw new GlobalException("未找到该笔订单对应的充值卡记录");
        }
        rechargePasswordCard.setRechargeStatus(RechargeStatusType.HAS_USE.getCode());
        rechargePasswordCard.buildUpdateData();
        rechargePasswordCardService.updateById(rechargePasswordCard);

        orderRecharge.setUpdateTime(DateUtils.getNowDate());

        orderRecharge.setRefundStatus(RechargeRefundStatusType.REFUND_REFUSE.getCode());
        orderRecharge.buildUpdateData();
        baseMapper.updateById(orderRecharge);

        orderRechargeRefundService.updateById(orderRechargeRefund);

        return 1;
    }

    /**
     * 同意退卡审核
     *
     * @param orderRechargeRefund 退卡申请信息
     * @return 处理结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int refundRechargeYes(OrderRechargeRefund orderRechargeRefund) {
        // 1. 幂等性控制
        String lockKey = String.format("recharge:refund:approve:%s", orderRechargeRefund.getOrderNo());
        if (!redisLockUtil.tryLock(lockKey)) {
            throw new ServiceException("退款审核处理中,请勿重复提交");
        }

        try {
            // 2. 校验订单和充值卡信息
            OrderRecharge orderRecharge = validateRefundOrder(orderRechargeRefund.getOrderNo());
            RechargePasswordCard rechargeCard = validateRechargeCard(orderRecharge.getOrderNo());

            // 3. 处理现金退款
            if (PayType.CASH.getCode().equals(orderRechargeRefund.getRefundType()) || PayType.RECHARGE_CARD.getCode().equals(orderRechargeRefund.getRefundType())) {
                refundSuccess(orderRechargeRefund.getOrderNo());
                return 1;
            } else {
                // 4. 更新退款申请状态
                updateRefundStatus(orderRechargeRefund, orderRecharge, rechargeCard);

                // 5. 发起第三方退款
                // 1. 构建退款请求
                PayRefundDTO refundDTO = buildRefundRequest(orderRechargeRefund, orderRecharge);

                // 2. 发起退款
                RefundResponseDTO response = payService.refundApply(refundDTO);
                if (PayResult.fail.getCode() == (response.getRefundResult())) {
                    // 退款失败
                    refundError(refundDTO.getOrderNo());
                }
            }
            return 1;
        } catch (Exception e) {
            log.error("退款审核处理失败, orderNo={}, error={}",
                    orderRechargeRefund.getOrderNo(), e.getMessage());
            throw new ServiceException("退款审核处理失败:" + e.getMessage());
        } finally {
            redisLockUtil.unlock(lockKey);
        }
    }

    /**
     * 校验退款订单
     */
    private OrderRecharge validateRefundOrder(String orderNo) {
        OrderRecharge orderRecharge = getOne(new QueryWrapper<OrderRecharge>()
                .lambda()
                .eq(OrderRecharge::getOrderNo, orderNo));

        if (orderRecharge == null) {
            throw new ServiceException("充值订单不存在");
        }

        // 校验订单状态
        if (!OrderRechargeStatus.YES_PAY.getCode().equals(orderRecharge.getOrderStatus())) {
            throw new ServiceException("订单状态异常,不能退款");
        }

        return orderRecharge;
    }

    /**
     * 校验充值卡
     */
    private RechargePasswordCard validateRechargeCard(String orderNo) {
        RechargePasswordCard card = rechargePasswordCardService.getOne(
                new QueryWrapper<RechargePasswordCard>()
                        .lambda()
                        .eq(RechargePasswordCard::getOrderNo, orderNo)
                        .eq(RechargePasswordCard::getDelFlag, DeleteStatus.OK.getCode()));

        if (card == null) {
            throw new ServiceException("未找到该笔订单对应的充值卡记录");
        }

        return card;
    }

    /**
     * 更新退款状态
     */
    private void updateRefundStatus(OrderRechargeRefund refundOrder,
                                    OrderRecharge orderRecharge,
                                    RechargePasswordCard card) {
        Date now = DateUtils.getNowDate();

        // 2. 更新订单状态
        orderRecharge.setUpdateTime(now);
        orderRecharge.setRefundStatus(OrderRefundStatus.REFUNDING.getCode());
        orderRecharge.buildUpdateData();
        updateById(orderRecharge);

        // 3. 更新退款申请状态
        refundOrder.setRefundStatus(RechargeRefundStatusType.REFUNDING.getCode());
        refundOrder.setUpdateTime(now);
        refundOrder.setRefundTime(now);
        refundOrder.setRemark("退卡审核同意");
        orderRechargeRefundService.updateById(refundOrder);
    }

    /**
     * 处理现金退款
     */
    private int handleCashRefund(OrderRechargeRefund refundOrder,
                                 OrderRecharge orderRecharge,
                                 RechargePasswordCard card) {
        // 1. 更新充值卡状态
        card.setRechargeStatus(RechargeStatusType.REFUND.getCode());
        rechargePasswordCardService.updateById(card);

        // 2. 更新订单状态
        orderRecharge.setRefundStatus(RechargeRefundStatusType.REFUND_SUCCESS.getCode());
        updateById(orderRecharge);

        // 3. 更新退款申请状态
        refundOrder.setRefundStatus(RechargeRefundStatusType.REFUND_SUCCESS.getCode());
        orderRechargeRefundService.updateById(refundOrder);

        return 1;
    }

    /**
     * 构建退款请求
     */
    private PayRefundDTO buildRefundRequest(OrderRechargeRefund refundOrder,
                                            OrderRecharge orderRecharge) {
        PayRefundDTO refundDTO = new PayRefundDTO();

        // 设置退款基本信息
        refundDTO.setOrderNo(refundOrder.getOrderNo());
        refundDTO.setOutRequestNo(refundOrder.getRefundNo());
        refundDTO.setOutTradeNo(orderRecharge.getOutTradeOrderNo());
        refundDTO.setRefundReason(refundOrder.getRefundReason());
        refundDTO.setStoreId(orderRecharge.getStoreId());

        // 设置退款金额信息
        refundDTO.setTotalAmount(orderRecharge.getPayAmount());
        if (refundOrder.getAliRefundAmount().compareTo(BigDecimal.ZERO) > 0) {
            refundDTO.setPayType(PayType.ALIPAY.getCode());
            refundDTO.setRefundAmount(refundOrder.getAliRefundAmount());
        } else if (refundOrder.getWxRefundAmount().compareTo(BigDecimal.ZERO) > 0) {
            refundDTO.setPayType(PayType.WECHAT.getCode());
            refundDTO.setRefundAmount(refundOrder.getWxRefundAmount());
        }

        return refundDTO;
    }


    /**
     * 批量删除充值订单
     *
     * @param ids 需要删除的充值订单主键
     * @return 结果
     */
    @Override
    public int deleteOrderRechargeByIds(Long[] ids) {
        return baseMapper.deleteOrderRechargeByIds(ids);
    }

    /**
     * 删除充值订单信息
     *
     * @param id 充值订单主键
     * @return 结果
     */
    @Override
    public int deleteOrderRechargeById(Long id) {
        return baseMapper.deleteOrderRechargeById(id);
    }

    @Override
    public List<OrderRechargeInstalment> getPayDetailById(Long orderId, String orderStatus) {
        return baseMapper.getPayDetailById(orderId, orderStatus);
    }

    /**
     * 创建充值订单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderPayResultVO createRechargeOrder(OrderRechargeCreateDTO createDTO) {
        //卡密充值
        if(StringUtils.isNotEmpty(createDTO.getCardNo()) && StringUtils.isNotEmpty(createDTO.getPassword())){
            OrderRechargeCreateDTO orderRechargeCreateDTO = new OrderRechargeCreateDTO();
            orderRechargeCreateDTO.setOrderSource(OrderSourceType.OFFLINE.getCode());
            orderRechargeCreateDTO.setCardNo(createDTO.getCardNo());
            orderRechargeCreateDTO.setPassword(createDTO.getPassword());
            orderRechargeCreateDTO.setRechargeType(RechargeTypeEnum.CARD.getCode());
            orderRechargeCreateDTO.setAppUserId(createDTO.getAppUserId());
            orderRechargeCreateDTO.setOrgId(createDTO.getOrgId());
            OrderPayResultVO orderPayResultVO = insertOrderRechargeByPasscard(orderRechargeCreateDTO);
            return orderPayResultVO;
        }
        // 1. 校验参数
        if (StringUtils.isEmpty(createDTO.getPayType())) {
            throw new ServiceException("请选择支付方式");
        }
        // 2. 获取充值套餐信息
        RechargePackageInfo packageInfo = getRechargePackageInfo(createDTO.getRechargeTypeId(), createDTO.getOrgId());

        // 3. 创建订单
        OrderRecharge orderRecharge = buildOrderRecharge(createDTO, packageInfo);

        // 4. 处理支付
        return handleRechargePayment(orderRecharge, createDTO);
    }

    /**
     * 获取充值套餐信息(包含活动)
     */
    private RechargePackageInfo getRechargePackageInfo(Long rechargeTypeId, Long orgId) {
        if (rechargeTypeId == null) {
            return null;
        }
        // 1. 获取套餐基本信息
        RechargeType rechargeType = rechargeTypeService.getById(rechargeTypeId);
        if (rechargeType == null) {
            throw new ServiceException("未查询到该充值套餐");
        }

        // 2. 获取套餐活动信息
        ActivityRechargeItem activityItem = activityRechargeItemService
                .getGiveAmountByActivity(rechargeTypeId, orgId);

        return RechargePackageInfo.builder()
                .rechargeType(rechargeType)
                .activityItem(activityItem)
                .build();
    }

    /**
     * 构建充值订单
     */
    private OrderRecharge buildOrderRecharge(OrderRechargeCreateDTO createDTO,
                                             RechargePackageInfo packageInfo) {

        OrderRecharge orderRecharge = new OrderRecharge();

        // 1. 设置基本信息
        orderRecharge.setOrderNo(orderNoUtils.getRechargeOrderNo());
        orderRecharge.setSourceType(SourceType.STORE.getCode());
        orderRecharge.setAppUserId(createDTO.getAppUserId());
        orderRecharge.setRechargeType(createDTO.getRechargeType());
        orderRecharge.setRechargeTypeId(createDTO.getRechargeTypeId());
        orderRecharge.setOrderSource(createDTO.getOrderSource());
        orderRecharge.setStoreId(createDTO.getOrgId());
        orderRecharge.setRemark(createDTO.getRemark());
        orderRecharge.setRefundAmount(BigDecimal.ZERO);

        orderRecharge.setPayType(createDTO.getPayType());
        // 2. 设置支付信息
        if (createDTO.getPayType().equals(PayType.WECHAT.getCode()) || createDTO.getPayType().equals(PayType.ALIPAY.getCode())) {
            String payType = PayCodeUtils.getPayTypeByCode(createDTO.getAuthCode());
            orderRecharge.setPayType(payType);
        }
        orderRecharge.setOrderStatus(OrderRechargeStatus.NO_PAY.getCode());
        orderRecharge.setPayStatus(PayStatus.WAITING_TO_PAY.getCode());

        // 3. 设置金额信息
        if (packageInfo == null) {
            //如果套餐为空，则是直接充值
            orderRecharge.setPayAmount(createDTO.getPayAmount());
            orderRecharge.setRechargeAmount(createDTO.getRechargeAmount());
            orderRecharge.setGiveAmount(BigDecimal.ZERO);
            orderRecharge.setGivePointAmount(0);
            orderRecharge.setWelfareAmount(createDTO.getWelfareAmount());
        } else {
            RechargeType rechargeType = packageInfo.getRechargeType();
            orderRecharge.setPayAmount(rechargeType.getRechargeAmount());
            orderRecharge.setRechargeAmount(rechargeType.getRechargeAmount());
            orderRecharge.setWelfareAmount(BigDecimal.ZERO);

            // 4. 设置赠送信息
            if (packageInfo.getActivityItem() != null) {
                // 如果有活动,使用活动的赠送金额
                orderRecharge.setGiveAmount(packageInfo.getActivityItem().getActivityGiveAmount());
                orderRecharge.setActivityId(packageInfo.getActivityItem().getActivityId());
            } else {
                orderRecharge.setGiveAmount(rechargeType.getGiveAmount());
            }
            orderRecharge.setGivePointAmount(rechargeType.getGivePointAmount());
        }
        // 5. 设置支付渠道金额
        initializePayChannelAmount(orderRecharge, createDTO);
        orderRecharge.setDelFlag(DeleteStatus.OK.getCode());
        orderRecharge.buildCreateData();
        save(orderRecharge);
        return orderRecharge;
    }

    /**
     * 初始化支付渠道金额
     */
    private void initializePayChannelAmount(OrderRecharge orderRecharge, OrderRechargeCreateDTO createDTO) {
        orderRecharge.setCashPayAmount(BigDecimal.ZERO);
        orderRecharge.setAliPayAmount(BigDecimal.ZERO);
        orderRecharge.setWxPayAmount(BigDecimal.ZERO);
        switch (PayType.getPayType(orderRecharge.getPayType())) {
            case WECHAT:
                orderRecharge.setWxPayAmount(orderRecharge.getPayAmount());
                break;
            case ALIPAY:
                orderRecharge.setAliPayAmount(orderRecharge.getPayAmount());
                break;
            case CASH:
                orderRecharge.setCashPayAmount(orderRecharge.getPayAmount());
                break;
            case COMBINE:
                //组合支付
                orderRecharge.setCashPayAmount(createDTO.getCashPayAmount());
                String payType = PayCodeUtils.getPayTypeByCode(createDTO.getAuthCode());
                if (payType.equals(PayType.WECHAT.getCode())) {
                    orderRecharge.setWxPayAmount(CurrencyUtil.sub(createDTO.getPayAmount(), createDTO.getCashPayAmount()));
                }
                if (payType.equals(PayType.ALIPAY.getCode())) {
                    orderRecharge.setAliPayAmount(CurrencyUtil.sub(createDTO.getPayAmount(), createDTO.getCashPayAmount()));
                }
                break;
        }
    }

    /**
     * 处理充值支付
     */
    private OrderPayResultVO handleRechargePayment(OrderRecharge orderRecharge, OrderRechargeCreateDTO createDTO) {
        OrderPayResultVO resultVO = new OrderPayResultVO();
        resultVO.setOrderId(orderRecharge.getId());
        resultVO.setOrderNo(orderRecharge.getOrderNo());
        // 1. 现金支付直接完成
        if (PayType.CASH.getCode().equals(createDTO.getPayType())) {
            paySuccess(orderRecharge, null);
            resultVO.setPayResult(200);
            resultVO.setPayMsg("支付成功");
            return resultVO;
        }

        // 2. APP支付
        if (OrderSourceType.APP.getCode().equals(createDTO.getOrderSource())) {
            PayOrderAppDTO payDTO = PayOrderAppDTO.buildRechargeOrderPayData(
                    orderRecharge,
                    createDTO.getPlatform()
            );
            AppPayRespVO appPayRespVO = payService.appPay(payDTO);
            resultVO.setPayResult(0);
            resultVO.setAppPayRespVO(appPayRespVO);
            return resultVO;
        }

        // 3. 线下支付(微信/支付宝)
        if (OrderSourceType.OFFLINE.getCode().equals(createDTO.getOrderSource())) {
            // 2. 发起支付
            if (orderRecharge.getPayType().equals(PayType.COMBINE.getCode())) {
                //如果是组合支付
                String payType = PayCodeUtils.getPayTypeByCode(createDTO.getAuthCode());
                orderRecharge.setPayType(payType);
                if (payType.equals(PayType.WECHAT.getCode())) {
                    orderRecharge.setPayAmount(orderRecharge.getWxPayAmount());
                }
                if (payType.equals(PayType.ALIPAY.getCode())) {
                    orderRecharge.setPayAmount(orderRecharge.getAliPayAmount());
                }
            }
            return payService.faceToFacePay(
                    PayOrderFaceToFaceDTO.createRechargeOrderPayData(
                            orderRecharge.getOrderNo(),
                            orderRecharge.getPayAmount(),
                            orderRecharge.getPayType(),
                            createDTO.getAuthCode()
                    )
            );
        }
        return resultVO;
    }


    /**
     * 卡密充值处理
     *
     * @param orderRechargeCreateDTO 充值请求参数
     * @return 支付结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderPayResultVO insertOrderRechargeByPasscard(OrderRechargeCreateDTO orderRechargeCreateDTO) {
        // 1. 参数校验
        if (StringUtils.isEmpty(orderRechargeCreateDTO.getCardNo())) {
            throw new ServiceException("充值卡号不能为空");
        }
        if (StringUtils.isEmpty(orderRechargeCreateDTO.getPassword())) {
            throw new ServiceException("充值卡密码不能为空");
        }
        if (orderRechargeCreateDTO.getAppUserId() == null) {
            throw new ServiceException("用户ID不能为空");
        }

        // 2. 获取并校验充值卡
        RechargePasswordCard rechargeCard = getAndValidateRechargeCard(
                orderRechargeCreateDTO.getCardNo(),
                orderRechargeCreateDTO.getPassword()
        );

        //如果是线下门店开卡，要判断线下门店跟绑定门店是否一致
        if(OrderSourceType.OFFLINE.getCode().equals(orderRechargeCreateDTO.getOrderSource())){
            if (rechargeCard.getRechargeStoreId() != null &&
                    !rechargeCard.getRechargeStoreId().equals(orderRechargeCreateDTO.getOrgId())) {
                throw new ServiceException("充值卡与门店不匹配");
            }
        }
        try {
            // 3. 创建充值订单
            OrderRecharge orderRecharge = createRechargeOrder(rechargeCard, orderRechargeCreateDTO);

            // 4. 更新充值卡状态
            updateRechargeCardStatus(rechargeCard, orderRecharge);

            // 添加用户积分
            appUserPointLogService.addPoint(orderRecharge.getAppUserId(), orderRecharge.getGivePointAmount().intValue(), orderRecharge.getOrderNo(), MemberPointSourceEnum.RECHARGEADD, "会员储值赠送");

            // 5. 记录账单流水
            createBillRecord(orderRecharge, rechargeCard);

            // 6. 返回支付结果
            return buildPayResult(orderRecharge);

        } catch (Exception e) {
            log.error("卡密充值处理异常, cardNo={}, error={}",
                    orderRechargeCreateDTO.getCardNo(), e.getMessage());
            throw new ServiceException("充值处理失败:" + e.getMessage());
        }
    }

    /**
     * 获取并校验充值卡
     */
    private RechargePasswordCard getAndValidateRechargeCard(String cardNo, String password) {
        RechargePasswordCard card = rechargePasswordCardService.getOne(
                new QueryWrapper<RechargePasswordCard>()
                        .lambda()
                        .eq(RechargePasswordCard::getCardNo, cardNo)
                        .eq(RechargePasswordCard::getPassword, password)
                        .eq(RechargePasswordCard::getDelFlag, DeleteStatus.OK.getCode())
        );

        if (card == null) {
            throw new ServiceException("无效的充值卡,请检查卡号和密码是否正确");
        }
        if (!card.getRechargeStatus().equals(RechargeStatusType.NOT_UES.getCode())) {
            throw new ServiceException("充值卡状态异常，请联系客服");
        }

        // 校验卡是否过期
        if (card.getExpireTime() != null &&
                card.getExpireTime().before(DateUtils.getNowDate())) {
            throw new ServiceException("充值卡已过期");
        }


        return card;
    }

    /**
     * 创建充值订单
     */
    private OrderRecharge createRechargeOrder(RechargePasswordCard card,
                                              OrderRechargeCreateDTO dto) {

        OrderRecharge orderRecharge = new OrderRecharge();

        // 设置订单基本信息
        orderRecharge.setOrderNo(orderNoUtils.getRechargeOrderNo());
        orderRecharge.setAppUserId(dto.getAppUserId());
        orderRecharge.setRechargeType(dto.getRechargeType());
        orderRecharge.setOrderSource(dto.getOrderSource());
        orderRecharge.setStoreId(card.getRechargeStoreId());
        orderRecharge.setSourceType(SourceType.STORE.getCode());
        orderRecharge.setDelFlag(DeleteStatus.OK.getCode());
        orderRecharge.buildCreateData();

        // 设置支付相关信息
        orderRecharge.setPayTime(DateUtils.getNowDate());
        orderRecharge.setPayType(PayType.RECHARGE_CARD.getCode());
        orderRecharge.setPayStatus(PayStatus.HAS_PAY.getCode());
        orderRecharge.setOrderStatus(OrderRechargeStatus.YES_PAY.getCode());
        orderRecharge.setRefundStatus(OrderRefundStatus.OK.getCode());
        orderRecharge.setRefundAmount(BigDecimal.ZERO);
        orderRecharge.setRechargeCardNo(card.getCardNo());

        // 设置金额信息
        orderRecharge.setPayAmount(card.getRechargeAmount());
        orderRecharge.setRechargeAmount(card.getRechargeAmount());
        orderRecharge.setGiveAmount(card.getGiveAmount());
        orderRecharge.setWelfareAmount(card.getWelfareAmount());
        orderRecharge.setGivePointAmount(card.getGivePointAmount());
        orderRecharge.setCouponDeductAmount(BigDecimal.ZERO);

        // 设置支付渠道金额
        orderRecharge.setCashPayAmount(card.getRechargeAmount());
        orderRecharge.setWxPayAmount(BigDecimal.ZERO);
        orderRecharge.setAliPayAmount(BigDecimal.ZERO);

        save(orderRecharge);
        return orderRecharge;
    }

    /**
     * 更新充值卡状态
     */
    private void updateRechargeCardStatus(RechargePasswordCard card, OrderRecharge order) {
        card.setRechargeUserId(order.getAppUserId());
        card.setRechargeTime(DateUtils.getNowDate());
        card.setRechargeStatus(RechargeStatusType.HAS_USE.getCode());
        card.setUseBindStoreId(order.getStoreId());
        card.setOrderNo(order.getOrderNo());
        card.setUpdateTime(DateUtils.getNowDate());
        card.setUpdateBy(AuthHolder.userName());
        card.setUpdateById(AuthHolder.userId());

        rechargePasswordCardService.updateById(card);
    }

    /**
     * 创建账单记录
     */
    private void createBillRecord(OrderRecharge order, RechargePasswordCard card) {
        BillMstrOrderDTO billDTO = new BillMstrOrderDTO();

        // 设置账单基本信息
        billDTO.setAppUserId(order.getAppUserId());
        billDTO.setOrgId(order.getStoreId());
        billDTO.setSourceType(order.getSourceType());
        billDTO.setOrderNo(order.getOrderNo());
        billDTO.setOrderType(OrderType.recharge.getCode());
        billDTO.setUseBindStoreId(card.getUseBindStoreId());

        // 设置账单金额信息
        billDTO.setRechargePayAmount(order.getRechargeAmount());
        billDTO.setWelfarePayAmount(order.getWelfareAmount());
        billDTO.setGivePayAmount(order.getGiveAmount());
        billDTO.setRechargeCardNo(order.getRechargeCardNo());

        // 计算总金额
        BigDecimal totalAmount = CurrencyUtil.add(
                order.getRechargeAmount(),
                order.getGiveAmount(),
                order.getWelfareAmount()
        );
        billDTO.setPayTotalAmount(totalAmount);

        // 设置备注
        billDTO.setRemark(String.format("充值卡：%s卡密激活，到账%s元",
                card.getCardNo(),
                totalAmount.toString())
        );

        billMstrOrderService.saveBillMstrOrder(billDTO);
    }

    /**
     * 构建支付结果
     */
    private OrderPayResultVO buildPayResult(OrderRecharge orderRecharge) {
        OrderPayResultVO resultVO = new OrderPayResultVO();
        resultVO.setIsAllPayEnd(Boolean.TRUE);
        resultVO.setOrderNo(orderRecharge.getOrderNo());
        return resultVO;
    }

    @Override
    public void paySuccess(OrderRecharge orderRecharge, String outTradeNo) {
        if (orderRecharge.getPayStatus().equals(PayStatus.HAS_PAY.getCode())) {
            log.error("订单已支付成功，无需再次处理，订单号：{}", orderRecharge.getOrderNo());
            return;
        }
        Date date = DateUtils.getNowDate();


        // 同步生成密码卡
        RechargePasswordCard rechargePasswordCard = buildRechargePasswordCardData(orderRecharge);
        orderRecharge.setRechargeCardNo(rechargePasswordCard.getCardNo());
        //  更新订单信息
        updateOrderStatusAndPayTime(orderRecharge, outTradeNo, date);

        // 添加用户积分
        appUserPointLogService.addPoint(orderRecharge.getAppUserId(), orderRecharge.getGivePointAmount().intValue(), orderRecharge.getOrderNo(), MemberPointSourceEnum.RECHARGEADD, "会员储值赠送");

        // 保存日志
        saveBillMstrOrder(orderRecharge, rechargePasswordCard, date);
        log.info("本充值订单已全部支付完，订单号：{}, 支付金额：{}", orderRecharge.getOrderNo(), orderRecharge.getPayAmount());
    }

    private void updateOrderStatusAndPayTime(OrderRecharge orderRecharge, String outTradeNo, Date payTime) {
        orderRecharge.setOutTradeOrderNo(outTradeNo);
        orderRecharge.setOrderStatus(OrderRechargeStatus.YES_PAY.getCode());
        orderRecharge.setPayTime(payTime);
        orderRecharge.setPayStatus(PayStatus.HAS_PAY.getCode());
        try {
            this.updateById(orderRecharge);
        } catch (Exception e) {
            log.error("更新订单状态和支付时间失败，订单号：{}", orderRecharge.getOrderNo(), e);
            throw new ServiceException("更新订单状态和支付时间失败");
        }
    }

    private void saveBillMstrOrder(OrderRecharge orderRecharge, RechargePasswordCard rechargePasswordCard, Date date) {
        BillMstrOrderDTO billMstrOrderDTO = new BillMstrOrderDTO();
        billMstrOrderDTO.setAppUserId(orderRecharge.getAppUserId());
        billMstrOrderDTO.setSourceType(orderRecharge.getSourceType());
        billMstrOrderDTO.setOrgId(orderRecharge.getStoreId());
        billMstrOrderDTO.setOrderId(orderRecharge.getId());
        billMstrOrderDTO.setOrderNo(orderRecharge.getOrderNo());
        billMstrOrderDTO.setOrderType(OrderType.recharge.getCode());
        billMstrOrderDTO.setRechargePayAmount(orderRecharge.getRechargeAmount());
        billMstrOrderDTO.setUseBindStoreId(rechargePasswordCard.getUseBindStoreId());
        billMstrOrderDTO.setWelfarePayAmount(orderRecharge.getWelfareAmount());
        billMstrOrderDTO.setGivePayAmount(orderRecharge.getGiveAmount());
        billMstrOrderDTO.setRechargeCardNo(orderRecharge.getRechargeCardNo());
        billMstrOrderDTO.setPayType(orderRecharge.getPayType());
        billMstrOrderDTO.setRechargeCardNo(orderRecharge.getRechargeCardNo());
        BigDecimal totalPayAmount = CurrencyUtil.add(orderRecharge.getRechargeAmount(), orderRecharge.getGiveAmount(), orderRecharge.getWelfareAmount());
        billMstrOrderDTO.setPayTotalAmount(totalPayAmount);
        billMstrOrderDTO.setRemark("充值卡：" + rechargePasswordCard.getCardNo() + "，储值到账" + totalPayAmount + "元");
        try {
            billMstrOrderService.saveBillMstrOrder(billMstrOrderDTO);
        } catch (Exception e) {
            log.error("保存消费日志失败，订单号：{}", orderRecharge.getOrderNo(), e);
            throw new ServiceException("保存消费日志失败");
        }
    }

    /**
     * 充值订单 处理优惠券使用情况
     *
     * @param orderRecharge
     * @param couponIds
     */
    private void handleOrderCoupon(OrderRecharge orderRecharge, List<Long> couponIds) {
        if (couponIds == null || couponIds.size() == 0) {
            log.debug("优惠券为空，不做处理");
            return;
        }
        Map<Long, AppCouponItem> appCouponItemMap = appCouponItemService.list(new QueryWrapper<AppCouponItem>().lambda()
                        .eq(AppCouponItem::getAppUserId, orderRecharge.getAppUserId())
                        .eq(AppCouponItem::getIsUsed, SysBoolType.NO.getCode())
                        .in(AppCouponItem::getId, couponIds))
                .stream().collect(Collectors.toMap(AppCouponItem::getId, AppCouponItem -> AppCouponItem));
        if (CollUtil.isEmpty(appCouponItemMap)) {
            throw new ServiceException("未能查询到可用于抵用充值的优惠券");
        }
        if (appCouponItemMap.size() != couponIds.size()) {
            throw new ServiceException("存在不可用优惠券，请检查后再操作");
        }
        BigDecimal deductRechargeAmount = BigDecimal.ZERO;
        List<OrderRechargeCouponRelation> orderRechargeCouponRelations = new ArrayList<>();
        for (Long couponId : couponIds) {
            OrderRechargeCouponRelation orderRechargeCouponRelation = new OrderRechargeCouponRelation();
            orderRechargeCouponRelation.setOrderId(orderRecharge.getId());
            orderRechargeCouponRelation.setOrderNo(orderRecharge.getOrderNo());
            orderRechargeCouponRelation.setCouponItemId(couponId);
            orderRechargeCouponRelation.setDeductAmount(BigDecimal.ZERO);
            orderRechargeCouponRelation.buildCreateData();
            orderRechargeCouponRelations.add(orderRechargeCouponRelation);

            deductRechargeAmount = deductRechargeAmount.add(BigDecimal.ZERO);
        }
        orderRechargeCouponRelationService.saveBatch(orderRechargeCouponRelations);

        orderRecharge.setCouponDeductAmount(deductRechargeAmount);
        orderRecharge.setPayAmount
                (
                        orderRecharge.getPayAmount().subtract(deductRechargeAmount).compareTo(BigDecimal.ZERO) < 0
                                ? BigDecimal.ZERO : orderRecharge.getPayAmount().subtract(deductRechargeAmount)
                );

        //优惠券使用完后，将优惠券修改为已使用状态
        appCouponItemService.update(new UpdateWrapper<AppCouponItem>()
                .lambda().set(AppCouponItem::getIsUsed, SysBoolType.YES.getCode())
                .set(AppCouponItem::getUsedStoreId, SecurityUtils.getLoginUser().getOrgId())
                .set(AppCouponItem::getUsedTime, DateUtils.getNowDate())
                .eq(AppCouponItem::getAppUserId, orderRecharge.getAppUserId())
                .in(AppCouponItem::getId, couponIds));
    }

    /**
     * 通过密码卡，保存充值订单
     *
     * @param rechargePasswordCard
     * @param orderRechargeCreateDTO
     * @return
     */
    @Override
    public OrderRecharge buildOrderRechargeByCardPassword(RechargePasswordCard rechargePasswordCard, OrderRechargeCreateDTO orderRechargeCreateDTO) {
        OrderRecharge orderRecharge = new OrderRecharge();
        // 保存订单主表
        orderRecharge.setCreateById(rechargePasswordCard.getCreateById());
        orderRecharge.setCreateBy(rechargePasswordCard.getCreateBy());
        orderRecharge.setCreateTime(DateUtils.getNowDate());
        orderRecharge.setStoreId(rechargePasswordCard.getRechargeStoreId());
        orderRecharge.setOrderNo(orderNoUtils.getRechargeOrderNo());
        orderRecharge.setAppUserId(orderRechargeCreateDTO.getAppUserId());
        orderRecharge.setRechargeType(orderRechargeCreateDTO.getRechargeType());
        orderRecharge.setPayTime(DateUtils.getNowDate());
        orderRecharge.setPayType(PayType.RECHARGE_CARD.getCode());
        orderRecharge.setDelFlag(DeleteStatus.OK.getCode());
        orderRecharge.setOrderStatus(OrderRechargeStatus.YES_PAY.getCode());
        orderRecharge.setPayStatus(PayStatus.HAS_PAY.getCode());
        orderRecharge.setSourceType(SourceType.STORE.getCode());
        orderRecharge.setOrderSource(orderRechargeCreateDTO.getOrderSource());
        orderRecharge.setRechargeCardNo(rechargePasswordCard.getCardNo());
        orderRecharge.setPayAmount(rechargePasswordCard.getRechargeAmount());
        orderRecharge.setCashPayAmount(rechargePasswordCard.getRechargeAmount());
        orderRecharge.setWelfareAmount(rechargePasswordCard.getWelfareAmount() == null ? BigDecimal.ZERO : rechargePasswordCard.getWelfareAmount());
        orderRecharge.setWxPayAmount(BigDecimal.ZERO);
        orderRecharge.setAliPayAmount(BigDecimal.ZERO);
        orderRecharge.setRechargeAmount(rechargePasswordCard.getRechargeAmount() == null ? BigDecimal.ZERO : rechargePasswordCard.getRechargeAmount());
        orderRecharge.setGiveAmount(rechargePasswordCard.getGiveAmount() == null ? BigDecimal.ZERO : rechargePasswordCard.getGiveAmount());
        orderRecharge.setGivePointAmount(rechargePasswordCard.getGivePointAmount() == null ? 0 : rechargePasswordCard.getGivePointAmount());
        orderRecharge.setRefundAmount(BigDecimal.ZERO);
        this.save(orderRecharge);

        return orderRecharge;
    }

    /**
     * 支付完成后， 创建密码卡， 更新订单信息
     *
     * @param orderNo 每次支付的订单编号
     *                这里分两种情况
     *                1、 app 直接整个订单一次性支付，所以orderNo是唯一且是主订单的订单编号
     *                2、 pc端存在分段多次支付同一个订单情况， 所以上报的时候，不能用同一个订单，否则微信/支付宝会报错，
     *                这里需要唯一的，所以拿子表分段支付订单编号
     */
    @Override
    public R creatPassWordCardByPayNotify(String orderNo, String outTradeNo) {
        OrderRecharge orderRecharge = getOrderRechargeByOrderNo(orderNo);
        if (orderRecharge == null) {
            log.error("充值支付成功订单不存在：" + orderNo);
            return R.fail("充值支付成功订单不存在");
        }
        paySuccess(orderRecharge, outTradeNo);
        return R.ok();
    }

    @Override
    public OrderRecharge getOrderRechargeByOrderNo(String orderNo) {
        OrderRecharge orderRecharge = this.getOne(new QueryWrapper<OrderRecharge>().lambda().eq(OrderRecharge::getOrderNo, orderNo));
        return orderRecharge;
    }


    /**
     * 生成密码卡
     *
     * @param orderRecharge
     * @return
     */
    public RechargePasswordCard buildRechargePasswordCardData(OrderRecharge orderRecharge) {
        RechargePasswordCard rechargePasswordCard = new RechargePasswordCard();
        rechargePasswordCard.setOrderNo(orderRecharge.getOrderNo());
        rechargePasswordCard.setCardNo(orderNoUtils.getOrderNo());
        rechargePasswordCard.setUseBindStoreId(orderRecharge.getStoreId());
        rechargePasswordCard.setRechargeAmount(orderRecharge.getRechargeAmount());
        rechargePasswordCard.setGiveAmount(orderRecharge.getGiveAmount());
        rechargePasswordCard.setGivePointAmount(orderRecharge.getGivePointAmount());
        rechargePasswordCard.setWelfareAmount(orderRecharge.getWelfareAmount());
        rechargePasswordCard.setActualAmount(orderRecharge.getRechargeAmount());

        rechargePasswordCard.setRechargeBalance(rechargePasswordCard.getRechargeAmount());
        rechargePasswordCard.setGiveBalance(rechargePasswordCard.getGiveAmount());
        rechargePasswordCard.setWelfareBalance(rechargePasswordCard.getWelfareAmount());
        rechargePasswordCard.setRechargeStatus(RechargeStatusType.HAS_USE.getCode());
        rechargePasswordCard.setRechargeTime(DateUtils.getNowDate());
        rechargePasswordCard.setRechargeUserId(orderRecharge.getAppUserId());
        rechargePasswordCard.setRechargeStoreId(orderRecharge.getStoreId());
        rechargePasswordCard.setDelFlag(DeleteStatus.OK.getCode());
        rechargePasswordCard.setCreateBy(orderRecharge.getCreateBy());
        rechargePasswordCard.setCreateById(orderRecharge.getCreateById());
        rechargePasswordCard.setCreateTime(orderRecharge.getCreateTime());
        rechargePasswordCard.setCreateType(RechargeCreateType.ONLINE_RECHARGE.getCode());
        rechargePasswordCard.setIsSupportLife(SysBoolType.YES.getCode());
        rechargePasswordCard.setIsSupportGoods(SysBoolType.YES.getCode());
        rechargePasswordCard.setIsSupportCloth(SysBoolType.YES.getCode());
        rechargePasswordCard.setIsSupportCar(SysBoolType.YES.getCode());
        rechargePasswordCardService.save(rechargePasswordCard);
        return rechargePasswordCard;
    }

    /**
     * 查询门店会员充值记录
     *
     * @param useId
     */
    @Override
    public List<OrderRechargeRecordVO> getRechargeRecordByUserId(Long useId) {
        List<OrderRechargeRecordVO> record = baseMapper.getRechargeRecordByUserId(useId);
        RechargePasswordCard rechargePasswordCard = rechargePasswordCardService.selectTotalBalanceGroupByAppUser(useId);
        if (rechargePasswordCard == null) {
            return record;
        }
        BigDecimal bigDecimal = rechargePasswordCard.getRechargeBalance().add(rechargePasswordCard.getGiveBalance());
        for (OrderRechargeRecordVO vo : record) {
            vo.setTotalBalance(bigDecimal);
        }
        return record;
    }

    /**
     * 充值退款申请
     *
     * @param refundDTO 退款申请参数
     * @return 处理结果
     */
    @Transactional(rollbackFor = Exception.class)
    public int refundRechargeApply(OrderRechargeRefundDTO refundDTO) {
        // 1. 幂等性控制
        String lockKey = String.format("recharge:refund:apply:%s", refundDTO.getOrderId());
        if (!redisLockUtil.tryLock(lockKey)) {
            throw new ServiceException("退款申请处理中,请勿重复提交");
        }

        try {
            // 2. 校验订单信息
            OrderRecharge orderRecharge = validateAndGetOrder(refundDTO.getOrderId());

            // 3. 校验充值卡信息
            RechargePasswordCard rechargeCard = validateAndGetRechargeCard(orderRecharge.getOrderNo());

            // 4. 冻结充值卡
            freezeRechargeCard(rechargeCard);

            // 5. 创建退款申请记录
            OrderRechargeRefund refundOrder = createRefundOrder(orderRecharge, rechargeCard, refundDTO);

            // 6. 更新订单状态
            updateOrderStatus(orderRecharge);

            // 7. 发起退款
//            processRefund(orderRecharge, refundOrder);

            return 1;
        } catch (Exception e) {
            log.error("充值退款申请处理失败, orderId={}, error={}", refundDTO.getOrderId(), e.getMessage());
            throw new ServiceException("退款申请处理失败:" + e.getMessage());
        } finally {
            redisLockUtil.unlock(lockKey);
        }
    }

    /**
     * 校验并获取订单信息
     */
    private OrderRecharge validateAndGetOrder(Long orderId) {
        OrderRecharge orderRecharge = this.getById(orderId);
        if (orderRecharge == null) {
            throw new ServiceException("订单不存在");
        }

        if (!OrderRechargeStatus.YES_PAY.getCode().equals(orderRecharge.getOrderStatus())) {
            throw new ServiceException("订单状态不正确,不能申请退款");
        }

        return orderRecharge;
    }

    /**
     * 校验并获取充值卡信息
     */
    private RechargePasswordCard validateAndGetRechargeCard(String orderNo) {
        RechargePasswordCard card = rechargePasswordCardService.getOne(
                new QueryWrapper<RechargePasswordCard>()
                        .lambda()
                        .eq(RechargePasswordCard::getOrderNo, orderNo)
                        .eq(RechargePasswordCard::getDelFlag, DeleteStatus.OK.getCode())
        );

        if (card == null) {
            log.error("未找到订单对应的充值卡记录, orderNo={}", orderNo);
            throw new ServiceException("未找到该笔订单对应的充值卡记录");
        }

        return card;
    }

    /**
     * 冻结充值卡
     */
    private void freezeRechargeCard(RechargePasswordCard card) {
        card.setRefundTime(DateUtils.getNowDate());
        card.setRechargeStatus(RechargeStatusType.FROZEN.getCode());
        card.buildUpdateData();

        boolean success = rechargePasswordCardService.updateById(card);
        if (!success) {
            throw new ServiceException("冻结充值卡失败");
        }
    }

    /**
     * 创建退款申请记录
     */
    private OrderRechargeRefund createRefundOrder(OrderRecharge orderRecharge,
                                                  RechargePasswordCard card,
                                                  OrderRechargeRefundDTO refundDTO) {
        OrderRechargeRefund refundOrder = new OrderRechargeRefund();

        // 设置基本信息
        refundOrder.setOrderNo(orderRecharge.getOrderNo());
        refundOrder.setRefundNo(orderNoUtils.getRechargeOrderNo());
        refundOrder.setCardNo(card.getCardNo());
        refundOrder.setStoreId(card.getRechargeStoreId());
        refundOrder.setRechargeUserId(orderRecharge.getAppUserId());

        // 设置退款信息
        refundOrder.setRefundType(orderRecharge.getPayType());
        refundOrder.setRefundReason(refundDTO.getRefundDescribe());
        refundOrder.setRefundStatus(OrderRefundStatus.REFUND_APPLYING.getCode());

        // 设置金额信息
        setRefundAmount(refundOrder, orderRecharge, card);

        // 设置时间信息
        refundOrder.setRefundApplyTime(DateUtils.getNowDate());
        refundOrder.setRefundTime(DateUtils.getNowDate());
        refundOrder.setDelFlag(DeleteStatus.OK.getCode());
        refundOrder.buildCreateData();

        orderRechargeRefundService.save(refundOrder);
        return refundOrder;
    }

    /**
     * 设置退款金额
     */
    private void setRefundAmount(OrderRechargeRefund refundOrder,
                                 OrderRecharge orderRecharge,
                                 RechargePasswordCard card) {
        // 设置订单相关金额
        refundOrder.setPayAmount(orderRecharge.getPayAmount());
        refundOrder.setRechargeAmount(orderRecharge.getRechargeAmount());
        refundOrder.setGiveAmount(orderRecharge.getGiveAmount());
        refundOrder.setWelfareAmount(orderRecharge.getWelfareAmount());

        // 设置卡余额
        refundOrder.setWelfareBalance(card.getWelfareBalance());
        refundOrder.setRechargeBalance(card.getRechargeBalance());
        refundOrder.setGiveBalance(card.getGiveBalance());
        refundOrder.setRefundAmount(card.getRechargeBalance());

        // 根据支付方式设置退款金额
        initializeRefundChannelAmount(refundOrder, orderRecharge, card);
    }

    /**
     * 初始化退款渠道金额
     */
    private void initializeRefundChannelAmount(OrderRechargeRefund refundOrder,
                                               OrderRecharge orderRecharge,
                                               RechargePasswordCard card) {
        refundOrder.setAliRefundAmount(BigDecimal.ZERO);
        refundOrder.setWxRefundAmount(BigDecimal.ZERO);
        refundOrder.setCashRefundAmount(BigDecimal.ZERO);

        switch (PayType.getPayType(refundOrder.getRefundType())) {
            case WECHAT:
                refundOrder.setWxRefundAmount(card.getRechargeBalance());
                break;
            case ALIPAY:
                refundOrder.setAliRefundAmount(card.getRechargeBalance());
                break;
            case CASH:
                refundOrder.setCashRefundAmount(card.getRechargeBalance());
                break;
            case COMBINE:
                handleCombineRefund(refundOrder, orderRecharge, card);
                break;
            case RECHARGE_CARD:
                refundOrder.setCashRefundAmount(card.getRechargeBalance());
                break;
        }
    }

    /**
     * 处理组合支付退款
     */
    private void handleCombineRefund(OrderRechargeRefund refundOrder,
                                     OrderRecharge orderRecharge,
                                     RechargePasswordCard card) {
        // 优先退微信支付宝,剩余退现金
        if (orderRecharge.getWxPayAmount().compareTo(BigDecimal.ZERO) > 0) {
            refundOrder.setWxRefundAmount(card.getRechargeBalance());
        }

        if (orderRecharge.getAliPayAmount().compareTo(BigDecimal.ZERO) > 0) {
            refundOrder.setAliRefundAmount(card.getRechargeBalance());
        }

        BigDecimal remainAmount = CurrencyUtil.sub(
                card.getRechargeBalance(),
                refundOrder.getWxRefundAmount(),
                refundOrder.getAliRefundAmount()
        );

        if (remainAmount.compareTo(BigDecimal.ZERO) > 0) {
            refundOrder.setCashRefundAmount(remainAmount);
        }
    }

    /**
     * 更新订单状态
     */
    private void updateOrderStatus(OrderRecharge orderRecharge) {
        orderRecharge.setRefundApplyTime(DateUtils.getNowDate());
        orderRecharge.setRefundTime(DateUtils.getNowDate());
        orderRecharge.setRefundStatus(OrderRefundStatus.REFUND_APPLYING.getCode());
        orderRecharge.buildUpdateData();

        boolean success = this.updateById(orderRecharge);
        if (!success) {
            throw new ServiceException("更新订单状态失败");
        }
    }


    @Override
    public R refundSuccess(String orderNo) {
        OrderRecharge orderRecharge = getOrderRechargeByOrderNo(orderNo);
        if (orderRecharge == null) {
            throw new ServiceException("未查询到订单");
        }
        if (orderRecharge.getRefundStatus() == OrderRefundStatus.REFUNDING.getCode()
                || orderRecharge.getRefundStatus() == OrderRefundStatus.REFUND_SUCCESS.getCode()) {//退款状态不正确，直接跳过
            throw new ServiceException("当前退款状态不正确");
        }
        //查询退款订单
        OrderRechargeRefund orderRechargeRefund = orderRechargeRefundService.selectOrderRechargeOrderNo(orderNo);
        orderRecharge.setRefundAmount(CurrencyUtil.add(orderRechargeRefund.getRefundAmount(), orderRechargeRefund.getRefundAmount()));
        orderRecharge.setRefundStatus(RechargeRefundStatusType.REFUND_SUCCESS.getCode());
        this.updateById(orderRecharge);

        // 3. 更新退款申请状态
        orderRechargeRefund.setRefundStatus(RechargeRefundStatusType.REFUND_SUCCESS.getCode());
        orderRechargeRefundService.updateById(orderRechargeRefund);

        RechargePasswordCard rechargePasswordCard = rechargePasswordCardService.getOne(new QueryWrapper<RechargePasswordCard>().lambda()
                .eq(RechargePasswordCard::getOrderNo, orderRecharge.getOrderNo())
                .eq(RechargePasswordCard::getDelFlag, DeleteStatus.OK.getCode()), Boolean.FALSE);
        if (rechargePasswordCard == null) {
            log.error("充值卡退款成功，订单不存在：" + orderNo);
            throw new ServiceException("充值卡不存在");
        }
        rechargePasswordCard.setRechargeStatus(RechargeStatusType.REFUND.getCode());
        rechargePasswordCardService.updateById(rechargePasswordCard);
        //退用户积分
        appUserPointLogService.reducePoint(orderRecharge.getAppUserId(), orderRecharge.getGivePointAmount().intValue(), orderRecharge.getOrderNo(), MemberPointSourceEnum.REFUND_DEDUCT, "会员储值退款扣除");
        //此处添加退款记录

        BillMstrOrderDTO billMstrOrderDTO = new BillMstrOrderDTO();
        billMstrOrderDTO.setAppUserId(orderRecharge.getAppUserId());
        billMstrOrderDTO.setOrgId(orderRecharge.getStoreId());
        billMstrOrderDTO.setOrderId(orderRecharge.getId());
        billMstrOrderDTO.setSourceType(orderRecharge.getSourceType());
        billMstrOrderDTO.setOrderNo(orderRecharge.getOrderNo());
        billMstrOrderDTO.setOrderType(OrderType.recharge.getCode());
        billMstrOrderDTO.setRechargePayAmount(orderRecharge.getRechargeAmount());
        billMstrOrderDTO.setUseBindStoreId(rechargePasswordCard.getUseBindStoreId());
        billMstrOrderDTO.setWelfarePayAmount(orderRechargeRefund.getWelfareBalance());
        billMstrOrderDTO.setGivePayAmount(orderRechargeRefund.getWelfareBalance());
        billMstrOrderDTO.setRechargeCardNo(orderRecharge.getRechargeCardNo());
        billMstrOrderDTO.setPayType(orderRecharge.getPayType());
        billMstrOrderDTO.setPayTotalAmount(orderRechargeRefund.getRefundAmount());
        billMstrOrderDTO.setRemark("充值卡：" + rechargePasswordCard.getCardNo() + "，退款" + orderRechargeRefund.getRefundAmount() + "元");
        try {
            billMstrOrderService.saveRefundBillMstrOrder(billMstrOrderDTO);
        } catch (Exception e) {
            log.error("保存消费日志失败，订单号：{}", orderRecharge.getOrderNo(), e);
            throw new ServiceException("保存消费日志失败");
        }
        log.debug("充值订单{}" + orderNo + "退款完成");
        return R.ok();
    }

    @Override
    public R refundClosed(String orderNo) {
        OrderRecharge orderRecharge = getOne(new QueryWrapper<OrderRecharge>().lambda().eq(OrderRecharge::getOrderNo, orderNo));
        if (orderRecharge == null) {
            throw new ServiceException("未查询到订单");
        }
        orderRecharge.setRefundStatus(OrderRefundStatus.REFUND_CANCEL.getCode());
        updateById(orderRecharge);
        return R.ok();
    }

    @Override
    public R refundError(String orderNo) {
        OrderRechargeRefund orderRechargeRefund = orderRechargeRefundService.selectOrderRechargeOrderNo(orderNo);
        orderRechargeRefund.setRefundStatus(OrderRefundStatus.ERROR.getCode());
        orderRechargeRefundService.updateById(orderRechargeRefund);
        return R.ok();
    }

    /**
     * 充值订单-处理支付失败
     *
     * @param orderNo
     * @return 处理支付失败
     */
    @Override
    public String handleCancelRecharge(String orderNo) {
        OrderRechargeInstalment orderRechargeInstalment = orderRechargeInstalmentService.getOne(new QueryWrapper<OrderRechargeInstalment>().lambda()
                .eq(OrderRechargeInstalment::getOrderNo, orderNo));
        OrderRecharge orderRecharge = this.getOne(new QueryWrapper<OrderRecharge>().lambda().eq(OrderRecharge::getOrderNo, orderRechargeInstalment.getMstrOrderNo()));
        if (orderRecharge == null) {
            log.info("充值订单不存在，订单编号：" + orderNo);
            return "订单不存在";
        }
        if (OrderRechargeStatus.REFUND.getCode().equals(orderRecharge.getOrderStatus())
                || OrderRefundStatus.REFUND_SUCCESS.getCode().equals(orderRecharge.getRefundStatus())) {
            log.info("充值订单已退款，不需要处理，订单编号：" + orderNo);
            return "订单已退款，不需要处理";
        }
        if (!OrderGoodsStatusType.NO_PAY.getCode().equals(orderRecharge.getOrderStatus())) {
            log.info("充值订单状态不对，无法取消，订单编号：" + orderNo);
            return "订单状态不对，无法取消";
        }
        orderRecharge.setOrderStatus(OrderRechargeStatus.CANCEL.getCode());
        orderRecharge.setRemark("支付失败取消订单");
        orderRecharge.buildUpdateData();
        baseMapper.updateById(orderRecharge);

        orderRechargeInstalment.setOrderStatus(OrderRechargeStatus.CANCEL.getCode());
        orderRechargeInstalment.setRemark("支付失败取消订单");
        orderRechargeInstalment.buildUpdateData();
        orderRechargeInstalmentService.updateById(orderRechargeInstalment);
        return "支付失败，取消订单";
    }

}
