package com.xinelu.applet.service.wechatpaymentinfo.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.xinelu.applet.service.wechatpaymentinfo.WeChatPayNotifyService;
import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatPayNotifyPlaintextVO;
import com.xinelu.applet.vo.wechatpaymentinfo.vo.WeChatRefundNotifyVO;
import com.xinelu.common.config.XylWeChatPaymentConfig;
import com.xinelu.common.constant.Constants;
import com.xinelu.common.enums.*;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.RedisDistributedLockUtils;
import com.xinelu.common.utils.http.HttpUtils;
import com.xinelu.manage.domain.appointmentorder.AppointmentOrder;
import com.xinelu.manage.domain.goodsOrder.GoodsOrder;
import com.xinelu.manage.domain.paymentinfo.PaymentInfo;
import com.xinelu.manage.domain.refundinfo.RefundInfo;
import com.xinelu.manage.domain.trainingorder.TrainingOrder;
import com.xinelu.manage.mapper.appointmentorder.AppointmentOrderMapper;
import com.xinelu.manage.mapper.goodsAttributeDetails.GoodsAttributeDetailsMapper;
import com.xinelu.manage.mapper.goodsOrder.GoodsOrderMapper;
import com.xinelu.manage.mapper.patientcouponreceive.PatientCouponReceiveMapper;
import com.xinelu.manage.mapper.paymentinfo.PaymentInfoMapper;
import com.xinelu.manage.mapper.refundinfo.RefundInfoMapper;
import com.xinelu.manage.mapper.trainingorder.TrainingOrderMapper;
import com.xinelu.manage.vo.AppointOrderAndDetailsInfo;
import com.xinelu.manage.vo.appointmentorder.AppointmentOrderInfoVO;
import com.xinelu.manage.vo.goods.GoodsOrderAndDetailsInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @Description 微信支付回调业务层实现类
 * @Author 纪寒
 * @Date 2022-10-20 14:00:52
 * @Version 1.0
 */
@Slf4j
@Service
public class WeChatPayNotifyServiceImpl implements WeChatPayNotifyService {

    @Resource
    private XylWeChatPaymentConfig xylWeChatPaymentConfig;
    @Resource
    private GoodsOrderMapper goodsOrderMapper;
    @Resource
    private AppointmentOrderMapper appointmentOrderMapper;
    @Resource
    private PaymentInfoMapper paymentInfoMapper;
    @Resource
    private RedisDistributedLockUtils redisDistributedLockUtils;
    @Resource(name = "transactionManager")
    private DataSourceTransactionManager transactionManager;
    @Resource
    private GoodsAttributeDetailsMapper goodsAttributeDetailsMapper;
    @Resource
    private RefundInfoMapper refundInfoMapper;
    @Resource(name = "xylVerifier")
    private Verifier xylVerifier;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private PatientCouponReceiveMapper patientCouponReceiveMapper;
    @Resource
    private TrainingOrderMapper trainingOrderMapper;

    /**
     * 支付回调标识
     */
    private static final String PAY = "PAY";

    /**
     * 退款回调标识
     */
    private static final String REFUND = "REFUND";

