package com.yonge.cooleshow.biz.dal.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yonge.cooleshow.biz.dal.dao.UserOrderDao;
import com.yonge.cooleshow.biz.dal.dto.UserAccountRecordDto;
import com.yonge.cooleshow.biz.dal.dto.req.OrderPayReq;
import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
import com.yonge.cooleshow.biz.dal.dto.search.OrderSearch;
import com.yonge.cooleshow.biz.dal.entity.ActivityPlan;
import com.yonge.cooleshow.biz.dal.entity.ActivityRegistration;
import com.yonge.cooleshow.biz.dal.entity.CourseGroup;
import com.yonge.cooleshow.biz.dal.entity.PlatformCashAccountRecord;
import com.yonge.cooleshow.biz.dal.entity.UserAccountRecord;
import com.yonge.cooleshow.biz.dal.entity.UserOrder;
import com.yonge.cooleshow.biz.dal.entity.UserOrderPayment;
import com.yonge.cooleshow.biz.dal.enums.AccountBizTypeEnum;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.enums.GoodTypeEnum;
import com.yonge.cooleshow.biz.dal.enums.InOrOutEnum;
import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
import com.yonge.cooleshow.biz.dal.enums.coupon.CouponCategoryEnum;
import com.yonge.cooleshow.biz.dal.enums.coupon.CouponUseStateEnum;
import com.yonge.cooleshow.biz.dal.queryInfo.CouponInfoQuery;
import com.yonge.cooleshow.biz.dal.service.ActivityEvaluationRecordService;
import com.yonge.cooleshow.biz.dal.service.ActivityPlanService;
import com.yonge.cooleshow.biz.dal.service.ActivityRegistrationService;
import com.yonge.cooleshow.biz.dal.service.ActivityUserRewardService;
import com.yonge.cooleshow.biz.dal.service.CouponInfoService;
import com.yonge.cooleshow.biz.dal.service.CourseGroupService;
import com.yonge.cooleshow.biz.dal.service.CourseScheduleService;
import com.yonge.cooleshow.biz.dal.service.MemberPriceSettingsService;
import com.yonge.cooleshow.biz.dal.service.MusicSheetService;
import com.yonge.cooleshow.biz.dal.service.PianoRoomBuyRecordService;
import com.yonge.cooleshow.biz.dal.service.PlatformCashAccountRecordService;
import com.yonge.cooleshow.biz.dal.service.SysConfigService;
import com.yonge.cooleshow.biz.dal.service.UserAccountService;
import com.yonge.cooleshow.biz.dal.service.UserOrderDetailService;
import com.yonge.cooleshow.biz.dal.service.UserOrderPaymentService;
import com.yonge.cooleshow.biz.dal.service.UserOrderService;
import com.yonge.cooleshow.biz.dal.service.VideoLessonPurchaseRecordService;
import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
import com.yonge.cooleshow.biz.dal.vo.UserOrderVo;
import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
import com.yonge.cooleshow.biz.dal.vo.res.OrderPayRes;
import com.yonge.cooleshow.biz.dal.wrapper.coupon.CouponOrderWrapper;
import com.yonge.cooleshow.common.constant.SysConfigConstant;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.enums.ActivityResourceEnum;
import com.yonge.cooleshow.common.enums.CacheNameEnum;
import com.yonge.cooleshow.common.enums.PostStatusEnum;
import com.yonge.cooleshow.common.service.IdGeneratorService;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.result.BaseResult;
import com.yonge.toolset.base.util.StringUtil;
import com.yonge.toolset.payment.base.enums.OpenEnum;
import com.yonge.toolset.payment.base.enums.PaymentClientEnum;
import com.yonge.toolset.payment.base.enums.TradeStatusEnum;
import com.yonge.toolset.payment.base.model.Payment;
import com.yonge.toolset.payment.base.model.callback.ExecutePaymentCallBack;
import com.yonge.toolset.payment.base.model.callback.PaymentCallBack;
import com.yonge.toolset.payment.core.props.PaymentProperties;
import com.yonge.toolset.payment.core.service.PaymentClient;
import com.yonge.toolset.payment.util.DistributedLock;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;

