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

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.microsvc.toolkit.middleware.payment.common.api.BasePaymentService;
import com.microsvc.toolkit.middleware.payment.common.api.PaymentServiceContext;
import com.microsvc.toolkit.middleware.payment.common.api.entity.DivideReq;
import com.microsvc.toolkit.middleware.payment.common.api.entity.DivideResp;
import com.microsvc.toolkit.middleware.payment.common.api.enums.PaymentStatus;
import com.yonge.cooleshow.biz.dal.dao.CourseScheduleStudentPaymentDao;
import com.yonge.cooleshow.biz.dal.dao.UserOrderDao;
import com.yonge.cooleshow.biz.dal.dao.VideoLessonGroupDao;
import com.yonge.cooleshow.biz.dal.dao.VideoLessonPurchaseRecordDao;
import com.yonge.cooleshow.biz.dal.dto.UserAccountRecordDto;
import com.yonge.cooleshow.biz.dal.entity.*;
import com.yonge.cooleshow.biz.dal.enums.*;
import com.yonge.cooleshow.biz.dal.enums.album.PurchaseRecordTypeEnum;
import com.yonge.cooleshow.biz.dal.enums.course.CourseRelationTypeEnum;
import com.yonge.cooleshow.biz.dal.mapper.PaymentDivMemberRecordMapper;
import com.yonge.cooleshow.biz.dal.service.*;
import com.yonge.cooleshow.biz.dal.support.WrapperUtil;
import com.yonge.cooleshow.biz.dal.vo.CourseScheduleStudentPaymentVo;
import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
import com.yonge.cooleshow.biz.dal.wrapper.PaymentDivMemberRecordWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.TenantAlbumWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.UserPaymentOrderWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.course.CourseRelationWrapper;
import com.yonge.cooleshow.common.constant.SysConfigConstant;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.enums.EStatus;
import com.yonge.cooleshow.common.enums.PostStatusEnum;
import com.yonge.toolset.base.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 分账子账户记录表
 * 2023-07-28 15:45:03
 */
@Slf4j
@Service
public class PaymentDivMemberRecordServiceImpl extends ServiceImpl<PaymentDivMemberRecordMapper, PaymentDivMemberRecord> implements PaymentDivMemberRecordService {

    @Autowired
    private TenantMemberService tenantMemberService;

    @Autowired
    private PaymentMerchantConfigService paymentMerchantConfigService;

    @Autowired
    private TenantAccountRecordService tenantAccountRecordService;

    @Autowired
    private UserOrderPaymentService userOrderPaymentService;

    @Autowired
    private PaymentDivMemberRecordService paymentDivMemberRecordService;

    @Autowired
    private PlatformCashAccountRecordService platformCashAccountRecordService;

    @Autowired
    private UserOrderService userOrderService;

    @Autowired
    private UserAccountService userAccountService;

    @Autowired
    private TeacherService teacherService;

    @Autowired
    private PaymentServiceContext paymentServiceContext;

    @Autowired
    private MusicSheetService musicSheetService;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private CourseScheduleStudentPaymentDao paymentDao;

    @Autowired
    private CourseScheduleService courseScheduleService;

    @Autowired
    private CourseGroupService courseGroupService;

    @Autowired
    private ImUserFriendService imUserFriendService;

    @Autowired
    private CourseScheduleTeacherSalaryService courseScheduleTeacherSalaryService;

    @Autowired
    private CourseScheduleStudentPaymentService courseScheduleStudentPaymentService;

    @Autowired
    private MusicSheetPurchaseRecordService musicSheetPurchaseRecordService;

    @Autowired
    private VideoLessonPurchaseRecordDao videoLessonPurchaseRecordDao;

    @Autowired
    private UserOrderDao userOrderDao;

    @Autowired
    private VideoLessonGroupDao videoLessonGroupDao;

    @Autowired
    private CourseRelationMusicAlbumService courseRelationMusicAlbumService;

    @Autowired
    private VideoLessonPurchaseRecordService videoLessonPurchaseRecordService;

    @Autowired
    private MemberPriceSettingsService memberPriceSettingsService;
    @Autowired
    private ActivityPlanService activityPlanService;
    @Autowired
    private TenantAlbumService tenantAlbumService;

    @Autowired
    private RedisCacheService redisCacheService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private TenantTeacherAccountRecordService tenantTeacherAccountRecordService;


    /**
     * 查询详情
     *
     * @param id 详情ID
     * @return PaymentDivMemberRecord
     */
    @Override
    public PaymentDivMemberRecord detail(Long id) {

        return baseMapper.selectById(id);
    }

    /**
     * 分页查询
     *
     * @param page  IPage<PaymentDivMemberRecord>
     * @param query PaymentDivMemberRecordWrapper.PaymentDivMemberRecordQuery
     * @return IPage<PaymentDivMemberRecord>
     */
    @Override
    public IPage<PaymentDivMemberRecord> selectPage(IPage<PaymentDivMemberRecord> page, PaymentDivMemberRecordWrapper.PaymentDivMemberRecordQuery query) {

        return page.setRecords(baseMapper.selectPage(page, query));
    }

    /**
     * 添加
     *
     * @param paymentDivMemberRecord PaymentDivMemberRecordWrapper.PaymentDivMemberRecord
     * @return Boolean
     */
    @Override
    public Boolean add(PaymentDivMemberRecordWrapper.PaymentDivMemberRecord paymentDivMemberRecord) {

        return this.save(JSON.parseObject(paymentDivMemberRecord.jsonString(), PaymentDivMemberRecord.class));
    }

    /**
     * 更新
     *
     * @param paymentDivMemberRecord PaymentDivMemberRecordWrapper.PaymentDivMemberRecord
     * @return Boolean
     */
    @Override
    public Boolean update(PaymentDivMemberRecordWrapper.PaymentDivMemberRecord paymentDivMemberRecord) {

        return this.updateById(JSON.parseObject(paymentDivMemberRecord.jsonString(), PaymentDivMemberRecord.class));
    }

    @Override
    public IPage<PaymentDivMemberRecordWrapper.IndexIncomeQueryDto> queryIncome(IPage<PaymentDivMemberRecordWrapper.IndexIncomeQueryDto> page, PaymentDivMemberRecordWrapper.IndexIncomeQuery query) {
        return page.setRecords(baseMapper.queryIncome(page, query));
    }

    @Override
    public PaymentDivMemberRecordWrapper.OrderDetailDto getIncomeOrderDetail(String orderNo, Long tenantId) {
        return baseMapper.getIncomeOrderDetail(orderNo, tenantId);
    }