    /**
     * 新医路支付回调接口
     *
     * @param request  请求信息
     * @param response 响应信息
     * @return 应答信息，避免微信平台重复发送回调通知
     */
    @Override
    public String xylWeChatPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("新医路微信支付回调开始执行");
        return weChatPayNotifyInfo(request, response, PaymentMerchantTypeEnum.XINYILU.getInfo(), PAY);
    }

    /**
     * 新医路退款回调接口
     *
     * @param request  请求信息
     * @param response 响应信息
     * @return 应答信息，避免微信平台重复发送回调通知
     * @throws Exception 异常信息
     */
    @Override
    public String xylWeChatRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("新医路微信退款回调开始执行");
        return weChatPayNotifyInfo(request, response, PaymentMerchantTypeEnum.XINYILU.getInfo(), REFUND);
    }

    /**
     * 微信支付回调通知公共方法
     *
     * @param request              请求信息
     * @param response             响应信息
     * @param accountFlag          账户标识，用于区分是新医路还是医路优品
     * @param refundAndPaymentFlag 支付和回调标识
     * @return 返回信息
     * @throws Exception 异常信息
     */
    private String weChatPayNotifyInfo(HttpServletRequest request, HttpServletResponse response,
                                       String accountFlag, String refundAndPaymentFlag) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        String body = HttpUtils.readRequestData(request);
        if (StringUtils.isBlank(body)) {
            log.error(accountFlag + "微信回调通知失败，请求体 ====> {}", body);
            response.setStatus(500);
            resultMap.put("code", "ERROR");
            resultMap.put("message", "通知验签失败");
            return JSON.toJSONString(resultMap);
        }
        log.info(accountFlag + "微信通知的请求体信息 ===> {}", body);
        String nonce = request.getHeader("Wechatpay-Nonce");
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String signature = request.getHeader("Wechatpay-Signature");
        String serialNo = request.getHeader("Wechatpay-Serial");
        NotificationRequest notificationRequest = new NotificationRequest.Builder().withSerialNumber(serialNo)
                .withNonce(nonce).withTimestamp(timestamp).withSignature(signature).withBody(body).build();
        NotificationHandler handler = new NotificationHandler(xylVerifier, xylWeChatPaymentConfig.getXylPaymentKey().getBytes(StandardCharsets.UTF_8));
        Notification notification = null;
        try {
            notification = handler.parse(notificationRequest);
        } catch (Exception e) {
            log.warn("微信支付回调异常，异常信息为：{}", e.getMessage());
        }
        if (Objects.isNull(notification)) {
            log.error(accountFlag + "微信通知验签失败，请求体 ====> {}", body);
            response.setStatus(500);
            resultMap.put("code", "ERROR");
            resultMap.put("message", "通知验签失败");
            return JSON.toJSONString(resultMap);
        }
        String ciphertext = StringUtils.isBlank(notification.getResource().getCiphertext()) ? "" : notification.getResource().getCiphertext();
        String nonceTwo = StringUtils.isBlank(notification.getResource().getNonce()) ? "" : notification.getResource().getNonce();
        String associatedData = StringUtils.isBlank(notification.getResource().getAssociatedData()) ? "" : notification.getResource().getAssociatedData();
        AesUtil aesUtil = new AesUtil(xylWeChatPaymentConfig.getXylPaymentKey().getBytes(StandardCharsets.UTF_8));
        String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonceTwo.getBytes(StandardCharsets.UTF_8), ciphertext);
        if (StringUtils.isBlank(plainText)) {
            response.setStatus(500);
            resultMap.put("code", "ERROR");
            resultMap.put("message", "解密失败！");
            return JSON.toJSONString(resultMap);
        }
        if (Constants.PAY_NOTIFY.equals(refundAndPaymentFlag)) {
            this.processPaymentInfo(plainText);
        }
        if (Constants.REFUND_NOTIFY.equals(refundAndPaymentFlag)) {
            this.processRefundInfo(plainText);
        }
        response.setStatus(200);
        resultMap.put("code", "SUCCESS");
        resultMap.put("message", "成功");
        log.info("微信回调方法执行完成！");
        return JSON.toJSONString(resultMap);
    }

    /**
     * 记录支付信息和修改订单状态
     *
     * @param plainText 支付验签以后的通知内容
     */
    private void processPaymentInfo(String plainText) {
        WeChatPayNotifyPlaintextVO notifyPlaintext = JSONObject.parseObject(plainText, WeChatPayNotifyPlaintextVO.class);
        if (StringUtils.isBlank(notifyPlaintext.getOutTradeNo())) {
            return;
        }
        String orderNoLockKey = Constants.WE_CHAT_NOTIFY_KEY + notifyPlaintext.getOutTradeNo();
        boolean tryLock = redisDistributedLockUtils.tryLock(orderNoLockKey, 5);
        if (!tryLock) {
            return;
        }
        TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            //记录学习培训订单支付日志和修改订单状态
            TrainingOrder trainingOrderInfo = trainingOrderMapper.getTrainingOrderInfoByOrderNo(notifyPlaintext.getOutTradeNo());
            if (Objects.nonNull(trainingOrderInfo)) {
                insertPaymentInfo(notifyPlaintext, null, null, trainingOrderInfo, plainText);
                if (WeChatTradeStateEnum.SUCCESS.getInfo().equals(notifyPlaintext.getTradeState())) {
                    trainingOrderMapper.updateTrainingOrderStatus(TrainingOrderStatusEnum.PAY.getInfo(), trainingOrderInfo.getTrainingOrderNo());
                } else {
                    log.info("学习培训微信订单状态异常，订单状态为 ====> {}", notifyPlaintext.getTradeState());
                }
                transactionManager.commit(transactionStatus);
                return;
            }
            //商品订单信息
            GoodsOrder goodsOrderInfo = goodsOrderMapper.getGoodsOrderByOrderNo(notifyPlaintext.getOutTradeNo());
            if (Objects.nonNull(goodsOrderInfo)) {
                insertPaymentInfo(notifyPlaintext, goodsOrderInfo, null, null, plainText);
                if (WeChatTradeStateEnum.SUCCESS.getInfo().equals(notifyPlaintext.getTradeState())) {
                    goodsOrderMapper.updateGoodsOrderStatus(GooodsOrderStatusEnum.WAIT_RECEIVED_GOODS.getInfo(), goodsOrderInfo.getOrderNo());
                } else {
                    log.info("商品订单微信订单状态异常，订单状态为 ====> {}", notifyPlaintext.getTradeState());
                }
                transactionManager.commit(transactionStatus);
                return;
            }
            AppointmentOrderInfoVO appointmentOrderInfo = appointmentOrderMapper.getAppointmentOrderInfoByOrderNo(notifyPlaintext.getOutTradeNo());
            if (Objects.isNull(appointmentOrderInfo)) {
                return;
            }
            //预约服务订单信息
            insertPaymentInfo(notifyPlaintext, null, appointmentOrderInfo, null, plainText);
            if (WeChatTradeStateEnum.SUCCESS.getInfo().equals(notifyPlaintext.getTradeState())) {
                appointmentOrderMapper.updateAppointmentOrderStatus(OrderStatusEnum.WAIT_DISPATCH.getInfo(), appointmentOrderInfo.getOrderNo());
            } else {
                log.info("预约服务微信订单状态异常，订单状态为 ====> {}", notifyPlaintext.getTradeState());
            }
            transactionManager.commit(transactionStatus);
        } catch (Exception e) {
            transactionManager.rollback(transactionStatus);
            log.error("微信支付回调失败，失败原因：{}", e.getMessage());
            throw e;
        } finally {
            redisDistributedLockUtils.unlock(orderNoLockKey);
            log.info("支付回调释放锁完成...........");
        }
    }

    /**
     * 记录支付日志信息
     *
     * @param notifyPlaintext  回调信息
     * @param goodsOrderInfo   商品订单信息
     * @param appointmentOrder 预约订单信息
     * @param plainText        回调明文
     */
    private void insertPaymentInfo(WeChatPayNotifyPlaintextVO notifyPlaintext, GoodsOrder goodsOrderInfo,
                                   AppointmentOrder appointmentOrder, TrainingOrder trainingOrderInfo, String plainText) {
        int paymentInfoCount = paymentInfoMapper.getPaymentInfoByOrderNo(notifyPlaintext.getOutTradeNo());
        if (paymentInfoCount <= 0) {
            PaymentInfo paymentInfo = buildPaymentInfo(notifyPlaintext, goodsOrderInfo, appointmentOrder, trainingOrderInfo, plainText);
            int insertCount = paymentInfoMapper.insertPaymentInfo(paymentInfo);
            if (insertCount <= 0) {
                log.error("记录支付日志出错，参数为 ====> [{}]", paymentInfo);
                throw new ServiceException("记录支付日志出错，请联系管理员！");
            }
        }
    }

    /**
     * 构建支付信息参数
     *
     * @param notifyPlaintext      通知明文信息
     * @param goodsOrderInfo       商品订单信息
     * @param appointmentOrderInfo 预约订单信息
     */
    private PaymentInfo buildPaymentInfo(WeChatPayNotifyPlaintextVO notifyPlaintext, GoodsOrder goodsOrderInfo,
                                         AppointmentOrder appointmentOrderInfo, TrainingOrder trainingOrder, String plainText) {
        PaymentInfo paymentInfo = new PaymentInfo();
        if (Objects.nonNull(goodsOrderInfo)) {
            paymentInfo.setPatientId(Objects.isNull(goodsOrderInfo.getPatientId()) ? null : goodsOrderInfo.getPatientId());
            paymentInfo.setOrderNo(StringUtils.isBlank(goodsOrderInfo.getOrderNo()) ? "" : goodsOrderInfo.getOrderNo());
            paymentInfo.setPayChannel(StringUtils.isBlank(goodsOrderInfo.getOrderChannel()) ? "" : goodsOrderInfo.getOrderChannel());
        } else if (Objects.nonNull(appointmentOrderInfo)) {
            paymentInfo.setPatientId(Objects.isNull(appointmentOrderInfo.getPatientId()) ? null : appointmentOrderInfo.getPatientId());
            paymentInfo.setOrderNo(StringUtils.isBlank(appointmentOrderInfo.getOrderNo()) ? "" : appointmentOrderInfo.getOrderNo());
            paymentInfo.setPayChannel(StringUtils.isBlank(appointmentOrderInfo.getOrderChannel()) ? "" : appointmentOrderInfo.getOrderChannel());
        } else if (Objects.nonNull(trainingOrder)) {
            paymentInfo.setNurseStationPersonId(Objects.isNull(trainingOrder.getNurseStationPersonId()) ? null : trainingOrder.getNurseStationPersonId());
            paymentInfo.setOrderNo(StringUtils.isBlank(trainingOrder.getTrainingOrderNo()) ? "" : trainingOrder.getTrainingOrderNo());
            paymentInfo.setPayChannel(StringUtils.isBlank(trainingOrder.getTrainingOrderChannel()) ? "" : trainingOrder.getTrainingOrderChannel());
        }
        paymentInfo.setTransactionNo(StringUtils.isBlank(notifyPlaintext.getTransactionId()) ? "" : notifyPlaintext.getTransactionId());
        paymentInfo.setPayPrice(BigDecimal.valueOf(Objects.isNull(notifyPlaintext.getAmount().getPayerTotal()) ? 0 : notifyPlaintext.getAmount().getPayerTotal()).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_DOWN));
        paymentInfo.setPayType(PayTypeEnum.WECHAT_PAY.getInfo());
        paymentInfo.setWechatTradeState(StringUtils.isBlank(notifyPlaintext.getTradeState()) ? "" : notifyPlaintext.getTradeState());
        paymentInfo.setPayNotifyContent(plainText);
        paymentInfo.setPayTime(LocalDateTime.parse(StringUtils.isBlank(notifyPlaintext.getSuccessTime()) ? "" : notifyPlaintext.getSuccessTime(), DateTimeFormatter.ISO_DATE_TIME));
        paymentInfo.setPaymentMerchantType(PaymentMerchantTypeEnum.XINYILU.getInfo());
        paymentInfo.setDelFlag(0);
        paymentInfo.setCreateTime(LocalDateTime.now());
        return paymentInfo;
    }

    /**
     * 修改订单状态以及减少库存信息
     *
     * @param plainText 支付验签以后的通知内容
     */
    private void processRefundInfo(String plainText) {
        WeChatRefundNotifyVO refundNotifyVO = JSONObject.parseObject(plainText, WeChatRefundNotifyVO.class);
        if (StringUtils.isBlank(refundNotifyVO.getOutTradeNo())) {
            return;
        }
        String orderNoLockKey = Constants.WE_CHAT_REFUND_KEY + refundNotifyVO.getOutTradeNo();
        boolean tryLock = redisDistributedLockUtils.tryLock(orderNoLockKey, 5);
        if (!tryLock) {
            return;
        }
        TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
        RedisAtomicLong redisAtomicLong = null;
        try {
            //处理学习培训订单退款信息
            TrainingOrder trainingOrderInfo = trainingOrderMapper.getTrainingOrderInfoByOrderNo(refundNotifyVO.getOutTradeNo());
            if (Objects.nonNull(trainingOrderInfo)) {
                handleRefundTrainingOrderNo(trainingOrderInfo, plainText, refundNotifyVO);
                transactionManager.commit(transactionStatus);
                return;
            }
            GoodsOrderAndDetailsInfo detailsOrderInfo = goodsOrderMapper.getGoodsAndDetailsOrderInfo(refundNotifyVO.getOutTradeNo());
            AppointOrderAndDetailsInfo appointmentOrderInfo = appointmentOrderMapper.getAppointOrderAndDetailsInfo(refundNotifyVO.getOutTradeNo());
            if (Objects.isNull(detailsOrderInfo) && Objects.isNull(appointmentOrderInfo)) {
                return;
            }
            if (Objects.nonNull(appointmentOrderInfo)) {
                updateAppointmentInfo(appointmentOrderInfo, plainText, refundNotifyVO);
                if (Objects.nonNull(appointmentOrderInfo.getAppointmentLimitCount()) && StringUtils.equals(AppointmentOrderTypeEnum.OTHER.getInfo(), appointmentOrderInfo.getOrderType())) {
                    String appointLimitCountKey = Constants.PRE_APPOINTMENT_LIMIT_COUNT_KEY + appointmentOrderInfo.getNurseStationItemId() + "_" + appointmentOrderInfo.getServiceDate() + "_" + appointmentOrderInfo.getServiceStartTime();
                    redisAtomicLong = new RedisAtomicLong(appointLimitCountKey, Objects.requireNonNull(redisTemplate.getConnectionFactory()));
                    if (redisAtomicLong.get() >= 0 && redisAtomicLong.get() < appointmentOrderInfo.getAppointmentLimitCount()) {
                        redisAtomicLong.incrementAndGet();
                    }
                }
            }
            if (Objects.nonNull(detailsOrderInfo)) {
                updateGoodsInfo(detailsOrderInfo, plainText, refundNotifyVO);
            }
            transactionManager.commit(transactionStatus);
        } catch (Exception e) {
            transactionManager.rollback(transactionStatus);
            log.error("微信退款回调通知失败，失败信息为：{}", e.getMessage());
            if (Objects.nonNull(redisAtomicLong) && redisAtomicLong.get() > 0) {
                redisAtomicLong.decrementAndGet();
            }
            throw e;
        } finally {
            redisDistributedLockUtils.unlock(orderNoLockKey);
            log.info("退款回调释放锁完成.............");
        }
    }

    /**
     * 处理预约服务订单信息
     *
     * @param appointmentOrderInfo 预约订单信息
     * @param plainText            明文
     * @param refundNotifyVO       退款回调信息
     */
    private void updateAppointmentInfo(AppointmentOrder appointmentOrderInfo, String plainText, WeChatRefundNotifyVO refundNotifyVO) {
        if (RefundStatusEnum.SUCCESS.getInfo().equals(refundNotifyVO.getRefundStatus())
                && StringUtils.isNotBlank(appointmentOrderInfo.getOrderStatus())
                && !(OrderStatusEnum.REFUNDED.getInfo().equals(appointmentOrderInfo.getOrderStatus()))) {
            int updateCount = appointmentOrderMapper.updateAppointmentOrderStatus(OrderStatusEnum.REFUNDED.getInfo(), appointmentOrderInfo.getOrderNo());
            if (updateCount < 1) {
                log.info("微信退款通知，修改预约订单状态失败，订单编号 =====> {}", refundNotifyVO.getOutTradeNo());
            }
            RefundInfo refundInfo = buildRefundInfo(plainText, refundNotifyVO);
            int refundCount = refundInfoMapper.updateRefundInfoByNo(refundInfo);
            if (refundCount < 1) {
                log.info("微信退款通知，记录预约订单微信退款单信息失败，订单编号 =====> {}", refundNotifyVO.getOutTradeNo());
            }
        }
        if (RefundStatusEnum.CLOSED.getInfo().equals(refundNotifyVO.getRefundStatus())) {
            log.info("当前预约退款单已经关闭，订单号 ====> {}, 退款单号 =====> {}", refundNotifyVO.getOutTradeNo(), refundNotifyVO.getOutRefundNo());
        }
        if (RefundStatusEnum.ABNORMAL.getInfo().equals(refundNotifyVO.getRefundStatus())) {
            log.info("预约订单退款异常，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，可前往【商户平台—>交易中心】，手动处理此笔退款，订单号 ====> {}, 退款单号 =====> {}", refundNotifyVO.getOutTradeNo(), refundNotifyVO.getOutRefundNo());
        }
    }

    /**
     * 处理商品订单信息
     *
     * @param detailsOrderInfo 商品订单信息
     * @param plainText        明文
     * @param refundNotifyVO   退款回调信息
     */
    private void updateGoodsInfo(GoodsOrderAndDetailsInfo detailsOrderInfo, String plainText, WeChatRefundNotifyVO refundNotifyVO) {
        if (RefundStatusEnum.SUCCESS.getInfo().equals(refundNotifyVO.getRefundStatus())
                && StringUtils.isNotBlank(detailsOrderInfo.getOrderStatus())
                && !(GooodsOrderStatusEnum.REFUNDED.getInfo().equals(detailsOrderInfo.getOrderStatus()))) {
            int updateGoodsOrderCount = goodsOrderMapper.updateGoodsOrderStatus(OrderStatusEnum.REFUNDED.getInfo(), detailsOrderInfo.getOrderNo());
            if (updateGoodsOrderCount < 1) {
                log.info("微信退款通知，修改商品单状态失败，订单编号 =====> {}", refundNotifyVO.getOutTradeNo());
            }
            if (StringUtils.isNotBlank(detailsOrderInfo.getOrderType()) && !OrderTypeEnum.HEALTH_CONSULTATION.getInfo().equals(detailsOrderInfo.getOrderType())) {
                if (!GooodsOrderStatusEnum.REFUNDED.getInfo().equals(detailsOrderInfo.getOrderStatus())) {
                    int updateStockCount = goodsAttributeDetailsMapper.addGoodsStockCount(detailsOrderInfo.getGoodsAttributeDetailsId(), detailsOrderInfo.getGoodsCount());
                    if (updateStockCount < 1) {
                        log.info("新增库存数量失败，订单编号：{}，商品属性明细id：{}，数量数量：{}", detailsOrderInfo.getOrderNo(), detailsOrderInfo.getGoodsAttributeDetailsId(), detailsOrderInfo.getGoodsCount());
                    }
                }
                if (Objects.nonNull(detailsOrderInfo.getCouponId()) && Objects.nonNull(detailsOrderInfo.getPatientId())) {
                    patientCouponReceiveMapper.updatePatientCouponUseStatus(detailsOrderInfo.getPatientId(), detailsOrderInfo.getCouponId(), CouponUseStatusEnum.NOT_USED.getInfo());
                }
            }
            RefundInfo refundInfo = buildRefundInfo(plainText, refundNotifyVO);
            int refundCount = refundInfoMapper.updateRefundInfoByNo(refundInfo);
            if (refundCount < 1) {
                log.info("微信退款通知，记录商品订单微信退款单信息失败，订单编号 =====> {}", refundNotifyVO.getOutTradeNo());
            }
        }
        //处理专家咨询订单-医生拒单退款信息
        if (RefundStatusEnum.SUCCESS.getInfo().equals(refundNotifyVO.getRefundStatus())
                && StringUtils.isNotBlank(detailsOrderInfo.getOrderStatus())
                && GooodsOrderStatusEnum.REFUNDED.getInfo().equals(detailsOrderInfo.getOrderStatus())
                && OrderTypeEnum.HEALTH_CONSULTATION.getInfo().equals(detailsOrderInfo.getOrderType())) {
            RefundInfo refundInfo = buildRefundInfo(plainText, refundNotifyVO);
            int refundCount = refundInfoMapper.updateRefundInfoByNo(refundInfo);
            if (refundCount < 1) {
                log.info("微信退款通知，记录专家咨询订单微信退款单信息失败，订单编号 =====> {}", refundNotifyVO.getOutTradeNo());
            }
        }
        if (RefundStatusEnum.CLOSED.getInfo().equals(refundNotifyVO.getRefundStatus())) {
            log.info("当前商品退款单已经关闭，订单号 ====> {}, 退款单号 =====> {}", refundNotifyVO.getOutTradeNo(), refundNotifyVO.getOutRefundNo());
        }
        if (RefundStatusEnum.ABNORMAL.getInfo().equals(refundNotifyVO.getRefundStatus())) {
            log.info("商品订单退款异常，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，可前往【商户平台—>交易中心】，手动处理此笔退款，订单号 ====> {}, 退款单号 =====> {}", refundNotifyVO.getOutTradeNo(), refundNotifyVO.getOutRefundNo());
        }
    }

    /**
     * 构建退款单信息
     *
     * @param plainText      退款通知解密的明文信息
     * @param refundNotifyVO 通知参数
     * @return 结果
     */
    private RefundInfo buildRefundInfo(String plainText, WeChatRefundNotifyVO refundNotifyVO) {
        RefundInfo refundInfo = new RefundInfo();
        refundInfo.setWechatRefundStatus(StringUtils.isBlank(refundNotifyVO.getRefundStatus()) ? "" : refundNotifyVO.getRefundStatus());
        refundInfo.setSuccessTime(LocalDateTime.parse(StringUtils.isBlank(refundNotifyVO.getSuccessTime()) ? "" : refundNotifyVO.getSuccessTime(), DateTimeFormatter.ISO_DATE_TIME));
        refundInfo.setRefundNotifyContent(plainText);
        refundInfo.setOrderNo(StringUtils.isBlank(refundNotifyVO.getOutTradeNo()) ? "" : refundNotifyVO.getOutTradeNo());
        refundInfo.setOutRefundNo(StringUtils.isBlank(refundNotifyVO.getOutRefundNo()) ? "" : refundNotifyVO.getOutRefundNo());
        return refundInfo;
    }

    /**
     * 处理学习培训订单回调信息
     *
     * @param trainingOrder  学习培训订单信息
     * @param plainText      明文
     * @param refundNotifyVO 退款回调信息
     */
    private void handleRefundTrainingOrderNo(TrainingOrder trainingOrder, String plainText, WeChatRefundNotifyVO refundNotifyVO) {
        if (RefundStatusEnum.SUCCESS.getInfo().equals(refundNotifyVO.getRefundStatus())
                && StringUtils.isNotBlank(trainingOrder.getTrainingOrderStatus())
                && !(TrainingOrderStatusEnum.REFUNDED.getInfo().equals(trainingOrder.getTrainingOrderStatus()))) {
            int updateCount = trainingOrderMapper.updateTrainingOrderStatus(TrainingOrderStatusEnum.REFUNDED.getInfo(), trainingOrder.getTrainingOrderNo());
            if (updateCount < 1) {
                log.info("微信退款通知，修改学习培训订单状态失败，订单编号 =====> {}", refundNotifyVO.getOutTradeNo());
            }
            //修改退款信息
            RefundInfo refundInfo = buildRefundInfo(plainText, refundNotifyVO);
            int refundCount = refundInfoMapper.updateRefundInfoByNo(refundInfo);
            if (refundCount < 1) {
                log.info("微信退款通知，记录学习培训微信退款单信息失败，订单编号 =====> {}", refundNotifyVO.getOutTradeNo());
            }
        }
        if (RefundStatusEnum.CLOSED.getInfo().equals(refundNotifyVO.getRefundStatus())) {
            log.info("当前学习培训退款单已经关闭，订单号 ====> {}, 退款单号 =====> {}", refundNotifyVO.getOutTradeNo(), refundNotifyVO.getOutRefundNo());
        }
        if (RefundStatusEnum.ABNORMAL.getInfo().equals(refundNotifyVO.getRefundStatus())) {
            log.info("学习培训订单退款异常，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，可前往【商户平台—>交易中心】，手动处理此笔退款，订单号 ====> {}, 退款单号 =====> {}", refundNotifyVO.getOutTradeNo(), refundNotifyVO.getOutRefundNo());
        }
    }
}