@Slf4j
@Service
public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> implements UserOrderService {

    @Autowired
    private MemberPriceSettingsService memberPriceSettingsService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private UserOrderDetailService orderDetailService;
    @Autowired
    private UserOrderPaymentService orderPaymentService;
    @Autowired
    private PaymentClient paymentClient;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private CourseGroupService courseGroupService;
    @Autowired
    private CourseScheduleService scheduleService;
    @Autowired
    private VideoLessonPurchaseRecordService recordService;
    @Autowired
    private MusicSheetService musicSheetService;
    @Autowired
    private PianoRoomBuyRecordService pianoRoomBuyRecordService;
    @Autowired
    private PlatformCashAccountRecordService platformCashAccountRecordService;
    @Autowired
    private UserAccountService userAccountService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private PaymentProperties paymentProperties;

    @Autowired
    private ActivityEvaluationRecordService activityEvaluationRecordService;

    @Autowired
    private ActivityRegistrationService activityRegistrationService;

    @Autowired
    private ActivityPlanService activityPlanService;

    @Autowired
    private ActivityUserRewardService activityUserRewardService;
    @Autowired
    private CouponInfoService couponInfoService;

    //验证订单是否可以下单,获取订单金额信息
    private static final Map<GoodTypeEnum, Function<OrderReq.OrderReqInfo, HttpResponseResult<OrderCreateRes>>> orderCreate = new HashMap<>();
    //插入订单后执行
    private static final Map<GoodTypeEnum, Consumer<UserOrderDetailVo>> orderAfter = new HashMap<>();
    //订单完成后执行
    private static final Map<GoodTypeEnum, Consumer<UserOrderDetailVo>> orderSuccess = new HashMap<>();
    //订单取消后执行
    private static final Map<GoodTypeEnum, Consumer<UserOrderDetailVo>> orderCancel = new HashMap<>();

    @PostConstruct
    private void init() {
        /**********订单生成前******************/
        //vip开通缴费
        orderCreate.put(GoodTypeEnum.VIP, memberPriceSettingsService::orderCreate);
        //直播课程购买
        orderCreate.put(GoodTypeEnum.LIVE, courseGroupService::buyLiveCourse);
        //陪练课购买
        orderCreate.put(GoodTypeEnum.PRACTICE, scheduleService::buyPracticeCourse);
        //视频课购买
        orderCreate.put(GoodTypeEnum.VIDEO, recordService::buyVideoCourse);
        //曲目购买
        orderCreate.put(GoodTypeEnum.MUSIC, musicSheetService::buyMusicSheetCheck);
        // 专辑购买
        orderCreate.put(GoodTypeEnum.ALBUM, musicSheetService::buyMusicSheetCheck);
        //琴房时长
        orderCreate.put(GoodTypeEnum.PINAO_ROOM, pianoRoomBuyRecordService::orderCreate);
        //活动报名
        orderCreate.put(GoodTypeEnum.ACTI_REGIST, activityPlanService::orderCreate);

        /**********订单生成后******************/
        //曲目购买
        orderAfter.put(GoodTypeEnum.MUSIC, musicSheetService::orderAfterSheet);
        // 专辑购买
        orderAfter.put(GoodTypeEnum.ALBUM, musicSheetService::orderAfterSheet);

        /**********订单完成后******************/
        //vip开通缴费
        orderSuccess.put(GoodTypeEnum.VIP, memberPriceSettingsService::orderSuccess);
        //直播课程购买
        orderSuccess.put(GoodTypeEnum.LIVE, courseGroupService::buyLiveCourseSuccess);
        //陪练课购买
        orderSuccess.put(GoodTypeEnum.PRACTICE, scheduleService::buyPracticeCourseSuccess);
        //视频课购买
        orderSuccess.put(GoodTypeEnum.VIDEO, recordService::buyVideoCourseSuccess);
        //曲目购买
        orderSuccess.put(GoodTypeEnum.MUSIC, musicSheetService::buyMusicSheetSuccess);
        // 专辑购买
        orderSuccess.put(GoodTypeEnum.ALBUM, musicSheetService::buyMusicSheetSuccess);
        //琴房时长
        orderSuccess.put(GoodTypeEnum.PINAO_ROOM, pianoRoomBuyRecordService::orderSuccess);
        //活动报名
        orderSuccess.put(GoodTypeEnum.ACTI_REGIST, activityPlanService::orderSuccess);

        /**********订单取消后******************/
        //陪练课购买
        orderCancel.put(GoodTypeEnum.PRACTICE, scheduleService::buyPracticeCourseFailed);
        //视频课购买
        orderCancel.put(GoodTypeEnum.VIDEO, recordService::buyVideoCourseFailed);
        //直播课购买
        orderCancel.put(GoodTypeEnum.LIVE, courseGroupService::buyLiveCourseCancel);
        // 曲目购买
        orderCancel.put(GoodTypeEnum.MUSIC, musicSheetService::buyMusicSheetCancel);
        // 专辑购买
        orderCancel.put(GoodTypeEnum.ALBUM, musicSheetService::buyMusicSheetCancel);
    }

    @Override
    public UserOrderVo detail(Long id) {
        UserOrderVo userOrderVo = baseMapper.detailById(id);
        if (null != userOrderVo) {
            userOrderVo.setOrderDetailList(orderDetailService.getOrderDetilListByOrderNo(userOrderVo.getOrderNo()));
        }
        return userOrderVo;
    }

    @Override
    public UserOrderVo detail(String orderNo, Long userId) {
        UserOrder param = new UserOrder();
        param.setUserId(userId);
        param.setOrderNo(orderNo);
        UserOrderVo userOrderVo = baseMapper.detailByOrderNo(param);
        if (null != userOrderVo) {
            userOrderVo.setOrderDetailList(orderDetailService.getOrderDetilListByOrderNo(userOrderVo.getOrderNo()));
        }
        return userOrderVo;
    }

    @Override
    public UserOrderVo detailApp(UserOrder param) {
        UserOrderVo userOrderVo = baseMapper.detailApp(param);
        if (null != userOrderVo) {
            userOrderVo.setFeeAmt(null);
            userOrderVo.setPlantformFee(null);
            List<UserOrderDetailVo> orderDetilList = orderDetailService.getOrderDetilListByOrderNo(userOrderVo.getOrderNo());
            orderDetilList.forEach(o -> {
                o.setPlantformFee(null);
                o.setPlantformFeeRate(null);
            });
            userOrderVo.setOrderDetailList(orderDetilList);

            // 计算优惠券金额
            CouponOrderWrapper couponOrderWrapper  = couponInfoService.queryUserOrderCouponInfo(param.getUserId(),
                    CouponInfoQuery.CouponOrderQuery.builder()
                            .clientType(userOrderVo.getOrderClient())
                            .orderNo(param.getOrderNo())
                            .amount(userOrderVo.getExpectPrice().doubleValue())
                            .build());
            userOrderVo.setDiscountPrice(BigDecimal.valueOf(couponOrderWrapper.getDiscountedPrices()));
        }
        return userOrderVo;
    }

    @Override
    public UserOrderVo getUserOrderByPaymentNoOrTransNo(String paymentNo, String transNo) {
        return baseMapper.getUserOrderByPaymentNoOrTransNo(paymentNo, transNo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult<Boolean> orderCancel(OrderPayReq payReq) {
        UserOrderVo detail = detail(payReq.getOrderNo(), payReq.getUserId());
        if (null == detail) {
            return HttpResponseResult.failed("未找到订单信息");
        }
        if (!OrderStatusEnum.WAIT_PAY.equals(detail.getStatus())
                && !OrderStatusEnum.PAYING.equals(detail.getStatus())) {
            return HttpResponseResult.failed("订单已关闭");
        }
        //关闭或完成订单
        closeOrSuccessOrder(payReq.getOrderNo(), StringUtil.isEmpty(payReq.getReason()) ? "订单取消" : payReq.getReason());
        return HttpResponseResult.succeed(true);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setSuccessStatus() {
        OrderSearch query = new OrderSearch();
        query.setStatus("WAIT_PAY,PAYING");
        List<UserOrderVo> userOrderVos = selectAllList(query);
         for (UserOrderVo userOrderVo : userOrderVos) {
             DistributedLock.of(redissonClient)
                     .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(userOrderVo.getOrderNo())
                             , () -> testOrderSuccess(userOrderVo.getOrderNo()), 60L, TimeUnit.SECONDS);
        }
    }

    @Override
    public List<UserOrder> selectUnRecordTimeOrder(OrderSearch query) {
        return baseMapper.selectUnRecordTimeOrder(query);
    }

    @Override
    public Integer updateStatusByOrderNo(String orderNo, String orderStatus) {
        return baseMapper.updateStatusByOrderNo(orderNo, orderStatus);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean setOrderStatus(UserOrder param) {
        String orderNo = param.getOrderNo();
        OrderStatusEnum orderStatus = param.getStatus();

        UserOrderVo detail = detail(orderNo, null);
        if (OrderStatusEnum.WAIT_PAY.equals(detail.getStatus())
                || OrderStatusEnum.PAYING.equals(detail.getStatus())) {

            if (OrderStatusEnum.CLOSE.equals(orderStatus)) {
                doOrderCancel(detail, orderStatus, "测试接口-订单关闭");
            }
            if (OrderStatusEnum.FAIL.equals(orderStatus)) {
                doOrderCancel(detail, orderStatus, "测试接口-订单交易失败");
            }
            if (OrderStatusEnum.PAID.equals(orderStatus)) {
                testOrderSuccess(detail.getOrderNo());
            }
        }
        return true;
    }


    @Override
    public IPage<UserOrderVo> selectPage(IPage<UserOrderVo> page, OrderSearch query) {
        return page.setRecords(baseMapper.selectPage(page, query));
    }

    @Override
    public List<UserOrderVo> selectAllList(OrderSearch query) {
        return baseMapper.selectAllList(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult<UserOrder> executeOrder(OrderReq orderReq) {
        long start = System.currentTimeMillis();
        log.info("订单[创建订单] Req：{}", JSONObject.toJSONString(orderReq));
        //订单号生成
        Long orderNo = idGeneratorService.generatorId("orderNo");
        orderReq.setOrderNo(Long.toString(orderNo));

        //分润人为自己,不是分润订单
        // if (null != orderReq.getRecomUserId() && orderReq.getUserId().equals(orderReq.getRecomUserId())) {
        //     orderReq.setRecomUserId(null);
        // }

        //验证参数,必须验证参数
        BigDecimal actualPrice = BigDecimal.ZERO;
        // 订单优惠券信息
        CouponOrderWrapper couponOrderWrapper = CouponOrderWrapper.builder()
                .discountedPrices(0D)
                .couponInfos(Lists.newArrayList())
                .build();

        for (OrderReq.OrderReqInfo info : orderReq.getOrderInfos()) {
            Function<OrderReq.OrderReqInfo, HttpResponseResult<OrderCreateRes>> createFunction = orderCreate.get(info.getGoodType());
            if (Objects.isNull(createFunction)) {
                return HttpResponseResult.failed("订单商品信息获取失败");
            }
            info.setOrderNo(orderReq.getOrderNo());
            info.setOrderType(orderReq.getOrderType());
            Long subOrderNo = idGeneratorService.generatorId("subOrderNo");
            info.setSubOrderNo(Long.toString(subOrderNo));
            info.setUserId(orderReq.getUserId());
            info.setRecomUserId(orderReq.getRecomUserId());
            info.setActivityId(orderReq.getActivityId());
            info.setActualPrice(orderReq.getActualPrice());
            HttpResponseResult<OrderCreateRes> createResult = createFunction.apply(info);
            OrderCreateRes createRes = createResult.getData();
            if (!createResult.getStatus() || null == createRes || !createRes.getRes()) {
                log.info("订单[创建订单] Res：{}", JSONObject.toJSONString(createResult));
                return HttpResponseResult.failed(StringUtil.isEmpty(createResult.getMsg()) ? "订单商品信息获取失败" : createResult.getMsg());
            }
            createRes.setGoodType(info.getGoodType());
            BigDecimal couponAmount = BigDecimal.ZERO;
            if (createRes.getCouponAmount() != null) {
                couponAmount = createRes.getCouponAmount();
            }

            // 计算优惠券金额
            if (StringUtils.isNotEmpty(orderReq.getCouponId())) {

                couponOrderWrapper = couponInfoService.queryUserOrderCouponInfo(orderReq.getUserId(),
                        CouponInfoQuery.CouponOrderQuery.builder()
                                .clientType(orderReq.getOrderClient())
                                .couponTypes(CouponCategoryEnum.getCategory(orderReq.getOrderType().getCode()))
                                .useState(CouponUseStateEnum.USABLE)
                                .timestamp(DateTime.now().getMillis())
                                .amount(createRes.getExpectPrice().doubleValue())
                                .build()
                                .issueIds(orderReq.getCouponId()));
            }

            //log.info("executeOrder couponId={}, wrapper={}", orderReq.getCouponId(), couponOrderWrapper.jsonString());

            // 优惠券优惠金额，暂时为0
            couponAmount =couponAmount.add(BigDecimal.valueOf(couponOrderWrapper.getDiscountedPrices()));

            if (couponAmount.compareTo(createRes.getExpectPrice()) > 0 ){
                couponAmount = createRes.getExpectPrice();
            }
            createRes.setActualPrice(createRes.getExpectPrice().subtract(couponAmount).setScale(2, RoundingMode.HALF_UP));
            createRes.setCouponAmount(couponAmount);
            //累计实际支付金额
            actualPrice = actualPrice.add(createRes.getActualPrice());
            orderReq.setActivityId(createRes.getActivityId());
            orderReq.setRewardId(createRes.getRewardId());

            info.setCreateRes(createRes);
        }

        //验证金额
        if (actualPrice.setScale(2, RoundingMode.HALF_UP)
                .compareTo(orderReq.getActualPrice().setScale(2, RoundingMode.HALF_UP)) != 0) {
            throw new BizException("订单金额校验不通过");
        }

        //验证成功后，订单入库
        UserOrderVo orderVo = insertOrder(orderReq);

        // 更新用户订单优惠券使用状态
        if (CollectionUtils.isNotEmpty(couponOrderWrapper.getCouponInfos())) {

            couponOrderWrapper.useType(CouponCategoryEnum.goodTypeTo(orderReq.getOrderType().getCode()));
            couponInfoService.updateUserOrderCouponInfo(couponOrderWrapper.orderNo(orderReq.getOrderNo()));
        }

        List<UserOrderDetailVo> orderDetailList = orderVo.getOrderDetailList();
        for (UserOrderDetailVo orderDetailVo : orderDetailList) {
            orderDetailVo.setUserId(orderReq.getUserId());
            orderDetailVo.setOrderId(orderVo.getId());
            orderDetailVo.setRecomUserId(orderReq.getRecomUserId());
            orderDetailVo.setOrderClient(orderVo.getOrderClient());
            Consumer<UserOrderDetailVo> afterFunction = orderAfter.get(orderDetailVo.getGoodType());
            if (!Objects.isNull(afterFunction)) {
                afterFunction.accept(orderDetailVo);
            }
        }
        log.info("下单请求 start is {} end is {}", start, System.currentTimeMillis());

        //判断订单是否是无需支付的订单，若是，则直接完成订单
        if (BigDecimal.ZERO.compareTo(orderVo.getActualPrice()) == 0) {
            orderSuccess(orderVo);
        }
        return HttpResponseResult.succeed(orderVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult<OrderPayRes> orderPay(OrderPayReq payReq) {
        //查询订单
        UserOrderVo detail = detail(payReq.getOrderNo(), payReq.getUserId());
        if (null == detail || !payReq.getUserId().equals(detail.getUserId())) {
            return HttpResponseResult.failed("订单不存在");
        }
        //查询付款单
        if (!OrderStatusEnum.WAIT_PAY.equals(detail.getStatus())
                && !OrderStatusEnum.PAYING.equals(detail.getStatus())) {
            return HttpResponseResult.failed("订单状态异常");
        }
        try {
            return doOrderPay(payReq, detail);
        } catch (BizException e) {
            return HttpResponseResult.failed(e.getMessage());
        } catch (Exception e) {
            return HttpResponseResult.failed("付款失败");
        }
    }

    @Override
    public HttpResponseResult<UserOrderVo> getPendingOrder(OrderSearch query) {
        UserOrderVo userOrderVo = baseMapper.getPendingOrder(query);
        if (null != userOrderVo) {
            userOrderVo.setOrderDetailList(orderDetailService.getOrderDetilListByOrderNo(userOrderVo.getOrderNo()));
        }
        return HttpResponseResult.succeed(userOrderVo);
    }

    @Override
    public void pollingOrder() {
        //查询半小时前创建的并且还未完成的订单 WAIT_PAY 待支付订单 PAYING 支付中订单
        OrderSearch search = new OrderSearch();
        search.setStatus(OrderStatusEnum.WAIT_PAY.getCode());
        search.setEndTime(LocalDateTime.now().minusMinutes(30));
        //查询待支付订单
        List<UserOrderVo> waitPayOrderList = baseMapper.selectAllList(search);
        for (UserOrderVo orderVo : waitPayOrderList) {
            //取消订单要获取锁，防止在轮询取消时，用户修改订单状态
            boolean b = DistributedLock.of(redissonClient)
                    .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(orderVo.getOrderNo())
                            , () -> pollingCancelOrder(orderVo.getOrderNo()), 60L, TimeUnit.SECONDS);
        }

        search.setStatus(OrderStatusEnum.PAYING.getCode());
        search.setEndTime(LocalDateTime.now().minusMinutes(120));
        //查询待支付中订单
        List<UserOrderVo> payingOrderList = baseMapper.selectPendingList(search);
        for (UserOrderVo orderVo : payingOrderList) {
            //取消订单要获取锁，防止在轮询取消时，用户修改订单状态
            DistributedLock.of(redissonClient)
                    .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(orderVo.getOrderNo())
                            , () -> pollingCancelOrder(orderVo.getOrderNo()), 60L, TimeUnit.SECONDS);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    void pollingCancelOrder(String orderNo) {
        closeOrSuccessOrder(orderNo, "订单超时");
    }

    private void closeOrSuccessOrder(String orderNo, String reason) {
        UserOrderVo detail = detail(orderNo, null);
        if (null == detail) {
            return;
        }
        if (!OrderStatusEnum.WAIT_PAY.equals(detail.getStatus())
                && !OrderStatusEnum.PAYING.equals(detail.getStatus())) {
            return;
        }
        UserOrderPayment userOrderPayment = orderPaymentService.detailByTransNoOrPaymentNo(detail.getTransNo(), detail.getPaymentNo());
        if (null == userOrderPayment) {
            //关闭订单
            doOrderCancel(detail, OrderStatusEnum.CLOSE, reason);
        } else if (TradeStatusEnum.pending.equals(userOrderPayment.getStatus())) {
            Payment param = new Payment(detail.getOpenType(),
                    PaymentClientEnum.valueOf(userOrderPayment.getPaymentClient()), detail.getPayChannel());
            param.setId(detail.getTransNo());
            param.setPaymentNo(detail.getPaymentNo());
            BaseResult<Payment> res = paymentClient.queryPayment(param);
            Payment queryPaymentData = res.getData();

            //支付成功
            if (res.getStatus() && TradeStatusEnum.succeeded.getCode().equals(queryPaymentData.getStatus())
                    && (OrderStatusEnum.WAIT_PAY.equals(detail.getStatus()) || OrderStatusEnum.PAYING.equals(detail.getStatus()))) {
                //订单已经完成，则完成订单
                orderSuccess(detail);
                //付款单改为已完成状态
                userOrderPayment.setTransNo(queryPaymentData.getId());
                userOrderPayment.setStatus(TradeStatusEnum.succeeded);
                userOrderPayment.setUpdateTime(new Date());
                userOrderPayment.setArrivalTime(new Date());
                userOrderPayment.setBackPayAmt(
                        new BigDecimal(queryPaymentData.getPayAmt()));

                ExecutePaymentCallBack executePaymentCallBack = queryPaymentData.getExecutePaymentCallBack();
                if (null != executePaymentCallBack) {
                    userOrderPayment.setArrivalTime(executePaymentCallBack.getTradeTime());
                    userOrderPayment.setBackPayAmt(
                            new BigDecimal(executePaymentCallBack.getPayAmt()));
                    userOrderPayment.setFeeAmt(new BigDecimal(executePaymentCallBack.getFeeAmt()));
                }
                orderPaymentService.updateById(userOrderPayment);
            } else {
                //关闭订单付款单
                Boolean close = orderPaymentService.closePaymentAndReqOpen(orderNo, reason);
                if (close) {
                    //关闭订单
                    doOrderCancel(detail, OrderStatusEnum.CLOSE, reason);
                }
            }
        } else if (TradeStatusEnum.succeeded.equals(userOrderPayment.getStatus())) {
            //订单已经完成，则完成订单
            orderSuccess(detail);
        } else if (TradeStatusEnum.failed.equals(userOrderPayment.getStatus())) {
            //入订单付款表，同时修改订单状态
            doOrderCancel(detail, OrderStatusEnum.FAIL, userOrderPayment.getPayFailMsg());
        } else if (TradeStatusEnum.close.equals(userOrderPayment.getStatus())) {
            //关闭订单
            doOrderCancel(detail, OrderStatusEnum.CLOSE, reason);
        }
    }

    /**
     * 判断订单是否完成，若订单已完成则完成订单
     *
     * @param orderNo
     * @return 可以继续支付 true
     */
    private Boolean checkAndSuccessOrder(String orderNo) {
        UserOrderVo detail = detail(orderNo, null);
        if (null == detail) {
            return true;
        }
        if (!OrderStatusEnum.WAIT_PAY.equals(detail.getStatus())
                && !OrderStatusEnum.PAYING.equals(detail.getStatus())) {
            return false;
        }
        UserOrderPayment userOrderPayment = orderPaymentService.detailByTransNoOrPaymentNo(detail.getTransNo(), detail.getPaymentNo());
        if (null == userOrderPayment) {
            return true;
        }

        Payment param = new Payment(detail.getOpenType(),
                PaymentClientEnum.valueOf(userOrderPayment.getPaymentClient()), detail.getPayChannel());
        param.setId(detail.getTransNo());
        param.setPaymentNo(detail.getPaymentNo());
        BaseResult<Payment> res = paymentClient.queryPayment(param);
        Payment queryPaymentData = res.getData();

        //支付成功
        if (res.getStatus() && TradeStatusEnum.succeeded.getCode().equals(queryPaymentData.getStatus())
                && (OrderStatusEnum.WAIT_PAY.equals(detail.getStatus()) || OrderStatusEnum.PAYING.equals(detail.getStatus()))) {
            //订单已经完成，则完成订单
            orderSuccess(detail, null);
            //付款单改为已完成状态
            userOrderPayment.setTransNo(queryPaymentData.getId());
            userOrderPayment.setStatus(TradeStatusEnum.succeeded);
            userOrderPayment.setUpdateTime(new Date());
            userOrderPayment.setArrivalTime(new Date());
            userOrderPayment.setBackPayAmt(
                    new BigDecimal(queryPaymentData.getPayAmt()));

            ExecutePaymentCallBack executePaymentCallBack = queryPaymentData.getExecutePaymentCallBack();
            if (null != executePaymentCallBack) {
                userOrderPayment.setArrivalTime(executePaymentCallBack.getTradeTime());
                userOrderPayment.setBackPayAmt(
                        new BigDecimal(executePaymentCallBack.getPayAmt()));
                userOrderPayment.setFeeAmt(new BigDecimal(executePaymentCallBack.getFeeAmt()));
            }
            orderPaymentService.updateById(userOrderPayment);
            return false;
        }
        return true;
    }

    private HttpResponseResult<OrderPayRes> doOrderPay(OrderPayReq payReq, UserOrderVo detail) throws Exception {
        Boolean aBoolean = checkAndSuccessOrder(payReq.getOrderNo());
        if (aBoolean) {
            return orderPaymentService.createOrderPayment(payReq, detail);
        } else {
            return HttpResponseResult.failed("订单状态异常");
        }

    }

    /***
     * 订单入库
     * @author liweifan
     * @param: orderReq
     * @updateTime 2022/3/31 16:15
     * @return: com.yonge.cooleshow.biz.dal.entity.Order
     */
    private UserOrderVo insertOrder(OrderReq orderReq) {
        UserOrder userOrder = new UserOrder();
        userOrder.setRewardId(orderReq.getRewardId());
        userOrder.setActivityId(orderReq.getActivityId());
        userOrder.setOrderNo(orderReq.getOrderNo());
        userOrder.setUserId(orderReq.getUserId());
        userOrder.setOrderName(orderReq.getOrderName());
        userOrder.setOrderType(orderReq.getOrderType());
        userOrder.setOrderClient(orderReq.getOrderClient());
        userOrder.setRecomUserId(orderReq.getRecomUserId());

        String desc = "";
        if (StringUtil.isEmpty(orderReq.getOrderDesc())) {
            desc += orderReq.getOrderType().getMsg() + "-" + orderReq.getOrderName();
        } else {
            desc = orderReq.getOrderDesc();
        }
        userOrder.setOrderDesc(desc);
        userOrder.setStatus(OrderStatusEnum.WAIT_PAY);
        userOrder.setUserNote(orderReq.getUserNote());
        userOrder.setCreateTime(new Date());

        userOrder.setOriginalPrice(BigDecimal.ZERO);
        userOrder.setExpectPrice(BigDecimal.ZERO);
        userOrder.setActualPrice(BigDecimal.ZERO);
        userOrder.setCouponAmount(BigDecimal.ZERO);
        userOrder.setPlantformFee(BigDecimal.ZERO);
        List<UserOrderDetailVo> orderDetailList = new ArrayList<>();
        for (OrderReq.OrderReqInfo data : orderReq.getOrderInfos()) {
            OrderCreateRes res = data.getCreateRes();

            UserOrderDetailVo orderDetail = new UserOrderDetailVo();
            orderDetail.setOrderNo(data.getOrderNo());
            orderDetail.setOrderType(orderReq.getOrderType());
            orderDetail.setSubOrderNo(data.getSubOrderNo());
            orderDetail.setMerchId(res.getMerchId());
            orderDetail.setGoodType(res.getGoodType());
            orderDetail.setBizId(res.getBizId());
            orderDetail.setBizContent(res.getBizContent());
            orderDetail.setOriginalPrice(null != res.getOriginalPrice() ? res.getOriginalPrice() : BigDecimal.ZERO);
            orderDetail.setExpectPrice(null != res.getExpectPrice() ? res.getExpectPrice() : BigDecimal.ZERO);
            orderDetail.setActualPrice(null != res.getActualPrice() ? res.getActualPrice() : BigDecimal.ZERO);
            orderDetail.setCouponAmount(null != res.getCouponAmount() ? res.getCouponAmount() : BigDecimal.ZERO);

            orderDetail.setGoodNum(null != res.getGoodNum() ? res.getGoodNum() : 1);
            //商品单价计算，使用商品原价计算，退费计算公式（退费金额=实际订单金额-（商品单价 * 已经使用商品数））
            //其中，已经使用的商品单价按照原价算
            orderDetail.setGoodPrice(
                    orderDetail.getOriginalPrice().divide(new BigDecimal(orderDetail.getGoodNum()), 2, RoundingMode.HALF_UP));
            //平台服务费
            BigDecimal serviceFeeRate = getServiceFeeRate(res.getGoodType());
            orderDetail.setPlantformFee(userOrder.getExpectPrice().multiply(serviceFeeRate));
            orderDetail.setPlantformFeeRate(serviceFeeRate);
            orderDetail.setBizParam(res.getBizParam());
            orderDetail.setCreateTime(new Date());

            orderReq.getOrderInfos().forEach(o -> {
                if (o.getGoodType().equals(res.getGoodType())) {
                    orderDetail.setGoodName(o.getGoodName());
                    orderDetail.setBizContent(JSONObject.toJSONString(o.getBizContent()));
                }
            });
            orderDetail.setGoodUrl(getGoodUrlByType(res.getGoodType()));

            orderDetailService.save(orderDetail);
            orderDetailList.add(orderDetail);

            userOrder.setOriginalPrice(userOrder.getOriginalPrice().add(orderDetail.getOriginalPrice()));
            userOrder.setExpectPrice(userOrder.getExpectPrice().add(orderDetail.getExpectPrice()));
            userOrder.setActualPrice(userOrder.getActualPrice().add(orderDetail.getActualPrice()));
            userOrder.setCouponAmount(userOrder.getCouponAmount().add(orderDetail.getCouponAmount()));
            userOrder.setPlantformFee(userOrder.getPlantformFee().add(orderDetail.getPlantformFee()));
        }

        userOrder.setActualPrice(userOrder.getActualPrice());
        userOrder.setCouponAmount(userOrder.getCouponAmount());

        if (userOrder.getActualPrice().subtract(orderReq.getActualPrice()).abs()
                .compareTo(new BigDecimal("0.01")) > 0) {
            throw new BizException("交易金额异常");
        }

        int insert = baseMapper.insert(userOrder);

        if (insert == 0 || null == userOrder.getId()) {
            throw new BizException("创建订单失败");
        }
        UserOrderVo vo = new UserOrderVo();

        BeanUtils.copyProperties(userOrder, vo);
        vo.setOrderDetailList(orderDetailList);
        return vo;
    }

    /***
     * 获取平台服务费率
     * @author liweifan
     * @param: orderTypeEnum
     * @updateTime 2022/3/31 16:49
     * @return: java.math.BigDecimal
     */
    private BigDecimal getServiceFeeRate(GoodTypeEnum goodTypeEnum) {
        String configValue = "0";
        if (GoodTypeEnum.VIDEO.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.VIDEO_LESSON_SERVICE_FEE);
        } else if (GoodTypeEnum.PRACTICE.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.PRACTICE_SERVICE_FEE);
        } else if (GoodTypeEnum.LIVE.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.LIVE_SERVICE_RATE);
        } else if (GoodTypeEnum.MUSIC.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.MUSIC_SHEET_SERVICE_FEE);
        }
        return new BigDecimal(configValue).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
    }

    /***
     * 获取商品图片
     * @author liweifan
     * @param: orderTypeEnum
     * @updateTime 2022/3/31 16:49
     * @return: java.math.BigDecimal
     */
    private String getGoodUrlByType(GoodTypeEnum goodTypeEnum) {
        String configValue = "";
        if (GoodTypeEnum.VIP.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_VIP);
        } else if (GoodTypeEnum.VIDEO.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_VIDEO);
        } else if (GoodTypeEnum.PRACTICE.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_PRACTICE);
        } else if (GoodTypeEnum.LIVE.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_LIVE);
        } else if (GoodTypeEnum.MUSIC.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_MUSIC);
        } else if (GoodTypeEnum.PINAO_ROOM.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_PIANO_ROOM);
        } else if (GoodTypeEnum.ACTI_REGIST.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_ACTI_REGIST);
        } else if (GoodTypeEnum.ALBUM.equals(goodTypeEnum)) {
            configValue = sysConfigService.findConfigValue(SysConfigConstant.GOOD_LOGO_ALBUM);
        }
        return configValue;
    }

    private Boolean checkPositiveOrZero(BigDecimal amount) {
        if (null == amount) {
            return false;
        }
        if (amount.doubleValue() < 0) {
            return false;
        }
        return true;
    }

    /***
     * 取消订单
     * @author liweifan
     * @param: userOrder
     * @updateTime 2022/4/13 17:23
     */
    @Transactional(rollbackFor = Exception.class)
    public void doOrderCancel(UserOrderVo userOrder, OrderStatusEnum orderStatus, String reason) {
        //已经完成过的订单，不能再取消
        if (!OrderStatusEnum.WAIT_PAY.equals(userOrder.getStatus())
                && !OrderStatusEnum.PAYING.equals(userOrder.getStatus())) {
            return;
        }
        //状态只能是关闭和失败
        if (!OrderStatusEnum.CLOSE.equals(orderStatus)
                && !OrderStatusEnum.FAIL.equals(orderStatus)) {
            return;
        }

        List<UserOrderDetailVo> orderDetailList = orderDetailService.getOrderDetilListByOrderNo(userOrder.getOrderNo());
        for (UserOrderDetailVo orderDetailVo : orderDetailList) {
            orderDetailVo.setUserId(userOrder.getUserId());
            orderDetailVo.setOrderId(userOrder.getId());

            //调用业务
            Consumer<UserOrderDetailVo> userOrderVoConsumer = orderCancel.get(orderDetailVo.getGoodType());
            if (!Objects.isNull(userOrderVoConsumer)) {
                userOrderVoConsumer.accept(orderDetailVo);
            }
        }
        userOrder.setReason(reason);
        userOrder.setStatus(orderStatus);
        userOrder.setUpdateTime(new Date());
        baseMapper.updateById(userOrder);

        // 重置优惠券状态
        couponInfoService.updateUserOrderCouponInfo(CouponOrderWrapper.builder()
                        .orderNo(userOrder.getOrderNo())
                        .reset(true)
                .build());
    }

    private void orderSuccess(UserOrderVo detail) {
        orderSuccess(detail, null);
    }

    /**
     * 订单完成
     *
     * @author liweifan
     * @param: detail
     * @updateTime 2022/4/13 17:17
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderSuccess(UserOrderVo detail, PaymentCallBack data) {
        //订单已完成
        if (!OrderStatusEnum.WAIT_PAY.equals(detail.getStatus())
                && !OrderStatusEnum.PAYING.equals(detail.getStatus())) {
            return;
        }

        //修改订单状态
        Date now = new Date();
        detail.setStatus(OrderStatusEnum.PAID);
        detail.setPayTime(now);
        detail.setUpdateTime(now);
        updateById(detail);

        if (null != data) {
            //更新付款单
            UserOrderPayment orderPayment = orderPaymentService
                    .detailByTransNoOrPaymentNo(data.getId(), data.getPaymentNo());
            if (null != orderPayment) {
                orderPayment.setTransNo(data.getId());
                orderPayment.setStatus(TradeStatusEnum.succeeded);
                orderPayment.setArrivalTime(now);
                orderPayment.setUpdateTime(now);

                if (null != data.getExecutePaymentCallBack()) {
                    orderPayment.setBackPayAmt(
                            new BigDecimal(data.getExecutePaymentCallBack().getPayAmt()));

                    BigDecimal feeAmt = new BigDecimal(data.getExecutePaymentCallBack().getFeeAmt());
                    if (BigDecimal.ZERO.compareTo(feeAmt) == 0) {
                        orderPayment.setFeeAmt(orderPayment.getPayAmt().subtract(orderPayment.getBackPayAmt()));
                    } else {
                        orderPayment.setFeeAmt(feeAmt);
                    }
                }
                orderPaymentService.updateById(orderPayment);
            }
        }

        //调用业务
        List<UserOrderDetailVo> orderDetailList = orderDetailService.getOrderDetilListByOrderNo(detail.getOrderNo());

        for (UserOrderDetailVo orderDetailVo : orderDetailList) {
            orderDetailVo.setUserId(detail.getUserId());
            orderDetailVo.setOrderId(detail.getId());
            orderDetailVo.setRecomUserId(detail.getRecomUserId());
            orderDetailVo.setActivityId(detail.getActivityId());
            orderDetailVo.setRewardId(detail.getRewardId());
            orderDetailVo.setOrderType(detail.getOrderType());
            //调用业务
            Consumer<UserOrderDetailVo> userOrderVoConsumer = orderSuccess.get(orderDetailVo.getGoodType());
            if (!Objects.isNull(userOrderVoConsumer)) {
                userOrderVoConsumer.accept(orderDetailVo);
            }
            //记录平台收入和用户分润收入(未记录卖家收益，卖家收益业务逻辑处理)
            savePlatformAccountRecord(orderDetailVo);
            //清除商家统计缓存
            Long merchId = orderDetailVo.getMerchId();
            if (merchId != null && merchId != 0) {
                redissonClient.getBucket(CacheNameEnum.TEACHER_TOTAL.getRedisKey(merchId)).delete();
            }

            // 记录活动参与
            saveActivityRecord(orderDetailVo);
        }
        //清除买家统计缓存
        if (ClientEnum.STUDENT.getCode().equals(detail.getPaymentClient())) {
            redissonClient.getBucket(CacheNameEnum.STUDENT_TOTAL.getRedisKey(detail.getUserId())).delete();
        } else if (ClientEnum.TEACHER.getCode().equals(detail.getPaymentClient())) {
            redissonClient.getBucket(CacheNameEnum.TEACHER_TOTAL.getRedisKey(detail.getUserId())).delete();
        }
    }

    private void saveActivityRecord(UserOrderDetailVo orderDetailVo) {
        if (orderDetailVo.getActivityId() == null || orderDetailVo.getActivityId() == 0 || orderDetailVo.getRecomUserId() == null) {
            return;
        }
        ActivityRegistration activityRegistration = new ActivityRegistration();
        activityRegistration.setActivityId(orderDetailVo.getActivityId());
        activityRegistration.setOrderNo(orderDetailVo.getOrderNo());
        activityRegistration.setSubOrderNo(orderDetailVo.getSubOrderNo());
        activityRegistration.setUserId(orderDetailVo.getUserId());
        activityRegistration.setCreateTime(new Date());
        activityRegistrationService.save(activityRegistration);
        activityEvaluationRecordService.saveActivityRecord(orderDetailVo.getActivityId(), orderDetailVo.getUserId(),
                                                           orderDetailVo.getRecomUserId(), ActivityResourceEnum.TEACHER);
        activityUserRewardService.saveRewardRecord(orderDetailVo.getActivityId(),orderDetailVo.getRewardId(),orderDetailVo.getUserId());
    }

    /**
     * 记录平台收入和用户分润收入
     *
     * @param orderDetailVo
     */
    @Transactional(rollbackFor = Exception.class)
    public void savePlatformAccountRecord(UserOrderDetailVo orderDetailVo) {
        BigDecimal expectPrice = orderDetailVo.getExpectPrice();
        if (expectPrice.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        //获取账期时间
        Date accountPeriodTime = getAccountPeriodTime(orderDetailVo);

        //平台收入
        //获取平台服务费率
        BigDecimal platformFeeRate = getPlatformFreeByGoodType(orderDetailVo.getGoodType());
        //没有卖家的为平台订单，平台全额收益
        if (null == orderDetailVo.getMerchId() || orderDetailVo.getMerchId().equals(0L)) {
            platformFeeRate = BigDecimal.ONE;
        }
        BigDecimal platformFee = expectPrice.multiply(platformFeeRate).setScale(2, RoundingMode.HALF_UP);
        platformFee = platformFee.subtract(orderDetailVo.getCouponAmount());

        if (platformFee.compareTo(BigDecimal.ZERO) > 0) {
            PlatformCashAccountRecord platformCashAccountRecord;
            if (GoodTypeEnum.PINAO_ROOM.equals(orderDetailVo.getGoodType())) {
                platformCashAccountRecord = new PlatformCashAccountRecord(orderDetailVo.getUserId(), platformFee,
                        InOrOutEnum.IN, PostStatusEnum.RECORDED, AccountBizTypeEnum.PIAON_ROOM, orderDetailVo.getBizId(),
                        orderDetailVo.getOrderNo(), accountPeriodTime);
            } else {
                AccountBizTypeEnum bizTypeEnum = AccountBizTypeEnum.valueOf(orderDetailVo.getGoodType().getCode());
                platformCashAccountRecord = new PlatformCashAccountRecord(orderDetailVo.getUserId(), platformFee,
                        InOrOutEnum.IN, PostStatusEnum.WAIT, bizTypeEnum, orderDetailVo.getBizId(),
                        orderDetailVo.getOrderNo(), accountPeriodTime);
            }
            platformCashAccountRecordService.save(platformCashAccountRecord);

            //卖家不能分润自己 买家和分润人相同，不分润
            if (null != orderDetailVo.getRecomUserId()
                    && !orderDetailVo.getRecomUserId().equals(orderDetailVo.getMerchId())
                    && !orderDetailVo.getUserId().equals(orderDetailVo.getRecomUserId())) {
                //获取分润收益费率
                BigDecimal shareFeeRate = getShareFreeByGoodType(orderDetailVo.getGoodType()
                        , orderDetailVo.getBizId());
                //入老师账户
                BigDecimal shareFee = platformFee.multiply(shareFeeRate).setScale(2, RoundingMode.HALF_UP);
                if (shareFee.compareTo(BigDecimal.ZERO) > 0) {
                    AccountBizTypeEnum bizTypeEnum = AccountBizTypeEnum.valueOf(orderDetailVo.getGoodType().getCode() + "_SHARE");
                    if (null != bizTypeEnum) {
                        //插入分润老师账户变更记录-分润老师预收
                        HttpResponseResult<UserAccountRecord> recomRecordRes = userAccountService.accountRecord(
                                new UserAccountRecordDto(orderDetailVo.getRecomUserId(), PostStatusEnum.WAIT, shareFee, InOrOutEnum.IN,
                                        bizTypeEnum, orderDetailVo.getBizId(), bizTypeEnum.getMsg(), orderDetailVo.getOrderNo(), orderDetailVo.getUserId(), accountPeriodTime));
                        if (recomRecordRes.getStatus()) {
                            //插入平台预支
                            platformCashAccountRecord = new PlatformCashAccountRecord(orderDetailVo.getRecomUserId(), shareFee,
                                    InOrOutEnum.OUT, PostStatusEnum.WAIT, bizTypeEnum, orderDetailVo.getBizId(), orderDetailVo.getOrderNo(), accountPeriodTime);
                            platformCashAccountRecordService.save(platformCashAccountRecord);
                        }
                    }
                }
            }

        }
    }

    /**
     * 获取账期时间
     *
     * @param orderDetailVo
     * @return
     */
    @Override
    public Date getAccountPeriodTime(UserOrderDetailVo orderDetailVo) {
        Calendar instance = Calendar.getInstance();
        GoodTypeEnum goodType = orderDetailVo.getGoodType();

        if (GoodTypeEnum.VIP.equals(goodType)) {
            instance.add(Calendar.DAY_OF_MONTH, Integer.parseInt(sysConfigService.findConfigValue(SysConfigConstant.VIP_ACCOUNT_PERIOD)));
        } else if (GoodTypeEnum.PRACTICE.equals(goodType)) {
            instance.add(Calendar.DAY_OF_MONTH, Integer.parseInt(sysConfigService.findConfigValue(SysConfigConstant.PRACTICE_ACCOUNT_PERIOD)));
        } else if (GoodTypeEnum.LIVE.equals(goodType)) {
            //直播课取直播课成课时间+账期
            CourseGroup byId = courseGroupService.getById(orderDetailVo.getBizId());
            instance.setTime(byId.getSalesEndDate());
            instance.add(Calendar.DAY_OF_MONTH, Integer.parseInt(sysConfigService.findConfigValue(SysConfigConstant.LIVE_ACCOUNT_PERIOD)));
        } else if (GoodTypeEnum.VIDEO.equals(goodType)) {
            instance.add(Calendar.DAY_OF_MONTH, Integer.parseInt(sysConfigService.findConfigValue(SysConfigConstant.VIDEO_ACCOUNT_PERIOD)));
        } else if (GoodTypeEnum.MUSIC.equals(goodType)) {
            instance.add(Calendar.DAY_OF_MONTH, Integer.parseInt(sysConfigService.findConfigValue(SysConfigConstant.MUSIC_ACCOUNT_PERIOD)));
        } else if (GoodTypeEnum.ALBUM.equals(goodType)) {
            instance.add(Calendar.DAY_OF_MONTH, Integer.parseInt(sysConfigService.findConfigValue(SysConfigConstant.ALBUM_ACCOUNT_PERIOD)));
        } else if (GoodTypeEnum.ACTI_REGIST.equals(goodType)) {
            instance.add(Calendar.DAY_OF_MONTH, Integer.parseInt(sysConfigService.findConfigValue(SysConfigConstant.ACTI_REGIST_ACCOUNT_PERIOD)));
        }
        return instance.getTime();
    }

    /**
     * 获取分润收益费率
     *
     * @param goodType
     * @return
     */
    @Override
    public BigDecimal getShareFreeByGoodType(GoodTypeEnum goodType, Long bizId) {
        if (GoodTypeEnum.VIP.equals(goodType)) {
            return getShareFreeByConfigName(SysConfigConstant.VIP_SHARE_FEE);
        }
        if (GoodTypeEnum.LIVE.equals(goodType)) {
            return getShareFreeByConfigName(SysConfigConstant.LIVE_SHARE_FEE);
        }
        if (GoodTypeEnum.VIDEO.equals(goodType)) {
            return getShareFreeByConfigName(SysConfigConstant.VIDEO_SHARE_FEE);
        }
        if (GoodTypeEnum.MUSIC.equals(goodType)) {
            return getShareFreeByConfigName(SysConfigConstant.MUSIC_SHARE_FEE);
        }
        if (GoodTypeEnum.ALBUM.equals(goodType)) {
            return getShareFreeByConfigName(SysConfigConstant.MUSIC_ALBUM_FEE);
        }
        if (GoodTypeEnum.ACTI_REGIST.equals(goodType)) {
            //获取当前活动的分润比例
            ActivityPlan byId = activityPlanService.getById(bizId);
            if (null != byId && null != byId.getShareRate()) {
                return byId.getShareRate().divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
            }
        }
        return BigDecimal.ZERO;
    }

    @Override
    public BigDecimal getShareFreeByConfigName(String configName) {
        return new BigDecimal(sysConfigService.findConfigValue(configName))
                .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
    }

    /**
     * 获取平台服务费率
     *
     * @param goodType
     * @return
     */
    private BigDecimal getPlatformFreeByGoodType(GoodTypeEnum goodType) {
        //会员|琴房时长，平台全额收益
        if (GoodTypeEnum.VIP.equals(goodType) || GoodTypeEnum.PINAO_ROOM.equals(goodType)
                || GoodTypeEnum.ACTI_REGIST.equals(goodType)) {
            return BigDecimal.ONE;
        }
        if (GoodTypeEnum.PRACTICE.equals(goodType)) {
            return new BigDecimal(sysConfigService.findConfigValue(SysConfigConstant.PRACTICE_SERVICE_FEE))
                    .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        }
        if (GoodTypeEnum.LIVE.equals(goodType)) {
            return new BigDecimal(sysConfigService.findConfigValue(SysConfigConstant.LIVE_SERVICE_RATE))
                    .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        }
        if (GoodTypeEnum.VIDEO.equals(goodType)) {
            return new BigDecimal(sysConfigService.findConfigValue(SysConfigConstant.VIDEO_LESSON_SERVICE_FEE))
                    .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        }
        if (GoodTypeEnum.MUSIC.equals(goodType)) {
            return new BigDecimal(sysConfigService.findConfigValue(SysConfigConstant.MUSIC_SHEET_SERVICE_FEE))
                    .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        }
        return BigDecimal.ZERO;
    }

    @Transactional(rollbackFor = Exception.class)
    public void testOrderSuccess(String orderNo) {
        if (StringUtil.isEmpty(orderNo)) {
            return;
        }
        UserOrderVo detail = detail(orderNo, null);
        if (null == detail) {
            return;
        }
        if (!OrderStatusEnum.WAIT_PAY.equals(detail.getStatus())
                && !OrderStatusEnum.PAYING.equals(detail.getStatus())) {
            return;
        }

        //关闭当前正在支付的订单
        orderPaymentService.closePaymentAndReqOpen(detail.getOrderNo(), "交易取消");

        UserOrderPayment orderPayment = new UserOrderPayment();
        OpenEnum openType = OpenEnum.valueOf(paymentProperties.getOpenType());
        orderPayment.setOpenType(openType);

        orderPayment.setOrderNo(detail.getOrderNo());

        //支付订单号生成
        Long paymentNo = idGeneratorService.generatorId("paymentNo");
        orderPayment.setPaymentNo(paymentNo.toString());

        orderPayment.setPayAmt(detail.getActualPrice());
        orderPayment.setStatus(TradeStatusEnum.succeeded);

        //保存新的付款单
        orderPaymentService.save(orderPayment);
        orderSuccess(detail, null);
    }

}