    @Override
    public PaymentDivMemberRecordWrapper.IndexIncomeSummaryDto incomeSummary(PaymentDivMemberRecordWrapper.IndexIncomeQuery query) {
        List<PaymentDivMemberRecordWrapper.IndexIncomeSummaryDetailDto> incomeSummary = baseMapper.incomeSummary(query);
        PaymentDivMemberRecordWrapper.IndexIncomeSummaryDto result = new PaymentDivMemberRecordWrapper.IndexIncomeSummaryDto();
        if (CollectionUtils.isNotEmpty(incomeSummary)) {
            BigDecimal reduce = incomeSummary.stream().map(e -> e.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            result.setIncomeDtos(incomeSummary);
            result.setTotalIncome(reduce);
        }
        List<PaymentDivMemberRecordWrapper.IndexIncomeSummaryDetailDto> expendSummary = baseMapper.expendSummary(query);
        if (CollectionUtils.isNotEmpty(expendSummary)) {
            BigDecimal reduce = expendSummary.stream().map(e -> e.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            result.setExpendDtos(expendSummary);
            result.setTotalExpend(reduce);
        }
        return result;
    }

    /**
     * 专辑分账
     *
     * @param userPaymentOrder 订单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void tenantAlbum(UserOrderDetailVo userPaymentOrder) {


        // 先计算分账金额，写入流水，最后执行分账，在写入分账数据


        // 分账
        Map<Long, BigDecimal> tenantdivMap = new HashMap<>();
        // 分润
        Map<Long, BigDecimal> teacherMap = new HashMap<>();
        // 老师收入
        Map<Long, BigDecimal> bizMap = new HashMap<>();

        // 计算商品分账数据
        if (userPaymentOrder.getOrderClient().equals(ClientEnum.STUDENT)) {

            // 专辑金额
            TenantAlbumWrapper.TenantAlbumContent tenantAlbumContent = JSON
                    .parseObject(userPaymentOrder.getBizContent(), TenantAlbumWrapper.TenantAlbumContent.class);


//            BigDecimal tenantAmount = tenantAlbumContent.getSalePrice().subtract(tenantAlbumContent.getOriginalPrice())
//                    .multiply(BigDecimal.valueOf(tenantAlbumContent.getBuyMultiple())).setScale(2, RoundingMode.HALF_UP);

            tenantdivMap.merge(tenantAlbumContent.getTenantId(), userPaymentOrder.getActualPrice(), BigDecimal::add);
            tenantdivMap.put(-1L, BigDecimal.ZERO);

        } else {

            tenantdivMap.merge(-1L, userPaymentOrder.getActualPrice(), BigDecimal::add);
        }

        // 计算老师分润数据  平台的真实收益
        BigDecimal platformFee = tenantdivMap.getOrDefault(-1L, BigDecimal.ZERO);

        tenantAlbumService.orderSuccess(userPaymentOrder);

        saveData(userPaymentOrder, tenantdivMap, teacherMap, bizMap ,platformFee);


    }

    /**
     * 曲目分账
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void musicSheet(UserOrderDetailVo userPaymentOrder) {

        // 先计算分账金额，写入流水，最后执行分账，在写入分账数据

        // 分账
        Map<Long, BigDecimal> tenantdivMap = new HashMap<>();
        tenantdivMap.merge(-1L, userPaymentOrder.getActualPrice(), BigDecimal::add);
        // 分润
        Map<Long, BigDecimal> teacherMap = new HashMap<>();
        // 老师收入
        Map<Long, BigDecimal> bizMap = new HashMap<>();

        // 计算商品分账数据
        // 曲目服务费比例
        String musicSheetServiceFee = sysConfigService.findConfigValue(SysConfigConstant.MUSIC_SHEET_SERVICE_FEE);
        BigDecimal serviceFee = new BigDecimal(musicSheetServiceFee).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        //支付金额
        BigDecimal actualPrice = userPaymentOrder.getActualPrice();
        BigDecimal expectPrice = userPaymentOrder.getExpectPrice();

        //服务费  原价的平台服务费 ，减去优惠券金额
        BigDecimal serviceFeeAmount = expectPrice.multiply(serviceFee).subtract(userPaymentOrder.getCouponAmount()).setScale(2, RoundingMode.HALF_UP);
        if (serviceFeeAmount.compareTo(BigDecimal.ZERO) < 0) {
            serviceFeeAmount = BigDecimal.ZERO;
        }

        // 保存购买记录
        musicSheetService.addMusicSheetPurchaseRecord(userPaymentOrder, actualPrice, serviceFeeAmount);

        String userAccountConfig = userPaymentOrder.getAccountConfig();
        UserPaymentOrderWrapper.AccountTenantTo accountTenantTo;
        if (StringUtils.isBlank(userAccountConfig)) {
            accountTenantTo = new UserPaymentOrderWrapper.AccountTenantTo();
        } else {
            accountTenantTo = JSON.parseObject(userAccountConfig, UserPaymentOrderWrapper.AccountTenantTo.class);
        }

        // 曲目判断老师收入
        if (userPaymentOrder.getOrderType().equals(OrderTypeEnum.MUSIC)) {
            MusicSheet musicSheet = musicSheetService.getById(userPaymentOrder.getBizId());
            if (!musicSheet.getSourceType().getCode().equals(SourceTypeEnum.PLATFORM.getCode())) {

                // 老师收入
                BigDecimal teacherAmount = BigDecimal.ONE.subtract(serviceFee).multiply(expectPrice).setScale(2, RoundingMode.HALF_UP);

                // 判断分润给机构 还是给老师
                // 机构ID = 0 老师设置了不分润
                if (accountTenantTo.getIncomeTenant() != null && accountTenantTo.getIncomeTenant() >0) {
                    // 分润给机构
                    tenantdivMap.merge(accountTenantTo.getIncomeTenant(), teacherAmount, BigDecimal::add);
                    tenantdivMap.merge(-1L, teacherAmount, BigDecimal::subtract);
                    serviceFeeAmount = tenantdivMap.get(-1L);
                } else {
                    // 分润给老师
                    bizMap.merge(userPaymentOrder.getBizId(), teacherAmount, BigDecimal::add);
                }
            } else {
                serviceFeeAmount = actualPrice;
            }
        } else {
            serviceFeeAmount = actualPrice;
        }

        // 消息通知
        CompletableFuture.runAsync(() -> {
                    musicSheetService.sendBuyMessage(userPaymentOrder.getMerchId(), userPaymentOrder.getUserId(),
                            userPaymentOrder.getBizId(), userPaymentOrder.getOrderClient(), userPaymentOrder.getOrderType());
                }
        );


        saveData(userPaymentOrder, tenantdivMap, teacherMap, bizMap, serviceFeeAmount);
    }

    private boolean checkSendMessage(Long userId, ClientEnum orderClient) {
        if (orderClient == null) {
            return false;
        }
        if (orderClient.equals(ClientEnum.STUDENT)) {
            Student student = studentService.getById(userId);
            if (student == null) {
                return false;
            } else return student.getTenantId() == -1;
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void practiceCourse(UserOrderDetailVo userPaymentOrder) {


        // 先计算分账金额，写入流水，最后执行分账，在写入分账数据

        // 分账
        Map<Long, BigDecimal> tenantdivMap = new HashMap<>();
        tenantdivMap.merge(-1L, userPaymentOrder.getActualPrice(), BigDecimal::add);
        // 分润
        Map<Long, BigDecimal> teacherMap = new HashMap<>();
        // 老师收入
        Map<Long, BigDecimal> bizMap = new HashMap<>();

        //服务费  原价的平台服务费 ，减去优惠券金额
        BigDecimal serviceFeeAmount = BigDecimal.ZERO;

        log.info("buyPracticeCourseSuccess  param:{}", JSON.toJSONString(userPaymentOrder));
        String orderNo = userPaymentOrder.getOrderNo();
        List<CourseScheduleStudentPaymentVo> paymentList = paymentDao.selectPaymentList(orderNo);
        if (CollectionUtils.isEmpty(paymentList)) {
            throw new BizException("订单不存在!");
        }

        //lock_改为0,课程组状态改为ING
        List<Long> scheduleIds = paymentList.stream().map(CourseScheduleStudentPayment::getCourseId).collect(Collectors.toList());
        courseScheduleService.getDao().updateLock(scheduleIds);
        UpdateWrapper<CourseGroup> warp = new UpdateWrapper<>();
        warp.set("status_", "ING").eq("id_", paymentList.get(0).getCourseGroupId());
        courseGroupService.update(warp);

        //查询陪练课服务费
        String practiceServiceRateStr = sysConfigService.findConfigValue(SysConfigConstant.PRACTICE_SERVICE_FEE);
        BigDecimal practiceServiceRate = new BigDecimal(practiceServiceRateStr).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);

        //写course_schedule_teacher_salary
        Long teacherId = null;
        Long studentId = null;
        Date now = new Date();
        List<CourseScheduleTeacherSalary> teacherSalaryList = new ArrayList<>();
        for (CourseScheduleStudentPaymentVo payment : paymentList) {
            BigDecimal expectPrice = payment.getExpectPrice();//预计价格

            CourseScheduleTeacherSalary teacherSalary = new CourseScheduleTeacherSalary();
            teacherSalary.setTeacherId(payment.getTeacherId());
            teacherSalary.setStudentId(payment.getUserId());
            teacherSalary.setCourseScheduleId(payment.getCourseId());
            teacherSalary.setCourseGroupType(payment.getCourseType());
            teacherSalary.setCourseGroupId(payment.getCourseGroupId());
            teacherSalary.setClassNum(payment.getClassNum());
            teacherSalary.setExpectSalary(expectPrice);//预计薪水
            BigDecimal actualSalary = expectPrice.subtract(expectPrice.multiply(practiceServiceRate)).setScale(2, RoundingMode.HALF_UP);
            teacherSalary.setActualSalary(actualSalary);//实际薪水(扣除手续费)
            teacherSalary.setReduceSalary(expectPrice.subtract(actualSalary));//扣除薪水 = 预计 - 实际
            teacherSalary.setReduceSalaryRemark(SysConfigConstant.PRACTICE_SERVICE_FEE);//扣除原因
            teacherSalary.setStatus(TeacherSalaryEnum.NOT_START.getCode());
            teacherSalary.setCreateTime(now);

            if (teacherSalary.getExpectSalary().compareTo(BigDecimal.ZERO) > 0) {
                teacherSalaryList.add(teacherSalary);
            }

            teacherId = payment.getTeacherId();
            studentId = payment.getUserId();
        }
        if (CollectionUtils.isNotEmpty(teacherSalaryList)) {
            courseScheduleTeacherSalaryService.getDao().insertBatch(teacherSalaryList);
            log.info("buyPracticeCourseSuccess ok");


            String userAccountConfig = userPaymentOrder.getAccountConfig();
            UserPaymentOrderWrapper.AccountTenantTo accountTenantTo;
            if (StringUtils.isBlank(userAccountConfig)) {
                accountTenantTo = new UserPaymentOrderWrapper.AccountTenantTo();
            } else {
                accountTenantTo = JSON.parseObject(userAccountConfig, UserPaymentOrderWrapper.AccountTenantTo.class);
            }

            // 老师收入总金额
            BigDecimal teacherAmount = teacherSalaryList.stream().map(CourseScheduleTeacherSalary::getActualSalary).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 判断分润给机构 还是给老师
           if (accountTenantTo.getIncomeTenant() != null && accountTenantTo.getIncomeTenant() > 0) {
                // 分润给机构
                tenantdivMap.merge( accountTenantTo.getIncomeTenant() , teacherAmount, BigDecimal::add);
                tenantdivMap.merge(-1L, teacherAmount, BigDecimal::subtract);
                serviceFeeAmount = tenantdivMap.get(-1L);
            } else {
                // 分润给老师
                bizMap.merge(userPaymentOrder.getBizId(), teacherAmount, BigDecimal::add);
            }

            saveData(userPaymentOrder, tenantdivMap, teacherMap, bizMap, serviceFeeAmount);
        }

        Set<Long> studentIds = new HashSet();
        studentIds.add(studentId);
        try {
            imUserFriendService.saveUserFriend(teacherId, studentIds);
            log.info("保存用户通讯录成功,teacherId:{},studentIds:{}", teacherId, studentIds);
        } catch (Exception e) {
            log.error("保存用户通讯录失败,teacherId:{},studentIds:{},e:{}", teacherId, studentIds, e);
        }

        //消息推送
        try {

            // 平台学生 发送推送
            if(checkSendMessage(userPaymentOrder.getUserId(),userPaymentOrder.getOrderClient())) {
                courseScheduleService.practiceSend(paymentList.get(0).getTeacherId(), userPaymentOrder.getUserId(), paymentList.size() + "", orderNo);
            }
        } catch (Exception e) {
            log.error("陪练课消息推送失败");
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void liveCourse(UserOrderDetailVo userPaymentOrder) {


        // 先计算分账金额，写入流水，最后执行分账，在写入分账数据

        // 分账
        Map<Long, BigDecimal> tenantdivMap = new HashMap<>();
        tenantdivMap.merge(-1L, userPaymentOrder.getActualPrice(), BigDecimal::add);
        // 分润
        Map<Long, BigDecimal> teacherMap = new HashMap<>();
        // 老师收入
        Map<Long, BigDecimal> bizMap = new HashMap<>();

        //服务费  原价的平台服务费 ，减去优惠券金额
        BigDecimal serviceFeeAmount = BigDecimal.ZERO;

        log.info("buyLiveCourseSuccess param :{}", JSON.toJSONString(userPaymentOrder));
        String orderNo = userPaymentOrder.getOrderNo();
        //更新课程组的购买人数+1
        List<CourseScheduleStudentPayment> studentPaymentList = courseScheduleStudentPaymentService.list(Wrappers.<CourseScheduleStudentPayment>lambdaQuery()
                .eq(CourseScheduleStudentPayment::getOrderNo, orderNo)
        );
        CourseScheduleStudentPayment studentPayment;
        if (CollectionUtils.isEmpty(studentPaymentList)) {
            log.info("buyLiveCourseSuccess >>> 订单不存在！orderParam： {}", JSON.toJSONString(userPaymentOrder));
            throw new BizException("订单不存在");
        } else {
            studentPayment = studentPaymentList.get(0);
        }
        //课程组信息
        CourseGroup courseGroup = courseGroupService.getOne(Wrappers.<CourseGroup>lambdaQuery()
                .eq(CourseGroup::getId, studentPayment.getCourseGroupId()));
        if (Objects.isNull(courseGroup)) {
            log.info("buyLiveCourseSuccess >>> 课程组不存在！orderParam： {}", JSON.toJSONString(userPaymentOrder));
            throw new BizException("课程组不存在");
        }
        //更新课程组的购买人数+1
        courseGroupService.getDao().opsPreStudentNum(studentPayment.getCourseGroupId(), 1);

        // 课程组 人数 + 1
        courseGroup.setPreStudentNum(courseGroup.getPreStudentNum() + 1);
        //查询课程组课程列表
        List<CourseSchedule> courseList = courseScheduleService.list(Wrappers.<CourseSchedule>lambdaQuery()
                .eq(CourseSchedule::getCourseGroupId, studentPayment.getCourseGroupId()));
        //课程总金额
        BigDecimal totalExpectPrice = WrapperUtil.sumList(studentPaymentList, CourseScheduleStudentPayment::getExpectPrice);
        //查询直播课服务费
        String liveServiceRateStr = sysConfigService.findConfigValue(SysConfigConstant.LIVE_SERVICE_RATE);
        BigDecimal liveServiceRate = new BigDecimal(liveServiceRateStr).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        //总课酬  1 - (1 * 手续费率)
        BigDecimal totalRatePrice = totalExpectPrice.subtract(totalExpectPrice.multiply(liveServiceRate)).setScale(2, RoundingMode.HALF_UP);
        //获取每节课的实际课酬 key 课堂数  value 课酬
        Map<Integer, BigDecimal> singerActualCourseSalary = WrapperUtil.getAveragePrice(courseGroup.getCourseNum(), totalRatePrice);
        //获取每节课的预计原课酬 key 课堂数  value 课酬
        Map<Integer, BigDecimal> singerExpectCourseSalary = WrapperUtil.getAveragePrice(courseGroup.getCourseNum(), totalExpectPrice);
        //写入课酬表计算-根据课程组总金额计算分配到每节课的金额
        Date now = new Date();
        List<CourseScheduleTeacherSalary> teacherSalaryList = new ArrayList<>();
        courseList.forEach(course -> {
            CourseScheduleTeacherSalary teacherSalary = new CourseScheduleTeacherSalary();
            teacherSalary.setTeacherId(course.getTeacherId());
            teacherSalary.setStudentId(studentPayment.getUserId());
            teacherSalary.setCourseScheduleId(course.getId());
            teacherSalary.setCourseGroupType(course.getType());
            teacherSalary.setCourseGroupId(course.getCourseGroupId());
            teacherSalary.setClassNum(course.getClassNum());
            teacherSalary.setCreateTime(now);
            teacherSalary.setStatus(TeacherSalaryEnum.NOT_START.getCode());
            //预计课酬
            BigDecimal ex = singerExpectCourseSalary.get(course.getClassNum());
            //实际课酬
            BigDecimal ac = singerActualCourseSalary.get(course.getClassNum());
            teacherSalary.setExpectSalary(ex);
            teacherSalary.setActualSalary(ac);
            //预计课酬-实际课酬 = 扣除费用
            teacherSalary.setReduceSalary(ex.subtract(ac));
            //备注是为直播课手续费
            teacherSalary.setReduceSalaryRemark(SysConfigConstant.LIVE_SERVICE_RATE);
            if (teacherSalary.getExpectSalary().compareTo(BigDecimal.ZERO) > 0) {
                teacherSalaryList.add(teacherSalary);
            }
        });
        if (CollectionUtils.isNotEmpty(teacherSalaryList)) {
            courseScheduleTeacherSalaryService.getDao().insertBatch(teacherSalaryList);


            String userAccountConfig = userPaymentOrder.getAccountConfig();
            UserPaymentOrderWrapper.AccountTenantTo accountTenantTo;
            if (StringUtils.isBlank(userAccountConfig)) {
                accountTenantTo = new UserPaymentOrderWrapper.AccountTenantTo();
            } else {
                accountTenantTo = JSON.parseObject(userAccountConfig, UserPaymentOrderWrapper.AccountTenantTo.class);
            }

            // 老师收入总金额
            BigDecimal teacherAmount = teacherSalaryList.stream().map(CourseScheduleTeacherSalary::getActualSalary).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 判断分润给机构 还是给老师
            if (accountTenantTo.getIncomeTenant() !=null && accountTenantTo.getIncomeTenant() >0) {
                // 分润给机构
                tenantdivMap.merge(accountTenantTo.getIncomeTenant() , teacherAmount, BigDecimal::add);
                tenantdivMap.merge(-1L, teacherAmount, BigDecimal::subtract);
                serviceFeeAmount = tenantdivMap.get(-1L);
            } else {
                // 分润给老师
                bizMap.merge(userPaymentOrder.getBizId(), teacherAmount, BigDecimal::add);
            }


            saveData(userPaymentOrder, tenantdivMap, teacherMap, bizMap, serviceFeeAmount);
        }
        log.info("buyLiveCourseSuccess ok");
        //课程购买成功后进行消息推送

        // 平台学生 发送推送
        if(checkSendMessage(userPaymentOrder.getUserId(),userPaymentOrder.getOrderClient())) {
            courseGroupService.buyLiveSendMessage(studentPayment, courseGroup);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void videoCourse(UserOrderDetailVo userPaymentOrder) {


        // 先计算分账金额，写入流水，最后执行分账，在写入分账数据

        // 分账
        Map<Long, BigDecimal> tenantdivMap = new HashMap<>();
        tenantdivMap.merge(-1L, userPaymentOrder.getActualPrice(), BigDecimal::add);
        // 分润
        Map<Long, BigDecimal> teacherMap = new HashMap<>();
        // 老师收入
        Map<Long, BigDecimal> bizMap = new HashMap<>();

        //服务费  原价的平台服务费 ，减去优惠券金额
        BigDecimal serviceFeeAmount = BigDecimal.ZERO;

        log.info("buyVideoCourseSuccess  param:{}", JSON.toJSONString(userPaymentOrder));
        String orderNo = userPaymentOrder.getOrderNo();
        VideoLessonPurchaseRecord purchaseRecord = videoLessonPurchaseRecordDao.selectOne(Wrappers.<VideoLessonPurchaseRecord>lambdaQuery()
                .eq(VideoLessonPurchaseRecord::getOrderNo, orderNo));
        if (purchaseRecord == null) {
            throw new BizException("课程组购买记录不存在!");
        }

        //查询订单状态
        UserOrder userOrder = userOrderDao.selectOne(Wrappers.<UserOrder>lambdaQuery()
                .eq(UserOrder::getOrderNo, orderNo));
        if (userOrder == null) {
            throw new BizException("订单不存在!");
        }
        //修改支付状态
        videoLessonPurchaseRecordDao.updateStatus(orderNo, OrderStatusEnum.PAID.getCode());
        //查询组信息
        VideoLessonGroup lessonGroup = videoLessonGroupDao.selectById(purchaseRecord.getVideoLessonGroupId());
        //记录流水

        //查询视频课服务费
        BigDecimal liveServiceRate = new BigDecimal(sysConfigService.findConfigValue(SysConfigConstant.VIDEO_LESSON_SERVICE_FEE))
                .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        //支付金额
        BigDecimal expectPrice = userPaymentOrder.getExpectPrice();
        //服务费
        serviceFeeAmount = expectPrice.multiply(liveServiceRate).setScale(2, RoundingMode.HALF_UP);
        //老师入账金额
        BigDecimal teacherAmount = expectPrice.subtract(serviceFeeAmount).setScale(2, RoundingMode.HALF_UP);
        // 判断分润给机构 还是给老师

        String userAccountConfig = userPaymentOrder.getAccountConfig();
        UserPaymentOrderWrapper.AccountTenantTo accountTenantTo;
        if (StringUtils.isBlank(userAccountConfig)) {
            accountTenantTo = new UserPaymentOrderWrapper.AccountTenantTo();
        } else {
            accountTenantTo = JSON.parseObject(userAccountConfig, UserPaymentOrderWrapper.AccountTenantTo.class);
        }

        if (accountTenantTo.getIncomeTenant() !=null && accountTenantTo.getIncomeTenant() >0) {
            // 分润给机构
            tenantdivMap.merge(accountTenantTo.getIncomeTenant(), teacherAmount, BigDecimal::add);
            tenantdivMap.merge(-1L, teacherAmount, BigDecimal::subtract);
            serviceFeeAmount = tenantdivMap.get(-1L);
        } else {
            // 分润给老师
            bizMap.merge(userPaymentOrder.getBizId(), teacherAmount, BigDecimal::add);
        }

        saveData(userPaymentOrder, tenantdivMap, teacherMap, bizMap, serviceFeeAmount);


        // 平台学生 发送推送
        if(checkSendMessage(userPaymentOrder.getUserId(),userPaymentOrder.getOrderClient())) {
            videoLessonPurchaseRecordService.videoSend(lessonGroup.getTeacherId(), purchaseRecord.getStudentId(), lessonGroup);
        }

        // 赠品曲目、专辑插入用户曲目购买记录表
        List<CourseRelationMusicAlbum> musicAlbums = courseRelationMusicAlbumService.lambdaQuery()
                .eq(CourseRelationMusicAlbum::getCourseGroupId, lessonGroup.getId())
                .eq(CourseRelationMusicAlbum::getDelFlog, EStatus.ENABLE.getValue())
                .eq(CourseRelationMusicAlbum::getUseRelationType, CourseRelationTypeEnum.GIFT)
                .list();

        List<Long> giftIds = musicAlbums.stream()
                .map(CourseRelationMusicAlbum::getId).distinct().collect(Collectors.toList());

        Map<Long, Long> purchaseIdMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(giftIds)) {

            // 查询用户购买记录
            purchaseIdMap = musicSheetPurchaseRecordService.lambdaQuery()
                    .eq(MusicSheetPurchaseRecord::getStudentId, userPaymentOrder.getUserId())
                    .eq(MusicSheetPurchaseRecord::getOrderStatus, OrderStatusEnum.PAID)
                    .in(MusicSheetPurchaseRecord::getCourseMusicAlbumId, giftIds)
                    .list().stream()
                    .collect(Collectors.toMap(MusicSheetPurchaseRecord::getCourseMusicAlbumId, MusicSheetPurchaseRecord::getId, (o, n) -> n));
        }

        List<CourseRelationWrapper.MusicAlbumRecord> musicAlbumRecords = com.google.common.collect.Lists.newArrayList();

        for (CourseRelationMusicAlbum item : musicAlbums) {

            musicAlbumRecords.add(CourseRelationWrapper.MusicAlbumRecord
                    .builder()
                    .clientType(userPaymentOrder.getOrderClient())
                    .musicSheetId(item.getMusicAlbumId())
                    .orderNo(userPaymentOrder.getOrderNo())
                    .purchasePrice(BigDecimal.ZERO)
                    .purchaseTime(DateTime.now().toDate())
                    .teacherId(userPaymentOrder.getMerchId())
                    .originalPrice(BigDecimal.ZERO)
                    .musicSheetServiceFee(BigDecimal.ZERO)
                    .orderStatus(OrderStatusEnum.PAID)
                    .studentId(userPaymentOrder.getUserId())
                    .purchaseType(PurchaseRecordTypeEnum.valueOf(item.getRelationType().getCode()))
                    .id(purchaseIdMap.get(item.getId()))
                    .courseMusicAlbumId(item.getId())
                    .build());
        }

        if (CollectionUtils.isNotEmpty(musicAlbumRecords)) {

            List<MusicSheetPurchaseRecord> records = JSON.parseArray(JSON.toJSONString(musicAlbumRecords),
                    MusicSheetPurchaseRecord.class);

            // 批量插入课程赠送曲目、专辑数据
            musicSheetPurchaseRecordService.saveBatch(records, 30);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void vip(UserOrderDetailVo userPaymentOrder) {

        // 先计算分账金额，写入流水，最后执行分账，在写入分账数据

        // 分账
        Map<Long, BigDecimal> tenantdivMap = new HashMap<>();
        tenantdivMap.merge(-1L, userPaymentOrder.getActualPrice(), BigDecimal::add);
        // 分润
        Map<Long, BigDecimal> teacherMap = new HashMap<>();
        // 老师收入
        Map<Long, BigDecimal> bizMap = new HashMap<>();

        //服务费  原价的平台服务费 ，减去优惠券金额
        BigDecimal serviceFeeAmount = userPaymentOrder.getActualPrice();

        memberPriceSettingsService.orderSuccess(userPaymentOrder);

        saveData(userPaymentOrder, tenantdivMap, teacherMap, bizMap, serviceFeeAmount);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void activity(UserOrderDetailVo userPaymentOrder) {

        // 先计算分账金额，写入流水，最后执行分账，在写入分账数据

        // 分账
        Map<Long, BigDecimal> tenantdivMap = new HashMap<>();
        tenantdivMap.merge(-1L, userPaymentOrder.getActualPrice(), BigDecimal::add);
        // 分润
        Map<Long, BigDecimal> teacherMap = new HashMap<>();
        // 老师收入
        Map<Long, BigDecimal> bizMap = new HashMap<>();

        //服务费  原价的平台服务费 ，减去优惠券金额
        BigDecimal serviceFeeAmount = userPaymentOrder.getActualPrice();


        activityPlanService.orderSuccess(userPaymentOrder,checkSendMessage(userPaymentOrder.getUserId(),userPaymentOrder.getOrderClient()));

        saveData(userPaymentOrder, tenantdivMap, teacherMap, bizMap, serviceFeeAmount);
    }

    @Override
    public List<PaymentDivMemberRecord> getByOrderNo(String orderNo) {
        return this.lambdaQuery()
            .eq(PaymentDivMemberRecord::getOrderNo, orderNo)
            .list();
    }


    // 写入数据库
    private void saveData(UserOrderDetailVo userPaymentOrder, Map<Long, BigDecimal> tenantdivMap, Map<Long, BigDecimal> teacherMap, Map<Long, BigDecimal> bizMap, BigDecimal serviceFeeAmount) {


        // 判断金额是否和支付金额一致
        BigDecimal totalAmount = tenantdivMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        if (totalAmount.compareTo(userPaymentOrder.getActualPrice()) != 0) {
            log.error("分账金额不一致 orderNo:{} totalAmount:{} actualPrice:{}", userPaymentOrder.getOrderNo(), totalAmount, userPaymentOrder.getActualPrice());
//            return;
        }
        // 机构分润

        Map<Long,BigDecimal> tenantShare = new HashMap<>();

        BigDecimal amount = bizMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);

        // 计算分润
        teacherAmount(userPaymentOrder, tenantdivMap, teacherMap,tenantShare, tenantdivMap.get(-1L).subtract(amount));

        String userAccountConfig = userPaymentOrder.getAccountConfig();
        UserPaymentOrderWrapper.AccountTenantTo accountTenantTo;
        if (StringUtils.isBlank(userAccountConfig)) {
            accountTenantTo = new UserPaymentOrderWrapper.AccountTenantTo();
        } else {
            accountTenantTo = JSON.parseObject(userAccountConfig, UserPaymentOrderWrapper.AccountTenantTo.class);
        }


        if (accountTenantTo.getIncomeTenant() >0 ){

            // 写入机构收支表
            tenantDivRecord(userPaymentOrder, tenantdivMap,false);
            // 写入平台
            platformDivRecord(userPaymentOrder, tenantdivMap);
        } else {
            // 写入平台
            platformDivRecord(userPaymentOrder, tenantdivMap);
            // 写入机构收支表
            tenantDivRecord(userPaymentOrder, tenantdivMap,false);

        }

        // 写入机构分润
        tenantDivRecord(userPaymentOrder, tenantShare,true);

        //写入老师收入
        //  老师分润
        for (Map.Entry<Long, BigDecimal> e : bizMap.entrySet()) {
            Long k = e.getKey();
            BigDecimal value = e.getValue();
            if (value.compareTo(BigDecimal.ZERO) > 0) {
                teacherBizRecord(userPaymentOrder, k, value);
            }
        }
        for (Map.Entry<Long, BigDecimal> entry : teacherMap.entrySet()) {
            BigDecimal v = entry.getValue();
            teacherShare(userPaymentOrder, v);
        }

        // 写入分账记录表
        divRecord(userPaymentOrder, tenantdivMap);
    }

    private void teacherBizRecord(UserOrderDetailVo userPaymentOrder, Long bizId, BigDecimal amount) {
        String userAccountConfig = userPaymentOrder.getAccountConfig();
        UserPaymentOrderWrapper.AccountTenantTo accountTenantTo;
        if (StringUtils.isBlank(userAccountConfig)) {
            accountTenantTo = new UserPaymentOrderWrapper.AccountTenantTo();
        } else {
            accountTenantTo = JSON.parseObject(userAccountConfig, UserPaymentOrderWrapper.AccountTenantTo.class);
        }
        if (!accountTenantTo.isIncomeTeacher()) {
            return;
        }

        //获取账期时间
        Date accountPeriodTime = userOrderService.getAccountPeriodTime(userPaymentOrder);

        //老师待入账
        List<UserAccountRecordDto> userAccountRecordDtos = new ArrayList<>();
        List<PlatformCashAccountRecord> platformCashAccountRecords = new ArrayList<>();
        UserAccountRecordDto dto = new UserAccountRecordDto(userPaymentOrder.getMerchId(), PostStatusEnum.WAIT, amount,
                InOrOutEnum.IN, AccountBizTypeEnum.valueOf(userPaymentOrder.getOrderType().getCode()), bizId, userPaymentOrder.getGoodName(), userPaymentOrder.getOrderNo(),
                userPaymentOrder.getUserId(), accountPeriodTime);
        userAccountRecordDtos.add(dto);

        // 插入平台账户 支出
        PlatformCashAccountRecord platformCashAccountRecord = new PlatformCashAccountRecord(userPaymentOrder.getUserId(), amount,
                InOrOutEnum.OUT, PostStatusEnum.WAIT, AccountBizTypeEnum.valueOf(userPaymentOrder.getOrderType().getCode()), bizId,
                userPaymentOrder.getOrderNo(), accountPeriodTime);
        platformCashAccountRecords.add(platformCashAccountRecord);

        if (CollectionUtils.isNotEmpty(userAccountRecordDtos)) {
            userAccountService.accountRecord(userAccountRecordDtos);
            platformCashAccountRecordService.saveBatch(platformCashAccountRecords);
        }
    }


    private void divRecord(UserOrderDetailVo userPaymentOrder, Map<Long, BigDecimal> tenantdivMap) {
        UserOrderPayment newestPayment = userOrderPaymentService.getNewestPayment(null, userPaymentOrder.getOrderNo());

        PaymentMerchantConfig merchantConfig = paymentMerchantConfigService.getByPaymentVendor(userPaymentOrder.getPaymentVendor());
        String userAccountConfig = userPaymentOrder.getAccountConfig();
        UserPaymentOrderWrapper.AccountTenantTo accountTenantTo;
        if (StringUtils.isBlank(userAccountConfig)) {
            accountTenantTo = new UserPaymentOrderWrapper.AccountTenantTo();
        } else {
            accountTenantTo = JSON.parseObject(userAccountConfig, UserPaymentOrderWrapper.AccountTenantTo.class);
        }

        BigDecimal amount = tenantdivMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        boolean tenantEnterFlag = false;
        //  执行分账
        TenantMember tenantMember = null;
        String divideOrderNo = IdWorker.getIdStr();
        BigDecimal feeAmt = BigDecimal.ZERO;
        DivideResp divide = new DivideResp();
        if (merchantConfig != null && newestPayment != null) {
            if (accountTenantTo.getIncomeTenant() > 0) {
                tenantMember = tenantMemberService
                        .getByAppIdAndTenantId(merchantConfig.getAppId(), accountTenantTo.getIncomeTenant(),merchantConfig.getPayerType());
            }
            if (tenantMember != null) {
                // 执行分账逻辑
                BasePaymentService paymentService = paymentServiceContext.getPaymentService(merchantConfig.getPaymentVendor());
                DivideReq.DivMember divMember = DivideReq.DivMember.builder()
                        .memberId(tenantMember.getMemberId())
                        .amount(amount)
                        .feeFlag("Y")
                        .build();
                DivideReq divideReq = DivideReq.builder()
                        .transNo(newestPayment.getTransNo())
                        .orderNo(userPaymentOrder.getOrderNo())
                        .divideOrderNo(divideOrderNo)
                        .divideAmount(amount)
                        .divMembers(Lists.newArrayList(divMember))
                        .build();
                try {
                    divide = paymentService.divide(divideReq);
                    feeAmt = divide.getFeeAmount();
                    tenantEnterFlag = true;
                } catch (Exception e) {
                    log.error("分账失败 分账对象 {} 分账数据 {} 分账订单号 {}", tenantMember, divideReq, divideOrderNo);
                }

            }
        }
        // 写入分账记录表
        PaymentDivMemberRecord paymentDivMemberRecord = PaymentDivMemberRecord.builder()
                .tenantId(accountTenantTo.getIncomeTenant())
                .appId(merchantConfig != null ? merchantConfig.getAppId() : null)
                .memberId(tenantMember != null ? tenantMember.getMemberId() : null)
                .orderNo(userPaymentOrder.getOrderNo())
                .divOrderNo(divideOrderNo)
                .transNo(newestPayment != null ? newestPayment.getTransNo() : null)
                .amount(amount)
                .divMemberJson(CollectionUtils.isNotEmpty(divide.getDivMembers())?JSON.toJSONString(divide.getDivMembers()):"")
                .tenantEnterFlag(divide.getStatus()!=null && divide.getStatus().equals(PaymentStatus.SUCCESSED))
                .status("SUCCESS")
                .feeFlag(true)
                .feeAmt(feeAmt)
                .build();
        paymentDivMemberRecordService.save(paymentDivMemberRecord);
    }

    private void teacherShare(UserOrderDetailVo userPaymentOrder, BigDecimal shareFee) {
        //获取账期时间
        Date accountPeriodTime = userOrderService.getAccountPeriodTime(userPaymentOrder);
        AccountBizTypeEnum bizTypeEnum = AccountBizTypeEnum.valueOf(userPaymentOrder.getGoodType().getCode() + "_SHARE");
        if (null != bizTypeEnum) {
            //插入分润老师账户变更记录-分润老师预收
            HttpResponseResult<UserAccountRecord> recomRecordRes = userAccountService.accountRecord(
                    new UserAccountRecordDto(userPaymentOrder.getRecomUserId(), PostStatusEnum.WAIT, shareFee, InOrOutEnum.IN,
                            bizTypeEnum, userPaymentOrder.getBizId(), bizTypeEnum.getMsg(), userPaymentOrder.getOrderNo(), userPaymentOrder.getUserId(), accountPeriodTime));
            if (recomRecordRes.getStatus()) {
                //插入平台预支
                PlatformCashAccountRecord platformCashAccountRecord = new PlatformCashAccountRecord(userPaymentOrder.getRecomUserId(), shareFee,
                        InOrOutEnum.OUT, PostStatusEnum.WAIT, bizTypeEnum, userPaymentOrder.getBizId(), userPaymentOrder.getOrderNo(), accountPeriodTime);
                platformCashAccountRecordService.save(platformCashAccountRecord);
            }
        }
    }

    private void platformDivRecord(UserOrderDetailVo userPaymentOrder, Map<Long, BigDecimal> tenantdivMap) {
        // 写入平台收入表
        Date date = new Date();
        String userAccountConfig = userPaymentOrder.getAccountConfig();
        UserPaymentOrderWrapper.AccountTenantTo accountTenantTo;
        if (StringUtils.isBlank(userAccountConfig)) {
            accountTenantTo = new UserPaymentOrderWrapper.AccountTenantTo();
        } else {
            accountTenantTo = JSON.parseObject(userAccountConfig, UserPaymentOrderWrapper.AccountTenantTo.class);
        }
        AccountBizTypeEnum bizTypeEnum = AccountBizTypeEnum.valueOf(userPaymentOrder.getOrderType().name());
        BigDecimal amount = tenantdivMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        PostStatusEnum platformPostStatus = PostStatusEnum.RECORDED;
        SourceTypeEnum sourceType = SourceTypeEnum.ORDER;
        if (accountTenantTo.getIncomeTenant() >0 ){
            amount = tenantdivMap.get(-1L);
            platformPostStatus = PostStatusEnum.WAIT;
            sourceType = SourceTypeEnum.TENANT;
        }

        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }

        PlatformCashAccountRecord platformCashAccountRecord = new PlatformCashAccountRecord(userPaymentOrder.getUserId(), amount,
                InOrOutEnum.IN, platformPostStatus, bizTypeEnum, userPaymentOrder.getBizId(),
                userPaymentOrder.getOrderNo(), date);
        platformCashAccountRecord.setSourceType(sourceType);

        platformCashAccountRecordService.save(platformCashAccountRecord);
        if (accountTenantTo.getIncomeTenant() >0 ){
            // 写入机构支出到平台
            // 写入机构流水表
            TenantAccountRecord tenantAccountRecord = TenantAccountRecord.builder()
                    .tenantId(accountTenantTo.getIncomeTenant())
                    .transAmount(amount)
                    .platformCashAccountRecordId(platformCashAccountRecord.getId())
                    .sourceType(SourceTypeEnum.PLATFORM)
                    .inOrOut(InOrOutEnum.OUT.getCode())
                    .postStatus(PostStatusEnum.WAIT.getCode())
                    .bizType(bizTypeEnum.getCode())
                    .bizId(userPaymentOrder.getBizId())
                    .bizName(userPaymentOrder.getGoodName())
                    .orderNo(userPaymentOrder.getOrderNo())
                    .build();
            tenantAccountRecordService.save(tenantAccountRecord);
        }
    }

    private void tenantDivRecord(UserOrderDetailVo userPaymentOrder, Map<Long, BigDecimal> tenantdivMap,boolean share) {
        // 写入收支表
        Date date = new Date();
        for (Map.Entry<Long, BigDecimal> entry : tenantdivMap.entrySet()) {
            Long tenantId = entry.getKey();
            BigDecimal amount = entry.getValue();
            BigDecimal tenantAmount = amount;
            if (tenantId.equals(-1L)) {
                continue;
            }
            String type = userPaymentOrder.getGoodType().getCode();
            if (share) {
                type = type + "_SHARE";
            }

            AccountBizTypeEnum bizTypeEnum = AccountBizTypeEnum.valueOf(type);

            // 如果是机构入账
            String userAccountConfig = userPaymentOrder.getAccountConfig();
            UserPaymentOrderWrapper.AccountTenantTo accountTenantTo;
            if (StringUtils.isBlank(userAccountConfig)) {
                accountTenantTo = new UserPaymentOrderWrapper.AccountTenantTo();
            } else {
                accountTenantTo = JSON.parseObject(userAccountConfig, UserPaymentOrderWrapper.AccountTenantTo.class);
            }
            PostStatusEnum tenantPostStatus = PostStatusEnum.WAIT;
            boolean isIncomeTenant = false;
            if (accountTenantTo.getIncomeTenant() > 0 && tenantId.equals(accountTenantTo.getIncomeTenant()) && !share) {
                tenantAmount = tenantdivMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
                tenantPostStatus = PostStatusEnum.RECORDED;
                isIncomeTenant = true;
            }
            if (tenantAmount.compareTo(BigDecimal.ZERO) <= 0) {
                continue;
            }
            Long platformCashAccountRecordId = null;
            if (!isIncomeTenant) {
                // 写入平台支出表
                PlatformCashAccountRecord platformCashAccountRecord2 = new PlatformCashAccountRecord(userPaymentOrder.getUserId(), amount,
                        InOrOutEnum.OUT, PostStatusEnum.WAIT, bizTypeEnum, userPaymentOrder.getBizId(),
                        userPaymentOrder.getOrderNo(), date);
                platformCashAccountRecord2.setSourceType(SourceTypeEnum.TENANT);
                platformCashAccountRecordService.save(platformCashAccountRecord2);
                platformCashAccountRecordId = platformCashAccountRecord2.getId();
            }

            // 写入机构流水表
            TenantAccountRecord tenantAccountRecord = TenantAccountRecord.builder()
                    .tenantId(tenantId)
                    .transAmount(tenantAmount)
                    .platformCashAccountRecordId(platformCashAccountRecordId)
                    .sourceType(SourceTypeEnum.ORDER)
                    .inOrOut(InOrOutEnum.IN.getCode())
                    .postStatus(tenantPostStatus.getCode())
                    .bizType(bizTypeEnum.getCode())
                    .bizId(userPaymentOrder.getBizId())
                    .bizName(userPaymentOrder.getGoodName())
                    .orderNo(userPaymentOrder.getOrderNo())
                    .build();

            if (!isIncomeTenant) {
                tenantAccountRecord.setSourceType(SourceTypeEnum.PLATFORM);
            }
            tenantAccountRecordService.save(tenantAccountRecord);
            // 是否结算到老师， 结算到老师的，写入机构支出 和老师机构收入
            if ((accountTenantTo.isIncomeTeacher()&& !share) || (share && accountTenantTo.isShareTeacher())) {
                TenantAccountRecord tenantAccountRecordOut = TenantAccountRecord.builder()
                        .tenantId(tenantId)
                        .transAmount(amount)
                        .platformCashAccountRecordId(null)
                        .sourceType(SourceTypeEnum.TEACHER)
                        .inOrOut(InOrOutEnum.OUT.getCode())
                        .postStatus(PostStatusEnum.WAIT.getCode())
                        .bizType(bizTypeEnum.getCode())
                        .bizId(userPaymentOrder.getBizId())
                        .bizName(userPaymentOrder.getGoodName())
                        .orderNo(userPaymentOrder.getOrderNo())
                        .build();
                tenantAccountRecordService.save(tenantAccountRecordOut);

                TenantTeacherAccountRecord tenantTeacherAccountRecord = TenantTeacherAccountRecord.builder()
                        .tenantId(tenantId)
                        .teacherId(userPaymentOrder.getMerchId())
                        .accountRecordId(tenantAccountRecordOut.getId())
                        .sourceType(SourceTypeEnum.TENANT)
                        .transAmount(amount)
                        .inOrOut(InOrOutEnum.IN.getCode())
                        .postStatus(PostStatusEnum.WAIT.getCode())
                        .bizType(bizTypeEnum.getCode())
                        .bizId(userPaymentOrder.getBizId())
                        .bizName(userPaymentOrder.getGoodName())
                        .orderNo(userPaymentOrder.getOrderNo())
                        .build();
                tenantTeacherAccountRecordService.save(tenantTeacherAccountRecord);
                tenantAccountRecordOut.setPlatformCashAccountRecordId(tenantTeacherAccountRecord.getId());
                tenantAccountRecordService.updateById(tenantAccountRecordOut);

            }

        }
    }


    // 计算分润
    private void teacherAmount(UserOrderDetailVo userPaymentOrder, Map<Long, BigDecimal> tenantdivMap, Map<Long, BigDecimal> teacherMap,
                               Map<Long, BigDecimal> tenantShare, BigDecimal platformFee) {

        if (platformFee.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }

        String userAccountConfig = userPaymentOrder.getAccountConfig();
        UserPaymentOrderWrapper.AccountTenantTo accountTenantTo;
        if (StringUtils.isBlank(userAccountConfig)) {
            accountTenantTo = new UserPaymentOrderWrapper.AccountTenantTo();
        } else {
            accountTenantTo = JSON.parseObject(userAccountConfig, UserPaymentOrderWrapper.AccountTenantTo.class);
        }

        //卖家不能分润自己 买家和分润人相同，不分润
        if (null != userPaymentOrder.getRecomUserId() && userPaymentOrder.getRecomUserId() != 0
                && !userPaymentOrder.getRecomUserId().equals(userPaymentOrder.getMerchId())
                && !userPaymentOrder.getUserId().equals(userPaymentOrder.getRecomUserId())) {

            //获取分润收益费率
            BigDecimal shareFeeRate = userOrderService.getShareFreeByGoodType(userPaymentOrder.getGoodType()
                    , userPaymentOrder.getBizId());
            //入老师账户
            BigDecimal shareFee = platformFee.multiply(shareFeeRate).setScale(2, RoundingMode.HALF_UP);
            if (shareFee.compareTo(BigDecimal.ZERO) > 0) {
                // 判断分润给机构 还是给老师
                if (accountTenantTo.getShareTenant() != null && accountTenantTo.getShareTenant() == 0) {

                } else if (accountTenantTo.getShareTenant() !=null && accountTenantTo.getShareTenant() > 0) {
                    // 分润给机构
                    tenantShare.merge(accountTenantTo.getShareTenant(), shareFee, BigDecimal::add);
//                    tenantdivMap.merge(-1L, shareFee, BigDecimal::subtract);

                } else {
                    // 分润给老师
                    teacherMap.merge(userPaymentOrder.getRecomUserId(), shareFee, BigDecimal::add);
                }
            }
        }
    }
}