package com.ym.mec.biz.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.auth.api.entity.SysUserRole;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.dal.page.MusicGroupQueryInfo;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.entity.ImGroupMember;
import com.ym.mec.common.entity.ImGroupModel;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.im.ImFeignService;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext.MessageSender;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
import com.ym.mec.util.http.HttpUtil;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> implements MusicGroupService {

    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private ChargeTypeDao chargeTypeDao;
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private SchoolDao schoolDao;
    @Autowired
    private MusicGroupPaymentCalenderDao musicGroupPaymentCalenderDao;
    @Autowired
    private MusicGroupPaymentCalenderService musicGroupPaymentCalenderService;
    @Autowired
    private MusicGroupPaymentEntitiesDao musicGroupPaymentEntitiesDao;
    @Autowired
    private MusicGroupSubjectGoodsGroupDao musicGroupSubjectGoodsGroupDao;
    @Autowired
    private MusicGroupSubjectPlanDao musicGroupSubjectPlanDao;
    @Autowired
    private MusicGroupBuildLogDao musicGroupBuildLogDao;
    @Autowired
    private MusicGroupPurchaseListDao musicGroupPurchaseListDao;
    @Autowired
    private MusicGroupStudentFeeDao musicGroupStudentFeeDao;

    @Autowired
    private ClassGroupStudentMapperDao classGroupStudentMapperDao;

    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;

    @Autowired
    private SysUserCashAccountService sysUserCashAccountService;

    @Autowired
    private SysUserCashAccountDetailService sysUserCashAccountDetailService;

    @Autowired
    private MusicGroupQuitDao musicGroupQuitDao;

    @Autowired
    private StudentRegistrationDao studentRegistrationDao;

    @Autowired
    private CourseScheduleDao courseScheduleDao;

    @Autowired
    private ClassGroupDao classGroupDao;

    @Autowired
    private OrganizationDao organizationDao;

    @Autowired
    private CourseScheduleTeacherSalaryDao courseScheduleTeacherSalaryDao;

    @Autowired
    private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;

    @Autowired
    private CooperationOrganDao cooperationOrganDao;

    @Autowired
    private TeacherAttendanceDao teacherAttendanceDao;

    @Autowired
    private StudentPaymentOrderService studentPaymentOrderService;

    @Autowired
    private StudentPaymentOrderDetailService studentPaymentOrderDetailService;

    @Autowired
    private PayService payService;

    @Autowired
    private SysUserFeignService sysUserFeignService;

    @Autowired
    private EmployeeDao employeeDao;

    @Autowired
    private SysMessageService sysMessageService;

    @Autowired
    private SysConfigDao sysConfigDao;

    @Autowired
    private ClassGroupService classGroupService;

    @Autowired
    private StudentPaymentOrderDetailDao studentPaymentOrderDetailDao;

    @Autowired
    private MusicGroupSubjectPlanService musicGroupSubjectPlanService;
    @Autowired
    private StudentRegistrationService studentRegistrationService;
    @Autowired
    private SporadicChargeInfoDao sporadicChargeInfoDao;
    @Autowired
    private MusicGroupSubjectGoodsGroupService musicGroupSubjectGoodsGroupService;
    @Autowired
    private GoodsService goodsService;

    @Autowired
    private ImFeignService imFeignService;

    private SimpleDateFormat sdf_ymd = new SimpleDateFormat("yyyy-MM-dd");

    private SimpleDateFormat sdf_hms = new SimpleDateFormat("HH:mm:ss");

    @Override
    public BaseDAO<String, MusicGroup> getDAO() {
        return musicGroupDao;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createGroup(SubFeeSettingDto subFeeSettingDto) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null || sysUser.getId() == null) {
            throw new BizException("获取用户信息失败");
        }
        MusicGroup musicGroup = subFeeSettingDto.getMusicGroup();
        List<MusicGroupSubjectGoodsGroup> musicGroupSubjectGoodsGroups = subFeeSettingDto.getMusicGroupSubjectGoodsGroups();
        List<MusicGroupSubjectPlan> musicGroupSubjectPlans = subFeeSettingDto.getMusicGroupSubjectPlans();
        List<SubjectRegisterDto> subjectRegisters = subFeeSettingDto.getSubjectRegisters();
        String musicGroupId = idGeneratorService.generatorId() + "";
        musicGroup.setId(musicGroupId);
        if (musicGroup.getStatus() != MusicGroupStatusEnum.DRAFT && musicGroup.getStatus() != MusicGroupStatusEnum.AUDIT) {
            throw new BizException("乐团初始状态错误");
        }
        // 保存乐团基本信息
        musicGroupDao.insert(musicGroup);

        // 记录创建日志
        String event = musicGroup.getStatus() == MusicGroupStatusEnum.AUDIT ? "新建乐团，提交审核" : "保存乐团草稿";
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, event, sysUser.getId(), ""));
        if (musicGroup.getStatus() == MusicGroupStatusEnum.AUDIT) {
            Set<Integer> roleIds = new HashSet<>(1);
            roleIds.add(SysUserRole.SECTION_MANAGER);

            sysMessageService.batchSeoMessage(musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId()), MessageTypeEnum.BACKSTAGE_CREATE_MUSIC_GROUP_APPLY, "", sysUser.getUsername());
        }
        // 保存乐团付费主体列表
        //批量新增
        if (subFeeSettingDto.getMusicGroupPaymentEntities() != null && subFeeSettingDto.getMusicGroupPaymentEntities().size() > 0) {
            musicGroupPaymentEntitiesDao.batchAdd(subFeeSettingDto.getMusicGroupPaymentEntities(), musicGroupId);
        }
        // 保存学员付费周期
        List<Integer> months = subFeeSettingDto.getMonths();
        if (months != null && months.size() > 0) {
            musicGroupPaymentCalenderDao.batchAdd(months, musicGroupId);
        }

        //乐团科目学生
        if (subjectRegisters != null && subjectRegisters.size() > 0) {
            List<StudentRegistration> studentRegistrationList = new ArrayList<>();
            subjectRegisters.forEach(e -> {
                if (e.getRegisterIdList().size() == 0) {
                    return;
                }
                //原来乐团的注册学生
                List<StudentRegistration> musicGroupStudentRegistrationList = studentRegistrationDao.findStudentListByIdList(e.getRegisterIdList());
                for (StudentRegistration studentRegistration : musicGroupStudentRegistrationList) {
                    studentRegistration.setId(null);
                    studentRegistration.setMusicGroupStatus(ClassGroupStudentStatusEnum.NORMAL);
                    studentRegistration.setPaymentStatus(PaymentStatusEnum.OPEN);
                    studentRegistration.setMusicGroupId(musicGroupId);
                    studentRegistration.setSubjectId(e.getSubjectId());
                    studentRegistration.setActualSubjectId(e.getSubjectId());
                    studentRegistration.setTemporaryCourseFee(null);
                }
                studentRegistrationList.addAll(musicGroupStudentRegistrationList);

                for (MusicGroupSubjectPlan musicGroupSubjectPlan : musicGroupSubjectPlans) {
                    if (!musicGroupSubjectPlan.getSubjectId().equals(e.getSubjectId())) continue;
                    musicGroupSubjectPlan.setExpectedStudentNum(e.getRegisterIdList().size());
                    musicGroupSubjectPlan.setApplyStudentNum(e.getRegisterIdList().size());
                }
            });
            musicGroup.setStatus(MusicGroupStatusEnum.PAY);
            //是否是免费团
            if (musicGroupSubjectPlans != null && musicGroupSubjectPlans.size() > 0) {
                int size = musicGroupSubjectPlans.stream().filter(e -> e.getFee().compareTo(BigDecimal.ZERO) == 1).collect(Collectors.toList()).size();
                if (size < 1) {
                    musicGroup.setStatus(MusicGroupStatusEnum.PREPARE);
                    if (studentRegistrationList.size() > 0) {
                        //修改为已缴费
                        studentRegistrationList.forEach(e -> e.setPaymentStatus(PaymentStatusEnum.YES));
                    }
                    musicGroupSubjectPlans.forEach(e -> e.setPaidStudentNum(e.getApplyStudentNum()));
                }
            }
            if (studentRegistrationList.size() > 0) {
                studentRegistrationDao.batchInsert(studentRegistrationList);
            }
            musicGroupDao.update(musicGroup);
//            List<MusicGroupStudentFee> musicGroupStudentFees = musicGroupStudentFeeDao.initMusicGroupStudentFee(musicGroupId);
//            if(musicGroupStudentFees != null && musicGroupStudentFees.size() > 0){
//                Date nextPaymentDate = musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, null,null);
//                musicGroupStudentFeeDao.batchInsert(musicGroupStudentFees,nextPaymentDate,"PAID_COMPLETED");
//            }
            musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "跨团调整", sysUser.getId(), ""));
        }

        // 保存乐团声部规划
        if (musicGroupSubjectPlans != null && musicGroupSubjectPlans.size() > 0) {
            musicGroupSubjectPlanDao.batchAdd(musicGroupSubjectPlans, musicGroupId);
        }
        // 保存乐团声部商品规划
        if (musicGroupSubjectGoodsGroups != null && musicGroupSubjectGoodsGroups.size() > 0) {
            for (MusicGroupSubjectGoodsGroup musicGroupSubjectGoodsGroup : musicGroupSubjectGoodsGroups) {
                if(musicGroupSubjectGoodsGroup.getType().equals(GoodsType.INSTRUMENT) && (musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson() == null
                        || musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson().isEmpty()
                        || musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson().equals("{}"))){
                    throw new BizException(musicGroupSubjectGoodsGroup.getName()+" 请选择提供方式");
                }
            }
            musicGroupSubjectGoodsGroupDao.batchInsert(musicGroupSubjectGoodsGroups, musicGroupId);
        }
        return musicGroupId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map sporadicPay(SporadicPayDto sporadicPayDto) throws Exception {
        //获取收费项价格
        SporadicChargeInfo chargeInfo = sporadicChargeInfoDao.get(sporadicPayDto.getSporadicId());
        if (chargeInfo == null) {
            throw new BizException("支付项不存在");
        }
        BigDecimal amount = chargeInfo.getAmount();
        if (chargeInfo.getDiscountAmount() != null && chargeInfo.getDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
            amount = amount.subtract(chargeInfo.getDiscountAmount());
        }
        if (!(amount.compareTo(sporadicPayDto.getAmount()) == 0)) {
            throw new BizException("订单金额异常");
        }

        OrderTypeEnum type = OrderTypeEnum.SPORADIC;
        String receiver = "PER";

        Integer userId = sporadicPayDto.getUserId();
        String orderNo = idGeneratorService.generatorId("payment") + "";
        String channelType = "";
        StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
        studentPaymentOrder.setUserId(userId);
        studentPaymentOrder.setGroupType(GroupType.SPORADIC);
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setType(type);
        studentPaymentOrder.setExpectAmount(amount);
        studentPaymentOrder.setActualAmount(amount);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setMusicGroupId(sporadicPayDto.getSporadicId().toString());
        studentPaymentOrderService.insert(studentPaymentOrder);

        studentPaymentOrder.setVersion(0);
        Date date = new Date();
        if (sporadicPayDto.getUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
            if(chargeInfo.getChargeType().getCode().equals(9)){
                throw new BizException("账户充值不支持余额支付");
            }
            SysUserCashAccount userCashAccount = sysUserCashAccountService.get(userId);

            if (userCashAccount == null) {
                throw new BizException("用户账户找不到");
            }
            if (userCashAccount.getBalance() != null && userCashAccount.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal balance = amount.compareTo(userCashAccount.getBalance()) >= 0 ? userCashAccount.getBalance() : amount;
                amount = amount.subtract(balance);
                studentPaymentOrder.setPaymentChannel("BALANCE");
                studentPaymentOrder.setActualAmount(amount);
                studentPaymentOrder.setBalancePaymentAmount(balance);
                sysUserCashAccountService.updateBalance(userId, balance.negate(), PlatformCashAccountDetailTypeEnum.SPORADIC, chargeInfo.getTitle());
            }
        }

        studentPaymentOrder.setPaymentChannel("BALANCE");
        studentPaymentOrder.setOrganId(chargeInfo.getOrganId());
        studentPaymentOrder.setRoutingOrganId(chargeInfo.getOrganId());
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        studentPaymentOrder.setVersion(studentPaymentOrder.getVersion() + 1);

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            Map<String, String> notifyMap = new HashMap<>();
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            notifyMap.put("channelType", channelType);
            notifyMap.put("orderNo", "");
            studentPaymentOrderService.updateOrder(notifyMap);
            return notifyMap;
        }

        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");

        Map<String, BigDecimal> classFee = new HashMap<>();
        classFee.put("course", BigDecimal.ZERO);
        classFee.put("instrument", BigDecimal.ZERO);
        classFee.put("accessories", BigDecimal.ZERO);
        classFee.put("other", amount);

        Map payMap = payService.getPayMap(
                amount,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/notify",
                baseApiUrl + "/api-student/studentOrder/paymentResult?orderNo=" + orderNo,
                chargeInfo.getTitle(),
                chargeInfo.getTitle(),
                userId,
                classFee,
                chargeInfo.getOrganId(),
                receiver
        );

        Map<String, BigDecimal> routingFee = (Map<String, BigDecimal>) payMap.get("routingFee");
        studentPaymentOrder.setOrganId(chargeInfo.getOrganId());
        studentPaymentOrder.setRoutingOrganId(chargeInfo.getOrganId());
        studentPaymentOrder.setComAmount(routingFee.get("COM"));
        studentPaymentOrder.setPerAmount(routingFee.get("PER"));
        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        return payMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map pay(RegisterPayDto registerPayDto) throws Exception {

        StudentRegistration studentRegistration = studentRegistrationService.get(registerPayDto.getRegisterId().longValue());
        if (studentRegistration == null) {
            throw new BizException("报名信息有误，请核查");
        }

        Integer userId = studentRegistration.getUserId();

        BigDecimal amount = registerPayDto.getAmount(); //前端获取的价格
        BigDecimal orderAmount = new BigDecimal("0");

        //获取课程价格
        MusicGroupSubjectPlan musicOneSubjectClassPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(studentRegistration.getMusicGroupId(), studentRegistration.getActualSubjectId());
        BigDecimal courseFee = musicOneSubjectClassPlan.getFee();
        if (studentRegistration.getTemporaryCourseFee() != null) {
            courseFee = studentRegistration.getTemporaryCourseFee();
        }
        orderAmount = orderAmount.add(courseFee);

        BigDecimal instrumentFee = BigDecimal.ZERO;
        BigDecimal accessoriesFee = BigDecimal.ZERO;
        BigDecimal otherFee = BigDecimal.ZERO;
        BigDecimal remitFee = BigDecimal.ZERO;

        //乐器及打包辅件
        List<MusicGroupSubjectGoodsGroup> goodsGroups = new ArrayList<>();
        if (studentRegistration.getTemporaryCourseFee() != null) {
            List<StudentPaymentOrderDetail> orderDetails = studentPaymentOrderDetailService.findUserApplyOrder(studentRegistration.getUserId(), DealStatusEnum.WAIT_PAY);
            for (StudentPaymentOrderDetail orderDetail : orderDetails) {
                if (orderDetail == null || orderDetail.getPrice() == null || orderDetail.getGoodsIdList() == null) {
                    continue;
                }
                MusicGroupSubjectGoodsGroup musicGroupSubjectGoodsGroup = new MusicGroupSubjectGoodsGroup();
                GoodsType goodsType = orderDetail.getType().equals(OrderDetailTypeEnum.MUSICAL) ? GoodsType.INSTRUMENT : GoodsType.ACCESSORIES;
                musicGroupSubjectGoodsGroup.setType(goodsType);
                musicGroupSubjectGoodsGroup.setGoodsIdList(orderDetail.getGoodsIdList());
                musicGroupSubjectGoodsGroup.setPrice(orderDetail.getPrice());
                musicGroupSubjectGoodsGroup.setKitGroupPurchaseType(orderDetail.getKitGroupPurchaseType());
                goodsGroups.add(musicGroupSubjectGoodsGroup);
                if (musicGroupSubjectGoodsGroup.getType().equals(GoodsType.INSTRUMENT)) {
                    instrumentFee = instrumentFee.add(orderDetail.getPrice());
                } else if (musicGroupSubjectGoodsGroup.getType().equals(GoodsType.ACCESSORIES)) {
                    accessoriesFee = accessoriesFee.add(orderDetail.getPrice());
                } else {
                    otherFee = otherFee.add(orderDetail.getPrice());
                }

                orderAmount = orderAmount.add(orderDetail.getPrice());
            }
        } else if (StringUtils.isNoneBlank(registerPayDto.getGoodsGroupIds())) {
            goodsGroups = musicGroupSubjectGoodsGroupService.findGoodsGroupByIds(registerPayDto.getGoodsGroupIds());
            for (MusicGroupSubjectGoodsGroup goodsGroup : goodsGroups) {
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && musicOneSubjectClassPlan.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.LEASE)) {
                    goodsGroup.setPrice(musicOneSubjectClassPlan.getDepositFee());
                    goodsGroup.setKitGroupPurchaseType(KitGroupPurchaseTypeEnum.LEASE);
                }
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && musicOneSubjectClassPlan.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.FREE)) {
                    goodsGroup.setPrice(new BigDecimal(0));
                }
                orderAmount = orderAmount.add(goodsGroup.getPrice());
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT)) {
                    instrumentFee = instrumentFee.add(goodsGroup.getPrice());
                } else if (goodsGroup.getType().equals(GoodsType.ACCESSORIES)) {
                    accessoriesFee = accessoriesFee.add(goodsGroup.getPrice());
                } else {
                    otherFee = otherFee.add(goodsGroup.getPrice());
                }
                //团购乐器减免课程费用
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && goodsGroup.getRemissionCourseFee() != null && musicOneSubjectClassPlan.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.GROUP)) {//团购
                    orderAmount = orderAmount.subtract(goodsGroup.getRemissionCourseFee());
                    courseFee = courseFee.subtract(goodsGroup.getRemissionCourseFee());
                }
            }
        } else if (registerPayDto.getGoodsGroups() != null && registerPayDto.getGoodsGroups().size() > 0) {
            String goodsGroupIds = registerPayDto.getGoodsGroups().keySet().stream().map(Object::toString).collect(Collectors.joining(","));
            goodsGroups = musicGroupSubjectGoodsGroupService.findGoodsGroupByIds(goodsGroupIds);
            for (MusicGroupSubjectGoodsGroup goodsGroup : goodsGroups) {
                Map<String, BigDecimal> groupType = JSONObject.parseObject(goodsGroup.getKitGroupPurchaseTypeJson(), new TypeReference<Map<String, BigDecimal>>() {
                });
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && registerPayDto.getGoodsGroups().get(goodsGroup.getId()).equals("GROUP")) {
                    if (!groupType.containsKey("GROUP")) {
                        throw new BizException("乐器提供方式不存在");
                    }
                    goodsGroup.setKitGroupPurchaseType(KitGroupPurchaseTypeEnum.GROUP);
                    remitFee = groupType.get("GROUP");
                }
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && registerPayDto.getGoodsGroups().get(goodsGroup.getId()).equals("LEASE")) {
                    if (!groupType.containsKey("LEASE")) {
                        throw new BizException("乐器提供方式不存在");
                    }
                    goodsGroup.setPrice(goodsGroup.getDepositFee());
                    goodsGroup.setKitGroupPurchaseType(KitGroupPurchaseTypeEnum.LEASE);
                    remitFee = groupType.get("LEASE");
                }
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && registerPayDto.getGoodsGroups().get(goodsGroup.getId()).equals("FREE")) {
                    if (!groupType.containsKey("FREE")) {
                        throw new BizException("乐器提供方式不存在");
                    }
                    goodsGroup.setPrice(new BigDecimal(0));
                    goodsGroup.setKitGroupPurchaseType(KitGroupPurchaseTypeEnum.FREE);
                    remitFee = groupType.get("FREE");
                }
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT)) {
                    instrumentFee = instrumentFee.add(goodsGroup.getPrice());
                } else if (goodsGroup.getType().equals(GoodsType.ACCESSORIES)) {
                    accessoriesFee = accessoriesFee.add(goodsGroup.getPrice());
                } else {
                    otherFee = otherFee.add(goodsGroup.getPrice());
                }
                orderAmount = orderAmount.add(goodsGroup.getPrice());
            }
            orderAmount = orderAmount.subtract(remitFee);
        }

        //单独辅件
        List<Goods> goodsList = null;
        if (registerPayDto.getGoodsIds() != null && !registerPayDto.getGoodsIds().equals("")) {
            goodsList = goodsService.findGoodsByIds(registerPayDto.getGoodsIds());
            for (Goods goods : goodsList) {
                orderAmount = orderAmount.add(goods.getGroupPurchasePrice());
                accessoriesFee = accessoriesFee.add(goods.getGroupPurchasePrice());
            }
        }

        //单独教谱
        List<Goods> otherGoodsList = null;
        if (registerPayDto.getOtherGoodsIds() != null && !registerPayDto.getOtherGoodsIds().equals("")) {
            otherGoodsList = goodsService.findGoodsByIds(registerPayDto.getOtherGoodsIds());
            for (Goods goods : otherGoodsList) {
                orderAmount = orderAmount.add(goods.getGroupPurchasePrice());
                otherFee = otherFee.add(goods.getGroupPurchasePrice());
            }
        }
        if (amount.compareTo(orderAmount) != 0) {
            throw new BizException("商品价格不符");
        }

        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new BizException("价格异常");
        }
        String orderNo = idGeneratorService.generatorId("payment") + "";

        String channelType = "";

        StudentPaymentOrder studentPaymentOrder = studentRegistrationService.addOrder(studentRegistration, amount, orderNo, channelType, courseFee, goodsGroups, goodsList, otherGoodsList);
        studentPaymentOrder.setVersion(0);

        Date date = new Date();
        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
        if (registerPayDto.getIsUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(userId);
            if (userCashAccount == null) {
                throw new BizException("用户账户找不到");
            }
            if (userCashAccount.getBalance() != null && userCashAccount.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal balance = amount.compareTo(userCashAccount.getBalance()) >= 0 ? userCashAccount.getBalance() : amount;
                amount = amount.subtract(balance);
                studentPaymentOrder.setPaymentChannel("BALANCE");
                studentPaymentOrder.setActualAmount(amount);
                studentPaymentOrder.setBalancePaymentAmount(balance);
                sysUserCashAccountService.updateBalance(userId, balance.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "乐团报名");
            }
        }
        studentPaymentOrder.setPaymentChannel("BALANCE");
        studentPaymentOrder.setRemitFee(remitFee);
        studentPaymentOrder.setOrganId(musicGroup.getOrganId());
        studentPaymentOrder.setRoutingOrganId(42);
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        studentPaymentOrder.setVersion(studentPaymentOrder.getVersion() + 1);

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            Map<String, String> notifyMap = new HashMap<>();
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            notifyMap.put("channelType", channelType);
            notifyMap.put("orderNo", "");
            studentPaymentOrderService.updateOrder(notifyMap);
            return notifyMap;
        }

        //分类费用 course，instrument，accessories，other
        Map<String, BigDecimal> classFee = new HashMap<>();
        classFee.put("course", courseFee);
        classFee.put("instrument", instrumentFee);
        classFee.put("accessories", accessoriesFee);
        classFee.put("other", otherFee);
        BigDecimal classFeeAmount = courseFee.add(instrumentFee).add(accessoriesFee).add(otherFee);

        if (amount.compareTo(classFeeAmount) < 0) {
            BigDecimal subAmount = classFeeAmount.subtract(amount);
            for (Map.Entry<String, BigDecimal> feeEntry : classFee.entrySet()) {
                if (subAmount.compareTo(feeEntry.getValue()) > 0) {
                    classFee.put(feeEntry.getKey(), BigDecimal.ZERO);
                    subAmount = subAmount.subtract(feeEntry.getValue());
                } else {
                    classFee.put(feeEntry.getKey(), feeEntry.getValue().subtract(subAmount));
                    break;
                }
            }
        }

        String orderSubject = "乐团报名";
        if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType().equals(CooperationOrgan.OwnershipType.COOPERATION)) {
            orderSubject = "乐团相关费用";
        }
        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");
        Map payMap = payService.getPayMap(
                amount,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/notify",
                baseApiUrl + "/api-student/studentOrder/paymentResult?orderNo=" + orderNo,
                orderSubject,
                orderSubject,
                userId,
                classFee,
                musicGroup.getOrganId()
        );

        Map<String, BigDecimal> routingFee = (Map<String, BigDecimal>) payMap.get("routingFee");
        studentPaymentOrder.setOrganId(musicGroup.getOrganId());
        studentPaymentOrder.setRoutingOrganId(42);
        studentPaymentOrder.setComAmount(routingFee.get("COM"));
        studentPaymentOrder.setPerAmount(routingFee.get("PER"));
        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        return payMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map rePay(RegisterPayDto registerPayDto) throws Exception {
        StudentRegistration studentRegistration = studentRegistrationService.get(registerPayDto.getRegisterId().longValue());
        if (studentRegistration == null) {
            throw new BizException("报名信息有误，请核查");
        }

        Integer userId = studentRegistration.getUserId();

        StudentPaymentOrder ApplyOrder = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(userId, studentRegistration.getMusicGroupId(), DealStatusEnum.ING);
        if (ApplyOrder == null) {
            throw new BizException("没有支付中的订单，请勿非法请求");
        }

        BigDecimal amount = registerPayDto.getAmount(); //前端获取的价格
        BigDecimal orderAmount = new BigDecimal("0");

        //获取课程价格
        MusicGroupSubjectPlan musicOneSubjectClassPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(studentRegistration.getMusicGroupId(), studentRegistration.getActualSubjectId());
        BigDecimal courseFee = musicOneSubjectClassPlan.getFee();
        if (studentRegistration.getTemporaryCourseFee() != null) {
            courseFee = studentRegistration.getTemporaryCourseFee();
        }
        orderAmount = orderAmount.add(courseFee);

        BigDecimal instrumentFee = BigDecimal.ZERO;
        BigDecimal accessoriesFee = BigDecimal.ZERO;
        BigDecimal otherFee = BigDecimal.ZERO;
        BigDecimal remitFee = BigDecimal.ZERO;

        //乐器及打包辅件
        List<MusicGroupSubjectGoodsGroup> goodsGroups = new ArrayList<>();
        if (studentRegistration.getTemporaryCourseFee() != null) {
            List<StudentPaymentOrderDetail> orderDetails = studentPaymentOrderDetailService.findUserApplyOrder(studentRegistration.getUserId(), DealStatusEnum.WAIT_PAY);
            for (StudentPaymentOrderDetail orderDetail : orderDetails) {
                if (orderDetail == null || orderDetail.getPrice() == null || orderDetail.getGoodsIdList() == null) {
                    continue;
                }
                MusicGroupSubjectGoodsGroup musicGroupSubjectGoodsGroup = new MusicGroupSubjectGoodsGroup();
                GoodsType goodsType = orderDetail.getType().equals(OrderDetailTypeEnum.MUSICAL) ? GoodsType.INSTRUMENT : GoodsType.ACCESSORIES;
                musicGroupSubjectGoodsGroup.setType(goodsType);
                musicGroupSubjectGoodsGroup.setGoodsIdList(orderDetail.getGoodsIdList());
                musicGroupSubjectGoodsGroup.setPrice(orderDetail.getPrice());
                musicGroupSubjectGoodsGroup.setKitGroupPurchaseType(orderDetail.getKitGroupPurchaseType());
                goodsGroups.add(musicGroupSubjectGoodsGroup);

                if (musicGroupSubjectGoodsGroup.getType().equals(GoodsType.INSTRUMENT)) {
                    instrumentFee = instrumentFee.add(orderDetail.getPrice());
                } else if (musicGroupSubjectGoodsGroup.getType().equals(GoodsType.ACCESSORIES)) {
                    accessoriesFee = accessoriesFee.add(orderDetail.getPrice());
                } else {
                    otherFee = otherFee.add(orderDetail.getPrice());
                }
                orderAmount = orderAmount.add(orderDetail.getPrice());
            }
        } else if (StringUtils.isNoneBlank(registerPayDto.getGoodsGroupIds())) {
            goodsGroups = musicGroupSubjectGoodsGroupService.findGoodsGroupByIds(registerPayDto.getGoodsGroupIds());
            for (MusicGroupSubjectGoodsGroup goodsGroup : goodsGroups) {
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && musicOneSubjectClassPlan.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.LEASE)) {
                    goodsGroup.setPrice(musicOneSubjectClassPlan.getDepositFee());
                }
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && musicOneSubjectClassPlan.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.FREE)) {
                    goodsGroup.setPrice(new BigDecimal(0));
                }

                orderAmount = orderAmount.add(goodsGroup.getPrice());
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT)) {
                    instrumentFee = instrumentFee.add(goodsGroup.getPrice());
                } else if (goodsGroup.getType().equals(GoodsType.ACCESSORIES)) {
                    accessoriesFee = accessoriesFee.add(goodsGroup.getPrice());
                } else {
                    otherFee = otherFee.add(goodsGroup.getPrice());
                }
                //团购乐器减免课程费用
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && goodsGroup.getRemissionCourseFee() != null && musicOneSubjectClassPlan.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.GROUP)) {//团购
                    orderAmount = orderAmount.subtract(goodsGroup.getRemissionCourseFee());
                    courseFee.subtract(goodsGroup.getRemissionCourseFee());
                }
            }
        } else if (registerPayDto.getGoodsGroups() != null && registerPayDto.getGoodsGroups().size() > 0) {
            String goodsGroupIds = registerPayDto.getGoodsGroups().keySet().stream().map(Object::toString).collect(Collectors.joining(","));
            goodsGroups = musicGroupSubjectGoodsGroupService.findGoodsGroupByIds(goodsGroupIds);
            for (MusicGroupSubjectGoodsGroup goodsGroup : goodsGroups) {
                Map<String, BigDecimal> groupType = JSONObject.parseObject(goodsGroup.getKitGroupPurchaseTypeJson(), new TypeReference<Map<String, BigDecimal>>() {
                });
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && registerPayDto.getGoodsGroups().get(goodsGroup.getId()).equals("GROUP")) {
                    if (!groupType.containsKey("GROUP")) {
                        throw new BizException("乐器提供方式不存在");
                    }
                    goodsGroup.setKitGroupPurchaseType(KitGroupPurchaseTypeEnum.GROUP);
                    remitFee = groupType.get("GROUP");
                }
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && registerPayDto.getGoodsGroups().get(goodsGroup.getId()).equals("LEASE")) {
                    if (!groupType.containsKey("LEASE")) {
                        throw new BizException("乐器提供方式不存在");
                    }
                    goodsGroup.setPrice(goodsGroup.getDepositFee());
                    goodsGroup.setKitGroupPurchaseType(KitGroupPurchaseTypeEnum.LEASE);
                    remitFee = groupType.get("LEASE");
                }
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT) && registerPayDto.getGoodsGroups().get(goodsGroup.getId()).equals("FREE")) {
                    if (!groupType.containsKey("FREE")) {
                        throw new BizException("乐器提供方式不存在");
                    }
                    goodsGroup.setPrice(new BigDecimal(0));
                    goodsGroup.setKitGroupPurchaseType(KitGroupPurchaseTypeEnum.FREE);
                    remitFee = groupType.get("FREE");
                }
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT)) {
                    instrumentFee = instrumentFee.add(goodsGroup.getPrice());
                } else if (goodsGroup.getType().equals(GoodsType.ACCESSORIES)) {
                    accessoriesFee = accessoriesFee.add(goodsGroup.getPrice());
                } else {
                    otherFee = otherFee.add(goodsGroup.getPrice());
                }
                orderAmount = orderAmount.add(goodsGroup.getPrice());
            }
            orderAmount = orderAmount.subtract(remitFee);
        }

        //单独辅件
        List<Goods> goodsList = null;
        if (registerPayDto.getGoodsIds() != null && !registerPayDto.getGoodsIds().equals("")) {
            goodsList = goodsService.findGoodsByIds(registerPayDto.getGoodsIds());
            for (Goods goods : goodsList) {
                orderAmount = orderAmount.add(goods.getGroupPurchasePrice());
                accessoriesFee = accessoriesFee.add(goods.getGroupPurchasePrice());
            }
        }

        //单独教谱
        List<Goods> otherGoodsList = null;
        if (registerPayDto.getOtherGoodsIds() != null && !registerPayDto.getOtherGoodsIds().equals("")) {
            otherGoodsList = goodsService.findGoodsByIds(registerPayDto.getOtherGoodsIds());
            for (Goods goods : otherGoodsList) {
                orderAmount = orderAmount.add(goods.getGroupPurchasePrice());
                otherFee = otherFee.add(goods.getGroupPurchasePrice());
            }
        }
        if (amount.compareTo(orderAmount) != 0) {
            throw new BizException("商品价格不符");
        }

        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new BizException("价格异常");
        }

        String orderNo = idGeneratorService.generatorId("payment") + "";

        String channelType = "";

        StudentPaymentOrder studentPaymentOrder = studentRegistrationService.reAddOrder(userId, amount, orderNo, channelType, courseFee, goodsGroups, goodsList, otherGoodsList, studentRegistration.getMusicGroupId(), ApplyOrder);
        studentPaymentOrder.setVersion(0);
        Date date = new Date();

        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
        if (registerPayDto.getIsUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
            SysUserCashAccount userCashAccount = sysUserCashAccountService.get(userId);
            if (userCashAccount == null) {
                throw new BizException("用户账户找不到");
            }
            if (userCashAccount.getBalance() != null && userCashAccount.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal balance = amount.compareTo(userCashAccount.getBalance()) >= 0 ? userCashAccount.getBalance() : amount;
                amount = amount.subtract(balance);
                studentPaymentOrder.setPaymentChannel("BALANCE");
                studentPaymentOrder.setActualAmount(amount);
                studentPaymentOrder.setBalancePaymentAmount(balance);
                sysUserCashAccountService.updateBalance(userId, balance.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "乐团报名");
            }
        }
        studentPaymentOrder.setPaymentChannel("BALANCE");
        studentPaymentOrder.setRemitFee(remitFee);
        studentPaymentOrder.setOrganId(musicGroup.getOrganId());
        studentPaymentOrder.setRoutingOrganId(42);
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        studentPaymentOrder.setVersion(studentPaymentOrder.getVersion() + 1);

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            Map<String, String> notifyMap = new HashMap<>();
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            notifyMap.put("channelType", channelType);
            notifyMap.put("orderNo", "");
            studentPaymentOrderService.updateOrder(notifyMap);
            return notifyMap;
        }

        //分类费用 course，instrument，accessories，other
        Map<String, BigDecimal> classFee = new HashMap<>();
        classFee.put("course", courseFee);
        classFee.put("instrument", instrumentFee);
        classFee.put("accessories", accessoriesFee);
        classFee.put("other", otherFee);
        BigDecimal classFeeAmount = courseFee.add(instrumentFee).add(accessoriesFee).add(otherFee);

        if (amount.compareTo(classFeeAmount) < 0) {
            BigDecimal subAmount = classFeeAmount.subtract(amount);
            for (Map.Entry<String, BigDecimal> feeEntry : classFee.entrySet()) {
                if (subAmount.compareTo(feeEntry.getValue()) > 0) {
                    classFee.put(feeEntry.getKey(), BigDecimal.ZERO);
                    subAmount = subAmount.subtract(feeEntry.getValue());
                } else {
                    classFee.put(feeEntry.getKey(), feeEntry.getValue().subtract(subAmount));
                    break;
                }
            }
        }
        String orderSubject = "乐团报名";
        if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType().equals(CooperationOrgan.OwnershipType.COOPERATION)) {
            orderSubject = "乐团相关费用";
        }
        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");
        Map payMap = payService.getPayMap(
                amount,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/notify",
                baseApiUrl + "/api-student/studentOrder/paymentResult?orderNo=" + orderNo,
                orderSubject,
                orderSubject,
                userId,
                classFee,
                musicGroup.getOrganId()
        );

        Map<String, BigDecimal> routingFee = (Map<String, BigDecimal>) payMap.get("routingFee");
        studentPaymentOrder.setOrganId(musicGroup.getOrganId());
        studentPaymentOrder.setRoutingOrganId(42);
        studentPaymentOrder.setComAmount(routingFee.get("COM"));
        studentPaymentOrder.setPerAmount(routingFee.get("PER"));
        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        return payMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSubjectInfo(SubFeeSettingDto subFeeSettingDto) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("身份校验失败");
        }
        String musicGroupId = subFeeSettingDto.getMusicGroupId();
        //乐团状态是否正确
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup != null) {
            if (subFeeSettingDto.getMusicGroupStatus() == null) {
                throw new BizException("参数校验异常");
            }
            if (musicGroup.getStatus() == MusicGroupStatusEnum.DRAFT || musicGroup.getStatus() == MusicGroupStatusEnum.AUDIT_FAILED) {
                musicGroup.setStatus(subFeeSettingDto.getMusicGroupStatus());
                musicGroup.setUpdateTime(new Date());
                musicGroupDao.update(musicGroup);
            }
            //记录日志信息
            musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "修改乐团计划声部、乐器", sysUser.getId(), JSONObject.toJSONString(subFeeSettingDto)));
            //删除原有的乐团声部规划
            musicGroupSubjectPlanDao.delByMusicGroupId(musicGroupId);
            //删除原有的声部商品组合
            musicGroupSubjectGoodsGroupDao.delByMusicGroupId(subFeeSettingDto.getMusicGroupId());
            //如果是进行中，补充缴费信息
//            if(musicGroup.getStatus() == MusicGroupStatusEnum.PROGRESS){
//                List<MusicGroupStudentFee> musicGroupStudentFees = musicGroupStudentFeeDao.initMusicGroupStudentFee(musicGroupId);
//                if(musicGroupStudentFees != null && musicGroupStudentFees.size() > 0){
//                    Date nextPaymentDate = musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, null,null);
//                    musicGroupStudentFeeDao.batchInsert(musicGroupStudentFees,nextPaymentDate,"PAID_COMPLETED");
//                }
//            }
            List<MusicGroupSubjectPlan> musicGroupSubjectPlans = subFeeSettingDto.getMusicGroupSubjectPlans();
            if (musicGroupSubjectPlans != null && musicGroupSubjectPlans.size() > 0) {
                musicGroupSubjectPlans.forEach(e -> {
                    //修改课程费用
                    musicGroupStudentFeeDao.updateCourseFee(musicGroupId, e.getSubjectId(), e.getFee());
                });
                musicGroupSubjectPlanDao.batchAdd(musicGroupSubjectPlans, musicGroupId);
            }
            if (subFeeSettingDto.getMusicGroupSubjectGoodsGroups() != null && subFeeSettingDto.getMusicGroupSubjectGoodsGroups().size() > 0) {
                for (MusicGroupSubjectGoodsGroup musicGroupSubjectGoodsGroup : subFeeSettingDto.getMusicGroupSubjectGoodsGroups()) {
                    if(musicGroupSubjectGoodsGroup.getType().equals(GoodsType.INSTRUMENT) && (musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson() == null
                            || musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson().isEmpty()
                            || musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson().equals("{}"))){
                        throw new BizException(musicGroupSubjectGoodsGroup.getName()+" 请选择提供方式");
                    }
                }

                musicGroupSubjectGoodsGroupDao.batchInsert(subFeeSettingDto.getMusicGroupSubjectGoodsGroups(), musicGroupId);
            }
        } else {
            throw new BizException("乐团信息不存在");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateExpectedStudentNum(List<UpdateExpectedNumDto> updateExpectedNumDtos) {
        updateExpectedNumDtos.forEach(e -> {
            MusicGroupSubjectPlan musicGroupSubjectPlan = musicGroupSubjectPlanDao.get(e.getMusicGroupSubjectPlanId());
            musicGroupSubjectPlan.setExpectedStudentNum(e.getExpectedStudentNum());
            musicGroupSubjectPlanDao.update(musicGroupSubjectPlan);
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void musicGroupAction(String musicGroupId) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = saveLog(musicGroupId, MusicGroupStatusEnum.PREPARE);
        //乐器采购清单是否确认
        Map<String, Object> param = new HashMap<>();
        param.put("musicGroupId", musicGroupId);
        int i = musicGroupPurchaseListDao.queryCount(param);
        if (i <= 0) {
            throw new BizException("采购清单未确认");
        }
        //课酬是否确认
        Integer courseScheduleNum = courseScheduleDao.countCourseScheduleByMusicGroupId(musicGroupId);
        if (courseScheduleNum != null && courseScheduleNum > 0) {
            if (classGroupService.checkSetSalary(musicGroupId) == false) {
                throw new BizException("课酬未确认");
            }
        }
//        updateTeamTeacher(musicGroup, musicGroup);
        //生成学员费用表
        List<MusicGroupStudentFee> musicGroupStudentFees = musicGroupStudentFeeDao.initMusicGroupStudentFee(musicGroupId);
        if (musicGroupStudentFees != null && musicGroupStudentFees.size() > 0) {
            musicGroupStudentFeeDao.batchInsert(musicGroupStudentFees, musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, null, null), "PAID_COMPLETED");
        }
        musicGroupStudentFeeDao.batchUpdateCalenders(musicGroupId);
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "确认开团(筹备中 -> 进行中)", sysUser.getId(), ""));
        musicGroup.setStatus(MusicGroupStatusEnum.PROGRESS);
        //获取所有已缴费学员人数
        List<StudentRegistration> studentRegistrations = studentRegistrationDao.queryStudentByMusicGroupId(musicGroupId);
        musicGroup.setGroupMemberNum(studentRegistrations == null ? 0 : studentRegistrations.size());
        musicGroup.setBillStartDate(new Date());
        musicGroupDao.update(musicGroup);
        //给老师发送乐团成立通知
        Map<Integer, String> map = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertMybatisMap(musicGroupDao.queryTeacherIdMap(musicGroupId))), HashMap.class);
        if (map != null && map.size() > 0) {
            sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.TEACHER_PUSH_MUSIC_GROUP_COURSE_ADD_PLAN,
                    map, null, 0, "1", "TEACHER", musicGroup.getName());
        }
        Set<Integer> roleIds = new HashSet<>(5);
        roleIds.add(SysUserRole.SECTION_MANAGER);
        roleIds.add(SysUserRole.EDUCATIONAL_TEACHER);
        roleIds.add(SysUserRole.OPERATION_EXECUTIVE);
        roleIds.add(SysUserRole.ADMISSIONS_DIRECTOR);
        roleIds.add(SysUserRole.DEAN_OF_STUDIES);

        sysMessageService.batchSeoMessage(musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId()), MessageTypeEnum.BACKSTAGE_ACTION_GROUP, "1", musicGroup.getName());
    }

    private MusicGroup saveLog(String musicGroupId, MusicGroupStatusEnum statusEnum) throws Exception {
        Date date = new Date();
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团信息不存在");
        }
        if (musicGroup.getStatus() != statusEnum) {
            throw new BizException("当前乐团状态不支持此操作");
        }
        musicGroup.setUpdateTime(date);
        return musicGroup;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void musicGroupAudit(String musicGroupId) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = saveLog(musicGroupId, MusicGroupStatusEnum.DRAFT);
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "提交审核（草稿 -> 审核中）", sysUser.getId(), ""));
        musicGroup.setStatus(MusicGroupStatusEnum.AUDIT);
        musicGroupDao.update(musicGroup);
        Set<Integer> roleIds = new HashSet<>(1);
        roleIds.add(SysUserRole.SECTION_MANAGER);

        sysMessageService.batchSeoMessage(musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId()), MessageTypeEnum.BACKSTAGE_CREATE_MUSIC_GROUP_APPLY, "", sysUser.getUsername());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void musicGroupAuditFailed(String musicGroupId, String memo) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = saveLog(musicGroupId, MusicGroupStatusEnum.AUDIT);
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "审核失败（审核中 -> 审核失败）", sysUser.getId(), memo));
        musicGroup.setMemo(memo);
        musicGroup.setStatus(MusicGroupStatusEnum.AUDIT_FAILED);
        musicGroupDao.update(musicGroup);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void musicGroupAuditSuccess(String musicGroupId) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = saveLog(musicGroupId, MusicGroupStatusEnum.AUDIT);
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "审核通过（审核中 -> 报名中）", sysUser.getId(), ""));
        musicGroup.setStatus(MusicGroupStatusEnum.APPLY);
        musicGroupDao.update(musicGroup);
        Set<Integer> roleIds = new HashSet<>(3);
        roleIds.add(SysUserRole.EDUCATIONAL_TEACHER);
        roleIds.add(SysUserRole.OPERATION_EXECUTIVE);
        roleIds.add(SysUserRole.ADMISSIONS_DIRECTOR);

        sysMessageService.batchSeoMessage(musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId()), MessageTypeEnum.BACKSTAGE_ACTION_APPLY, "", musicGroup.getName());
    }

    @Override
    public void pushMessage(String musicGroupId) throws IOException {
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
            //是否有基础训练班
            Integer num = classGroupDao.countClassNumByType(musicGroupId);
            if(num != null && num > 0){
                Map<Integer, String> studentMap = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertMybatisMap(studentRegistrationDao.findIdMapByMusicGroupId(musicGroupId, 2))), HashMap.class);
                if (studentMap != null && studentMap.size() > 0) {
                    String baseURL = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);
                    String url = baseURL + "/#/smallRegister?musicGroupId=" + musicGroupId;
                    String serverPhone = sysConfigDao.findConfigValue(SysConfigService.SERVER_PHONE);
                    sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.SMS_BASICS_SKILL_APPLY_MESSAGE,
                            studentMap, null, 0, "5?" + url, "STUDENT", musicGroup.getName(), HttpUtil.getSortUrl(url), serverPhone);
                }
            }
        }
    }

//    @Override
//    public void musicGroupStudentFeePatch(List<String> musicGroupIds) {
//        if(musicGroupIds != null && musicGroupIds.size() > 0){
//            List<MusicGroupStudentFee> musicGroupStudentFees = null;
//            for (String musicGroupId: musicGroupIds) {
//                musicGroupStudentFees = musicGroupStudentFeeDao.initMusicGroupStudentFee(musicGroupId);
//                if(musicGroupStudentFees != null && musicGroupStudentFees.size() > 0){
//                    musicGroupStudentFeeDao.batchInsert(musicGroupStudentFees,musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, null,null),"PAID_COMPLETED");
//                }
//            }
//        }
//    }

    @Override
    public List<MusicCardDto> queryUserMusicGroups(Integer userId) {
        List<MusicCardDto> musicCardDtos = musicGroupDao.queryUserMusicGroups(userId);
        Set<String> musicGroupIds = musicCardDtos.stream().map(MusicCardDto::getMusicGroupId).collect(Collectors.toSet());
        Map<String, String> paymentStatus = MapUtil.convertMybatisMap(musicGroupStudentFeeDao.queryUserPaymentStatus(userId, StringUtils.join(musicGroupIds, ",")));
        // 获取学员在该乐团续费状态
        musicCardDtos.forEach(e -> {
            e.setPaymentStatus(paymentStatus.get(e.getMusicGroupId()));
        });
        return musicCardDtos;
    }

    @Override
    public MusicCardDto queryPersonalMusicGroups(Integer userId) {
        SysUser sysUser = sysUserFeignService.queryUserById(userId);
        if (sysUser == null) {
            throw new BizException("用户不存在");
        }
        MusicCardDto musicCardDto = musicGroupDao.queryPersonalMusicGroups(userId);
        if (musicCardDto == null) {
            musicCardDto = new MusicCardDto();
            musicCardDto.setUserName(sysUser.getUsername());
        }
        musicCardDto.setMusicGroupNum(musicGroupDao.countUserMusicGroups(userId));
        musicCardDto.setVipClassNum(classGroupStudentMapperDao.countUserGroups(userId, ClassGroupTypeEnum.VIP.getCode()));
        return musicCardDto;
    }

    @Override
    public List<BasicUserDto> findTeachersByStuId(Integer studentId,String search) {
        //获取相关乐团老师列表
        Set<Integer> teacherIds = teacherDao.findMusicTeacherIds(studentId);
        //获取学员所在乐团列表
        List<String> musicGroupIds = studentRegistrationDao.queryStudentMusicGroup(studentId);
        if(musicGroupIds != null && musicGroupIds.size() > 0){
            List<MusicGroup> musicGroups = musicGroupDao.queryListByIds(StringUtils.join(musicGroupIds, ","));
            musicGroups.forEach(e->{
                teacherIds.add(e.getDirectorUserId());
                teacherIds.add(e.getEducationalTeacherId());
                teacherIds.add(e.getTeamTeacherId());
            });
        }
        //获取相关vip课老师列表
        teacherIds.addAll(teacherDao.findVipTeacherIds(studentId));
        //获取陪练课老师列表
        teacherIds.addAll(teacherDao.findPracticeTeacherIds(studentId));
        //获取陪练课,vip课代课老师关联
        teacherIds.addAll(teacherDao.findCloseCourseTeacherIds(studentId));
        if(teacherIds.size() > 0){
        	return teacherDao.queryTeacherBaseInfo(teacherIds,search);
        }
        return new ArrayList<BasicUserDto>();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean cancelMusicGroup(String musicGroupId) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.getLocked(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团找不到");
        }

        if (musicGroup.getStatus() != MusicGroupStatusEnum.PROGRESS) {
            musicGroup.setStatus(MusicGroupStatusEnum.CANCELED);
            musicGroup.setUpdateTime(new Date());
            musicGroupDao.update(musicGroup);
        } else {
            throw new BizException("乐团当前状态是{}，不能取消", musicGroup.getStatus().getMsg());
        }

        // 查询是否有中间状态的缴费信息
        List<StudentPaymentOrder> studentPaymentOrders = studentPaymentOrderDao.queryByDealStatus(musicGroupId, OrderTypeEnum.APPLY, DealStatusEnum.ING);

        if (studentPaymentOrders != null && studentPaymentOrders.size() > 0) {
            throw new BizException("缴费存在交易中的数据，不能取消乐团");
        }

        //删除续费记录
        musicGroupStudentFeeDao.deleteByMusicGroupId(musicGroupId, null);

        // 删除课表
        courseScheduleDao.deleteCourseSchedulesByMusicGroupID(musicGroupId, GroupType.MUSIC);
        // 删除每节课的课酬
        courseScheduleStudentPaymentDao.deleteByMusicGroupId(musicGroupId, GroupType.MUSIC);
        courseScheduleTeacherSalaryDao.deleteByMusicGroupId(musicGroupId, GroupType.MUSIC);

        //删除考勤
        teacherAttendanceDao.deleteByMusicGroupId(musicGroupId, GroupType.MUSIC);

        // 查询已缴费信息
        studentPaymentOrders = studentPaymentOrderDao.queryByDealStatus(musicGroupId, OrderTypeEnum.APPLY, DealStatusEnum.SUCCESS);

        // 退费
        for (StudentPaymentOrder order : studentPaymentOrders) {
            sysUserCashAccountService.updateBalance(order.getUserId(), order.getActualAmount());
            // 增加交易流水
            sysUserCashAccountDetailService.addCashAccountDetail(order.getUserId(), order.getActualAmount(), SysUserCashAccountDetailService.MUSIC_GROUP
                    + musicGroupId, "", PlatformCashAccountDetailTypeEnum.REFUNDS, null, DealStatusEnum.SUCCESS, "取消乐团", null);
        }
        //获取当前乐团所有已报名学员
        if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
            List<StudentRegistration> registrations = studentRegistrationDao.findClassGroupStu(musicGroupId, null);
            if (registrations != null && registrations.size() > 0) {
                Map<Integer, String> map = new HashMap<>(registrations.size());
                registrations.forEach(e -> {
                    map.put(e.getUserId(), e.getUserId().toString());
                });
                sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_MUSIC_GROUP_CLOSE,
                        map, null, 0, "1", "STUDENT", musicGroup.getName(), sysConfigDao.findConfigValue(SysConfigService.REFUND_PERIOD));
            }
        }
        //记录建团日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "取消乐团", sysUser.getId(), ""));
        Set<Integer> roleIds = new HashSet<>(2);
        roleIds.add(SysUserRole.SECTION_MANAGER);
        roleIds.add(SysUserRole.OPERATION_EXECUTIVE);

        sysMessageService.batchSeoMessage(musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId()), MessageTypeEnum.BACKSTAGE_MUSIC_GROUP_STOP, "1", musicGroup.getName());
        return true;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean pauseMusicGroup(String musicGroupId) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团找不到");
        }

        if (musicGroup.getStatus() != MusicGroupStatusEnum.PROGRESS) {
            throw new BizException("乐团当前状态是{}，不能暂停", musicGroup.getStatus().getMsg());
        }

        musicGroup.setStatus(MusicGroupStatusEnum.PAUSE);
        musicGroup.setUpdateTime(new Date());
        musicGroupDao.update(musicGroup);

        // 清除下次缴费时间
        musicGroupStudentFeeDao.updateNextPaymentDate(musicGroupId, null);
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "暂停乐团", sysUser.getId(), ""));

        //删除课表
        courseScheduleDao.logicDeleteCourseSchedulesByMusicGroupID(musicGroup.getId());

        return true;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean resumeMusicGroup(String musicGroupId) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团找不到");
        }

        if (musicGroup.getStatus() != MusicGroupStatusEnum.PAUSE) {
            throw new BizException("乐团当前状态是{}，不能恢复", musicGroup.getStatus().getMsg());
        }

        musicGroup.setStatus(MusicGroupStatusEnum.PROGRESS);
        musicGroup.setUpdateTime(new Date());
        musicGroupDao.update(musicGroup);

        // 重新设置下次缴费时间
        List<MusicGroupStudentFee> fees = musicGroupStudentFeeDao.queryByMusicGroupId(musicGroupId);
        Date date = new Date();
        fees.forEach(e -> {
            e.setNextPaymentDate(musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, null, e));
            e.setUpdateTime(date);
        });
        musicGroupStudentFeeDao.batchUpdate(fees);
//        musicGroupStudentFeeDao.updateNextPaymentDate(musicGroupId, musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, null));
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "恢复乐团", sysUser.getId(), ""));

        //恢复课表
        courseScheduleDao.resumeCourseScheduleByMusicGroupId(musicGroup.getId());

        return true;
    }

    @Override
    public boolean extensionPayment(String musicGroupId, Date expireDate) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团找不到");
        }

        if (musicGroup.getStatus() != MusicGroupStatusEnum.PAY) {
            throw new BizException("乐团当前状态是{}，延长缴费", musicGroup.getStatus().getMsg());
        }

        Date date = new Date();

        if (date.after(expireDate)) {
            throw new BizException("日期设置错误");
        }

        musicGroup.setPaymentExpireDate(expireDate);
        musicGroup.setApplyExpireDate(expireDate);
        musicGroup.setUpdateTime(date);
        musicGroupDao.update(musicGroup);
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "延长缴费", sysUser.getId(), ""));
        Set<Integer> roleIds = new HashSet<>(4);
        roleIds.add(SysUserRole.SECTION_MANAGER);
        roleIds.add(SysUserRole.EDUCATIONAL_TEACHER);
        roleIds.add(SysUserRole.OPERATION_EXECUTIVE);
        roleIds.add(SysUserRole.ADMISSIONS_DIRECTOR);

        sysMessageService.batchSeoMessage(musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId()), MessageTypeEnum.BACKSTAGE_LENGTHEN_PAYMENT, "", musicGroup.getName());
        return true;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean applyQuitMusicGroup(String musicGroupId) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团不存在");
        }

        MusicGroupQuit musicGroupQuit = new MusicGroupQuit();
        musicGroupQuit.setCreateTime(new Date());
        musicGroupQuit.setJoinDate(sysUser.getCreateTime());
        musicGroupQuit.setMusicGroupId(musicGroupId);
        musicGroupQuit.setUserId(sysUser.getId());
        musicGroupQuit.setStatus(ApprovalStatus.PROCESSING);

        musicGroupQuitDao.insert(musicGroupQuit);
        Set<Integer> roleIds = new HashSet<>(1);
        roleIds.add(SysUserRole.EDUCATIONAL_TEACHER);
        Map<String, Object> memo = new HashMap<>(2);
        memo.put("Id", musicGroupQuit.getId());
        memo.put("type", "MUSICGROUP");

        sysMessageService.batchSeoMessage(musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId()), MessageTypeEnum.BACKSTAGE_STUDENT_APPLY_QUIT_GROUP, JSONObject.toJSONString(memo), sysUser.getUsername());
        return true;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean approveQuitMusicGroup(Long id, ApprovalStatus status, String reason, boolean isRefundCourseFee, boolean isRefundInstrumentFee,
                                         boolean isRefundTeachingAssistantsFee) {
        MusicGroupQuit musicGroupQuit = musicGroupQuitDao.get(id);
        if (musicGroupQuit == null) {
            throw new BizException("数据不存在");
        }
        Date date = new Date();

        String musicGroupId = musicGroupQuit.getMusicGroupId();
        Integer userId = musicGroupQuit.getUserId();

        musicGroupQuit.setStatus(status);
        musicGroupQuit.setReason(reason);
        musicGroupQuit.setQuitDate(date);
        musicGroupQuitDao.update(musicGroupQuit);

        if (status == ApprovalStatus.APPROVED) {

            StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
            if (studentRegistration == null) {
                throw new BizException("用户注册信息不存在");
            }
            //更新学员在班级的状态
            classGroupStudentMapperDao.deleteStudentByMusicGroupId(musicGroupId, userId);

            List<Integer> classGroupIdList = classGroupStudentMapperDao.queryClassGroupIdList(musicGroupId, userId, GroupType.MUSIC);
            if (classGroupIdList != null && classGroupIdList.size() > 0) {
                //更新班级人数
                //classGroupDao.batchUpdateStudentNumMinusOne(classGroupIdList);

                List<ImGroupModel> imGroupModels = new ArrayList<>();
                ImGroupMember[] imGroupMember = {new ImGroupMember(userId.toString())};
                for (Integer classGroupId : classGroupIdList) {
                    imGroupModels.add(new ImGroupModel(classGroupId + "", imGroupMember, ""));
                }
                imFeignService.groupBatchQuit(imGroupModels);
            }

            List<CourseSchedule> musicGroupCourseSchedules = courseScheduleDao.findMusicGroupCourseSchedulesWithStudent(musicGroupId, GroupType.MUSIC.getCode(), CourseStatusEnum.NOT_START.getCode(), userId);
            if (!CollectionUtils.isEmpty(musicGroupCourseSchedules)) {
                List<Long> courseScheduleIds = musicGroupCourseSchedules.stream().map(courseSchedule -> courseSchedule.getId()).collect(Collectors.toList());

                // 删除未上课
                courseScheduleDao.deleteMusicGroupCourseSchedulesWithStudent(courseScheduleIds, userId);

                //删除学生缴费表
                courseScheduleStudentPaymentDao.deleteStudentCourseSchedule(userId, musicGroupCourseSchedules);
            }

            //删除续费周期
            musicGroupStudentFeeDao.deleteByUserIdAndMusicGroupId(userId, musicGroupId);

            // 退团
            studentRegistration.setMusicGroupStatus(ClassGroupStudentStatusEnum.QUIT);
            studentRegistration.setUpdateTime(date);

            studentRegistrationDao.update(studentRegistration);

            BigDecimal amount = new BigDecimal(0);

            // 判断乐器是否是租赁
            // MusicGroupSubjectPlan musicGroupSubjectPlan = musicGroupSubjectPlanDao.getMusicOneSubjectClassPlan(musicGroupId, subjectId);

            StudentPaymentOrder studentPaymentOrder = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(userId, musicGroupId, DealStatusEnum.SUCCESS);

            if (studentPaymentOrder == null) {
                //兼容历史数据
                return true;
            }

            List<StudentPaymentOrderDetail> orderDetailList = studentPaymentOrderDetailDao.findApplyOrderGoods(studentPaymentOrder.getId());

            BigDecimal remitFee = studentPaymentOrder.getRemitFee() == null ? BigDecimal.ZERO : studentPaymentOrder.getRemitFee();
            for (StudentPaymentOrderDetail detail : orderDetailList) {
                if (remitFee.compareTo(detail.getPrice()) >= 0) {
                    remitFee = remitFee.subtract(detail.getPrice());
                    detail.setPrice(BigDecimal.ZERO);
                } else {
                    detail.setPrice(detail.getPrice().subtract(remitFee));
                    remitFee = BigDecimal.ZERO;
                }

                if (isRefundCourseFee) {
                    // 退课程费用
                    if (detail.getType() == OrderDetailTypeEnum.COURSE) {
                        amount = amount.add(detail.getPrice());
                    }
                }
                if (isRefundInstrumentFee) {
                    // 退乐器费用
                    if (detail.getType() == OrderDetailTypeEnum.MUSICAL) {
                        amount = amount.add(detail.getPrice());
                    }

                }
                if (isRefundTeachingAssistantsFee) {
                    // 退教辅费用
                    if (detail.getType() == OrderDetailTypeEnum.ACCESSORIES || detail.getType() == OrderDetailTypeEnum.TEACHING) {
                        amount = amount.add(detail.getPrice());
                    }
                }
            }
            if (amount.doubleValue() > 0) {
                // 增加交易流水
                sysUserCashAccountDetailService.addCashAccountDetail(userId, amount, SysUserCashAccountDetailService.MUSIC_GROUP + musicGroupId, "",
                        PlatformCashAccountDetailTypeEnum.REFUNDS, null, DealStatusEnum.SUCCESS, "退出乐团", null);
            }
        }
        return true;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean directQuitMusicGroup(String musicGroupId, Integer userId, String reason, boolean isRefundCourseFee, boolean isRefundInstrumentFee,
                                        boolean isRefundTeachingAssistantsFee) {

        SysUser sysUser = sysUserFeignService.queryUserById(userId);
        if (sysUser == null) {
            throw new BizException("获取用户信息失败");
        }

        Date date = new Date();

        MusicGroupQuit musicGroupQuit = new MusicGroupQuit();
        musicGroupQuit.setCreateTime(date);
        musicGroupQuit.setJoinDate(sysUser.getCreateTime());
        musicGroupQuit.setMusicGroupId(musicGroupId);
        musicGroupQuit.setUserId(sysUser.getId());
        musicGroupQuit.setStatus(ApprovalStatus.APPROVED);
        musicGroupQuit.setReason(reason);
        musicGroupQuit.setQuitDate(date);

        musicGroupQuitDao.insert(musicGroupQuit);

        // 判断乐器是否是租赁
        StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if (studentRegistration == null) {
            throw new BizException("用户注册信息不存在");
        }
        //更新学员在班级的状态
        classGroupStudentMapperDao.deleteStudentByMusicGroupId(musicGroupId, userId);

        List<Integer> classGroupIdList = classGroupStudentMapperDao.queryClassGroupIdList(musicGroupId, userId, GroupType.MUSIC);
        if (classGroupIdList != null && classGroupIdList.size() > 0) {
            //更新班级人数
            //classGroupDao.batchUpdateStudentNumMinusOne(classGroupIdList);

            //删除融云群
            List<ImGroupModel> imGroupModels = new ArrayList<ImGroupModel>();
            ImGroupMember[] imGroupMember = {new ImGroupMember(userId.toString())};
            for (Integer classGroupId : classGroupIdList) {
                imGroupModels.add(new ImGroupModel(classGroupId + "", imGroupMember, ""));
            }
            imFeignService.groupBatchQuit(imGroupModels);
        }

        List<CourseSchedule> musicGroupCourseSchedules = courseScheduleDao.findMusicGroupCourseSchedulesWithStudent(musicGroupId, GroupType.MUSIC.getCode(), CourseStatusEnum.NOT_START.getCode(), userId);
        if (!CollectionUtils.isEmpty(musicGroupCourseSchedules)) {
            List<Long> courseScheduleIds = musicGroupCourseSchedules.stream().map(courseSchedule -> courseSchedule.getId()).collect(Collectors.toList());

            // 删除未上课
            courseScheduleDao.deleteMusicGroupCourseSchedulesWithStudent(courseScheduleIds, userId);

            // 删除学生缴费表
            courseScheduleStudentPaymentDao.deleteStudentCourseSchedule(userId, musicGroupCourseSchedules);
        }

        //删除续费周期
        musicGroupStudentFeeDao.deleteByUserIdAndMusicGroupId(userId, musicGroupId);

        // 退团
        studentRegistration.setMusicGroupStatus(ClassGroupStudentStatusEnum.QUIT);
        studentRegistration.setUpdateTime(date);

        studentRegistrationDao.update(studentRegistration);

        BigDecimal amount = new BigDecimal(0);

        // 判断乐器是否是租赁
        // MusicGroupSubjectPlan musicGroupSubjectPlan = musicGroupSubjectPlanDao.getMusicOneSubjectClassPlan(musicGroupId, subjectId);

        StudentPaymentOrder studentPaymentOrder = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(userId, musicGroupId, DealStatusEnum.SUCCESS);

        if (studentPaymentOrder == null) {
            return true;
        }

        List<StudentPaymentOrderDetail> orderDetailList = studentPaymentOrderDetailDao.findApplyOrderGoods(studentPaymentOrder.getId());
        BigDecimal remitFee = studentPaymentOrder.getRemitFee() == null ? BigDecimal.ZERO : studentPaymentOrder.getRemitFee();

        for (StudentPaymentOrderDetail detail : orderDetailList) {
            if (remitFee.compareTo(detail.getPrice()) >= 0) {
                remitFee = remitFee.subtract(detail.getPrice());
                detail.setPrice(BigDecimal.ZERO);
            } else {
                detail.setPrice(detail.getPrice().subtract(remitFee));
                remitFee = BigDecimal.ZERO;
            }
            if (isRefundCourseFee) {
                // 退课程费用
                if (detail.getType() == OrderDetailTypeEnum.COURSE) {
                    amount = amount.add(detail.getPrice());
                }
            }
            if (isRefundInstrumentFee) {
                // 退乐器费用
                if (detail.getType() == OrderDetailTypeEnum.MUSICAL) {
                    amount = amount.add(detail.getPrice());
                }

            }
            if (isRefundTeachingAssistantsFee) {
                // 退教辅费用
                if (detail.getType() == OrderDetailTypeEnum.ACCESSORIES || detail.getType() == OrderDetailTypeEnum.TEACHING) {
                    amount = amount.add(detail.getPrice());
                }
            }
        }
        if (amount.doubleValue() > 0) {
            // 增加交易流水
            sysUserCashAccountDetailService.addCashAccountDetail(userId, amount, SysUserCashAccountDetailService.MUSIC_GROUP + musicGroupId, "",
                    PlatformCashAccountDetailTypeEnum.REFUNDS, null, DealStatusEnum.SUCCESS, "退出乐团", null);
        }

        return true;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Map renew(String musicGroupId, Integer userId, boolean isUseBalancePayment) {

        MusicGroup musicGroup = this.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团不存在");
        }

        MusicGroupStudentFee musicGroupStudentFee = musicGroupStudentFeeDao.findByUser(userId, musicGroupId);

        if (musicGroupStudentFee == null) {
            throw new BizException("个人续费信息错误");
        }
        
        StudentRegistration studentRegistration = studentRegistrationService.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if(studentRegistration == null || studentRegistration.getPaymentStatus() != PaymentStatusEnum.YES){
        	throw new BizException("请走报名缴费流程");
        }
        
        //判断是否是续费
		/*List<StudentPaymentOrder> orderList = studentPaymentOrderDao.queryByCondition(GroupType.MUSIC, musicGroupId, userId, DealStatusEnum.SUCCESS);
		if (orderList == null || orderList.size() == 0) {
			throw new BizException("请走报名缴费流程");
		}*/

        // 判断当前是否是续费状态
        if (musicGroupStudentFee.getPaymentStatus() != PaymentStatus.NON_PAYMENT) {
            throw new BizException("已缴费");
        }

        BigDecimal amount = musicGroupStudentFee.getCourseFee();
        if (amount == null || amount.doubleValue() == 0) {
            amount = musicGroupStudentFee.getCourseFee();
        }

        Date date = new Date();
        StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
        studentPaymentOrder.setGroupType(GroupType.MUSIC);
        studentPaymentOrder.setUserId(userId);
        studentPaymentOrder.setOrderNo(idGeneratorService.generatorId("payment") + "");
        studentPaymentOrder.setType(OrderTypeEnum.RENEW);
        studentPaymentOrder.setExpectAmount(amount);
        studentPaymentOrder.setActualAmount(amount);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setMusicGroupId(musicGroupId);
        studentPaymentOrder.setCreateTime(date);
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrder.setVersion(0);
        studentPaymentOrderService.insert(studentPaymentOrder);

        ArrayList<StudentPaymentOrderDetail> studentPaymentOrderDetailList = new ArrayList<>();
        StudentPaymentOrderDetail studentPaymentOrderDetail = new StudentPaymentOrderDetail();
        studentPaymentOrderDetail.setType(OrderDetailTypeEnum.COURSE);
        studentPaymentOrderDetail.setPrice(amount);
        studentPaymentOrderDetail.setCreateTime(date);
        studentPaymentOrderDetail.setUpdateTime(date);
        studentPaymentOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
        studentPaymentOrderDetailList.add(studentPaymentOrderDetail);

        studentPaymentOrderDetailService.batchAdd(studentPaymentOrderDetailList);

        if (isUseBalancePayment || amount.doubleValue() == 0) {
            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(userId);
            if (userCashAccount == null) {
                throw new BizException("用户账户找不到");
            }
            studentPaymentOrder.setPaymentChannel("BALANCE");
            if (userCashAccount.getBalance().subtract(amount).doubleValue() >= 0) {
                // 更新订单信息
                studentPaymentOrder.setBalancePaymentAmount(amount);
                studentPaymentOrder.setStatus(DealStatusEnum.SUCCESS);
                studentPaymentOrder.setUpdateTime(date);
                studentPaymentOrder.setOrganId(musicGroup.getOrganId());
                studentPaymentOrder.setRoutingOrganId(42);
                studentPaymentOrderService.update(studentPaymentOrder);

                sysUserCashAccountService.updateBalance(userId, amount.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "乐团续费");

                //更新下次续费时间
                musicGroupStudentFee.setUpdateTime(date);
                musicGroupStudentFee.setLatestPaidTime(date);
                musicGroupStudentFee.setPaymentStatus(PaymentStatus.PAID_COMPLETED);
                musicGroupStudentFee.setTemporaryCourseFee(new BigDecimal(0));
                musicGroupStudentFee.setNextPaymentDate(musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, musicGroupStudentFee.getNextPaymentDate(), musicGroupStudentFee));
                musicGroupStudentFeeDao.update(musicGroupStudentFee);
                return null;
            } else {
                if (userCashAccount.getBalance().doubleValue() > 0) {
                    sysUserCashAccountService.updateBalance(userId, userCashAccount.getBalance().negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "乐团续费");
                    amount = amount.subtract(userCashAccount.getBalance());
                    studentPaymentOrder.setBalancePaymentAmount(userCashAccount.getBalance());
                } else {
                    studentPaymentOrder.setBalancePaymentAmount(new BigDecimal(0));
                }
            }
        }
        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");

        //分类费用 course，instrument，accessories，other
        Map<String, BigDecimal> classFee = new HashMap<>();
        classFee.put("course", amount);
        classFee.put("instrument", BigDecimal.ZERO);
        classFee.put("accessories", BigDecimal.ZERO);
        classFee.put("other", BigDecimal.ZERO);

        try {

            Map<String, Object> payMap = payService.getPayMap(amount, studentPaymentOrder.getOrderNo(),
                    baseApiUrl + "/api-student/studentOrder/notify",
                    baseApiUrl + "/api-student/studentOrder/paymentResult?orderNo=" + studentPaymentOrder.getOrderNo(),
                    "续费",
                    "乐团续费",
                    userId,
                    classFee,
                    musicGroup.getOrganId()
            );

            Map<String, BigDecimal> routingFee = (Map<String, BigDecimal>) payMap.get("routingFee");
            studentPaymentOrder.setOrganId(musicGroup.getOrganId());
            studentPaymentOrder.setRoutingOrganId(42);
            studentPaymentOrder.setComAmount(routingFee.get("COM"));
            studentPaymentOrder.setPerAmount(routingFee.get("PER"));
            studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
            studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
            studentPaymentOrder.setUpdateTime(date);
            studentPaymentOrderService.update(studentPaymentOrder);

            return payMap;
        } catch (Exception e) {
            throw new BizException("调用支付接口出错", e);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean renewForCallback(StudentPaymentOrder studentPaymentOrder) throws IOException {

        studentPaymentOrderService.update(studentPaymentOrder);

        Integer userId = studentPaymentOrder.getUserId();
        String musicGroupId = studentPaymentOrder.getMusicGroupId();

        //更新下次续费时间
        MusicGroupStudentFee musicGroupStudentFee = musicGroupStudentFeeDao.findByUser(userId, musicGroupId);

        if (musicGroupStudentFee == null) {
            throw new BizException("系统数据异常，找不到学员预缴费信息");
        }
        Date date = new Date();
        StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        Map<Integer, String> yimei = new HashMap<>(1);
        Map<Integer, String> push = new HashMap<>(1);
        push.put(userId, userId.toString());
        yimei.put(userId, studentRegistration.getParentsPhone());
        if (studentPaymentOrder.getStatus() == DealStatusEnum.SUCCESS) {
            musicGroupStudentFee.setUpdateTime(date);
            musicGroupStudentFee.setLatestPaidTime(date);
            musicGroupStudentFee.setPaymentStatus(PaymentStatus.PAID_COMPLETED);
            musicGroupStudentFee.setTemporaryCourseFee(new BigDecimal(0));
            musicGroupStudentFee.setNextPaymentDate(musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, musicGroupStudentFee.getNextPaymentDate(), musicGroupStudentFee));
            musicGroupStudentFeeDao.update(musicGroupStudentFee);

            //插入交易明细
            SysUserCashAccount cashAccount = sysUserCashAccountService.get(userId);
            BigDecimal amount = studentPaymentOrder.getActualAmount();
            //充值
            SysUserCashAccountDetail rechargeDetail = new SysUserCashAccountDetail();
            rechargeDetail.setAmount(amount);
            rechargeDetail.setBalance(cashAccount.getBalance().add(amount));
            rechargeDetail.setComment("缴费前充值");
            rechargeDetail.setCreateTime(date);
            rechargeDetail.setStatus(DealStatusEnum.SUCCESS);
            rechargeDetail.setTransNo(studentPaymentOrder.getTransNo());
            rechargeDetail.setType(PlatformCashAccountDetailTypeEnum.RECHARGE);
            rechargeDetail.setUpdateTime(date);
            rechargeDetail.setUserId(userId);
            rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
            rechargeDetail.setComAmount(studentPaymentOrder.getComAmount());
            rechargeDetail.setPerAmount(studentPaymentOrder.getPerAmount());
            sysUserCashAccountDetailService.insert(rechargeDetail);

            //缴费
            SysUserCashAccountDetail paymentDetail = new SysUserCashAccountDetail();
            paymentDetail.setAmount(amount.negate());
            paymentDetail.setBalance(cashAccount.getBalance());
            paymentDetail.setComment("续费");
            paymentDetail.setCreateTime(date);
            paymentDetail.setStatus(DealStatusEnum.SUCCESS);
            paymentDetail.setTransNo(studentPaymentOrder.getTransNo());
            paymentDetail.setType(PlatformCashAccountDetailTypeEnum.PAY_FEE);
            paymentDetail.setUpdateTime(date);
            paymentDetail.setUserId(userId);
            paymentDetail.setChannel(studentPaymentOrder.getPaymentChannel());
            paymentDetail.setComAmount(studentPaymentOrder.getComAmount().negate());
            paymentDetail.setPerAmount(studentPaymentOrder.getPerAmount().negate());
            sysUserCashAccountDetailService.insert(paymentDetail);
            MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
            if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
                // 发送续费结果通知
                sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.STUDENT_SMS_MUSIC_GROUP_RENEW_SUCCESS, push, null, 0, "1", "STUDENT",
                        studentRegistration.getParentsName(), studentPaymentOrder.getActualAmount());
                sysMessageService.batchSendMessage(MessageSender.YIMEI, MessageTypeEnum.STUDENT_SMS_MUSIC_GROUP_RENEW_SUCCESS, yimei, null, 0, "1", "",
                        studentRegistration.getParentsName(), studentPaymentOrder.getActualAmount());
            }
            return true;
        } else {
            if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().doubleValue() > 0) {
                sysUserCashAccountService.updateBalance(userId, studentPaymentOrder.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS,
                        "乐团续费失败");
            }
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
            if (studentPaymentOrder.getStatus() == DealStatusEnum.CLOSE || studentPaymentOrder.getStatus() == DealStatusEnum.FAILED) {
                String baseUrl = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);
                String memo = baseUrl + "/#/renew?musicGroupId=" + musicGroupId;
                //4?http://mstudev.dayaedu.com/#/renew?musicGroupId=" +musicGroupId
                sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_MUSIC_GROUP_RENEW_FAILED, push, null, 0, "4?" + memo, "STUDENT",
                        HttpUtil.getSortUrl(memo));
                return false;
            }
        }
        return false;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean updateTeacherCoursesSalary(Long courseScheduleId, Integer teacherId, BigDecimal salary, BigDecimal subsidy, String scope) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("获取用户信息失败");
        }
        CourseSchedule courseSchedule = courseScheduleDao.get(courseScheduleId);
        if (courseSchedule == null) {
            throw new BizException("课程信息不存在");
        }

        if ("all".equals(scope)) {
            Integer classGrpupId = courseSchedule.getClassGroupId();
            String startDateTime = sdf_ymd.format(courseSchedule.getClassDate()) + " " + sdf_hms.format(courseSchedule.getStartClassTime());
            // 未结算的课酬都修改
            courseScheduleTeacherSalaryDao.batchUpdateWages(classGrpupId, teacherId, salary, subsidy, startDateTime);
        } else {
            CourseScheduleTeacherSalary courseScheduleTeacherSalary = courseScheduleTeacherSalaryDao.queryByCourseScheduleIdAndUserId(courseScheduleId,
                    teacherId);
            if (courseScheduleTeacherSalary == null) {
                throw new BizException("课程结算信息不存在");
            }
            // 判断当前课程是否结算
            if (courseScheduleTeacherSalary.getSettlementTime() != null) {
                throw new BizException("课程已结算");
            }
            courseScheduleTeacherSalary.setExpectSalary(salary);
            courseScheduleTeacherSalary.setSubsidy(subsidy);
            courseScheduleTeacherSalary.setUpdateTime(new Date());
            courseScheduleTeacherSalaryDao.update(courseScheduleTeacherSalary);
        }
        Teacher teacher = teacherDao.get(teacherId);
        MusicGroup musicGroup = musicGroupDao.get(classGroupDao.findByCourseSchedule(courseScheduleId.intValue()).getMusicGroupId());
        Set<Integer> roleIds = new HashSet<>(1);
        roleIds.add(SysUserRole.SECTION_MANAGER);

        sysMessageService.batchSeoMessage(musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId()), MessageTypeEnum.BACKSTAGE_TEACHER_AMOUNT_CHANGE, "",
                teacher.getRealName(), musicGroup.getName(), scope.equals("all") ? "所有" : "本次");
        return true;
    }

    @Override
    public PageInfo<MusicGroup> queryMusicGroupPage(MusicGroupQueryInfo queryInfo) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("获取用户信息失败");
        }
        //获取用户权限列表
        List<Integer> roles = employeeDao.queryUserRole(sysUser.getId());
        PageInfo<MusicGroup> musicGroupPageInfo;
        if (roles != null && roles.size() == 1 && roles.contains(SysUserRole.EDUCATIONAL_TEACHER)) {
            //只有教务老师权限
            /*String musicGroupIds = musicGroupDao.queryEducationalMusicGroupId(sysUser.getId());
            queryInfo.setMusicGroupId(musicGroupIds);*/
            musicGroupPageInfo = queryPage(queryInfo);
        } else {
            musicGroupPageInfo = queryPage(queryInfo);
        }
        List<MusicGroup> musicGroupList = musicGroupPageInfo.getRows();
        // 获取学校编号列表
//        Set<Integer> schoolIds = musicGroupList.stream().map(e -> e.getSchoolId()).collect(Collectors.toSet());
//        List<Map<Integer, String>> schoolNames = schoolDao.queryNameByIds(StringUtils.join(schoolIds,","));
        // 获取相关学校名称map
//        Map<Integer, String> schoolNameMap = MapUtil.convertMybatisMap(schoolNames);

        // 获取教务老师编号列表
        Set<Integer> educationalTeacherIds = musicGroupList.stream().map(e -> e.getEducationalTeacherId()).collect(Collectors.toSet());
        // 获取相关老师的名字
        List<Map<Integer, String>> educationalTeacherNames = teacherDao.queryNameByIds(StringUtils.join(educationalTeacherIds, ","));
        Map<Integer, String> educationalTeacherNameMap = MapUtil.convertMybatisMap(educationalTeacherNames);

        // 获取运营主管编号列表
        Set<Integer> teamTeacherIds = musicGroupList.stream().map(e -> e.getTeamTeacherId()).collect(Collectors.toSet());
        List<Map<Integer, String>> teamTeacherNames = teacherDao.queryNameByIds(StringUtils.join(teamTeacherIds, ","));
        Map<Integer, String> teamTeacherNameMap = MapUtil.convertMybatisMap(teamTeacherNames);

        // 获取乐团编号列表
        Set<String> musicGroupIds = musicGroupList.stream().map(e -> e.getId()).collect(Collectors.toSet());
        // 统计乐团在读人数
//        List<Map<String, Long>> payNums = musicGroupDao.countPayNum(StringUtils.join(musicGroupIds,","));
//        Map<String, String> payNumMap = MapUtil.convertMybatisMap(payNums);

        Map<String, Integer> payNumMap = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertIntegerMap(studentRegistrationDao.countNormalNum(StringUtils.join(musicGroupIds, ",")))), HashMap.class);

        // 获取收费类型编号列表
        Set<Integer> chargeTypeIds = musicGroupList.stream().map(e -> e.getChargeTypeId()).collect(Collectors.toSet());
        if (chargeTypeIds == null) {
            chargeTypeIds = new HashSet<>();
        }
        List<Map<Integer, String>> chargeTypeNames = chargeTypeDao.queryNameByIds(StringUtils.join(chargeTypeIds, ","));
        Map<Integer, String> chargeTypeNameMap = MapUtil.convertMybatisMap(chargeTypeNames);

        //获取教学点编号
        Map<Integer, String> cooperationOrganNames = MapUtil.convertMybatisMap(cooperationOrganDao.queryNameByIds(StringUtils.join(musicGroupList.stream().map(MusicGroup::getCooperationOrganId).collect(Collectors.toSet()), ",")));

//        Set<Integer> organIds = musicGroupList.stream().map(e -> e.getOrganId()).collect(Collectors.toSet());
//        Map<Integer,String> organNames = MapUtil.convertMybatisMap(organizationDao.findOrganNameMap(StringUtils.join(organIds,",")));

        //获取分部名称map
        musicGroupList.forEach(e -> {
//            e.setSchoolName(schoolNameMap.get(e.getSchoolId()));
//            e.setOrganName(organNames.get(e.getOrganId()));
            e.setCooperationOrganName(cooperationOrganNames.get(e.getCooperationOrganId()));
            e.setEducationalTeacherName(educationalTeacherNameMap.get(e.getEducationalTeacherId()));
            e.setTeamTeacherName(teamTeacherNameMap.get(e.getTeamTeacherId()));
            e.setPayNum(payNumMap.get(e.getId()) == null ? 0 : payNumMap.get(e.getId()));
            e.setChargeTypeName(chargeTypeNameMap.get(e.getChargeTypeId()));
        });
        return musicGroupPageInfo;
    }

    private void updateTeamTeacher(MusicGroup oldMusicGroup, MusicGroup newMusicGroup) {
        //获取当前乐团所有班级
        List<ClassGroup> classGroups = classGroupDao.findClassGroups(newMusicGroup.getId());
        if (classGroups == null || classGroups.size() == 0) {
            return;
        }
        Integer teamTeacherId = newMusicGroup.getTeamTeacherId();
        Integer educationalTeacherId = newMusicGroup.getEducationalTeacherId();

        ImGroupMember[] oldImGroupMembers1 = {new ImGroupMember(oldMusicGroup.getTeamTeacherId().toString())};
        ImGroupMember[] nowImGroupMembers1 = {new ImGroupMember(teamTeacherId.toString())};
        ImGroupMember[] oldImGroupMembers2 = {new ImGroupMember(oldMusicGroup.getEducationalTeacherId().toString())};
        ImGroupMember[] nowImGroupMembers2 = {new ImGroupMember(educationalTeacherId.toString())};

        Integer oldDirectorUserId = oldMusicGroup.getDirectorUserId();
        if(oldDirectorUserId == null){
            oldDirectorUserId = teamTeacherId;
        }
        Integer directorUserId = newMusicGroup.getDirectorUserId();
        if(directorUserId == null){
            directorUserId = teamTeacherId;
        }

        ImGroupMember[] oldImGroupMembers3 = {new ImGroupMember(oldDirectorUserId.toString())};
        ImGroupMember[] nowImGroupMembers3 = {new ImGroupMember(directorUserId.toString())};
        classGroups.forEach(e -> {
            imFeignService.groupQuit(new ImGroupModel(e.getId().toString(), oldImGroupMembers3, e.getName()));
            imFeignService.groupJoin(new ImGroupModel(e.getId().toString(), nowImGroupMembers3, e.getName()));
            imFeignService.groupQuit(new ImGroupModel(e.getId().toString(), oldImGroupMembers2, e.getName()));
            imFeignService.groupJoin(new ImGroupModel(e.getId().toString(), nowImGroupMembers2, e.getName()));
            imFeignService.groupQuit(new ImGroupModel(e.getId().toString(), oldImGroupMembers1, e.getName()));
            imFeignService.groupJoin(new ImGroupModel(e.getId().toString(), nowImGroupMembers1, e.getName()));
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBaseInfo(SubFeeSettingDto subFeeSettingDto) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        String musicGroupId = subFeeSettingDto.getMusicGroup().getId();
        MusicGroup group = musicGroupDao.get(musicGroupId);
        MusicGroup musicGroup = subFeeSettingDto.getMusicGroup();
        if (group == null) {
            throw new BizException("乐团信息不存在");
        } else if (group.getSchoolId() != musicGroup.getSchoolId()) {
            //如果已生成课表，那么修改未上课时教学点
            courseScheduleDao.updateCourseScheduleSchool("MUSIC", musicGroupId, musicGroup.getSchoolId());
        }
        updateTeamTeacher(group,musicGroup);
        List<Integer> months = subFeeSettingDto.getMonths();

        Date date = new Date();

        //判断缴费日历是否修改
        boolean isModifiedOfCalender = false;

        List<MusicGroupPaymentCalender> calenderList = musicGroupPaymentCalenderDao.findByMusicGroupId(musicGroupId);
        if (months.size() == calenderList.size()) {
            for (MusicGroupPaymentCalender cal : calenderList) {
                if (!months.contains(cal.getPaymentMonth())) {
                    isModifiedOfCalender = true;
                    break;
                }
            }
        } else {
            isModifiedOfCalender = true;
        }

        if (isModifiedOfCalender) {
            Integer num = musicGroupStudentFeeDao.countStudentNoPayNum(musicGroupId);
            if (num > 0) {
                throw new BizException("缴费周期更新失败，当前乐团有未缴费的学员");
            }

            // 删除乐团相关付费周期
            musicGroupPaymentCalenderDao.delByGroupId(musicGroupId);
            if (months != null && months.size() > 0) {
                // 批量插入
                musicGroupPaymentCalenderDao.batchAdd(months, musicGroupId);
            }
        }
        if (musicGroup.getStatus() == MusicGroupStatusEnum.PROGRESS) {
            //修改未锁定学员缴费周期
            String join = null;
            if (months != null && months.size() > 0) {
                join = StringUtils.join(months, ",");
            }
            musicGroupStudentFeeDao.batchUpdateCalender(join, musicGroupId);
            List<MusicGroupStudentFee> fees = musicGroupStudentFeeDao.queryByMusicGroupId(musicGroupId);
            fees.forEach(e -> {
                e.setNextPaymentDate(musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, null, e));
                e.setUpdateTime(date);
            });
            musicGroupStudentFeeDao.batchUpdate(fees);
        }
        musicGroup.setUpdateTime(date);
        musicGroupDao.update(musicGroup);
        //修改课程里面的教学点
        if (!musicGroup.getSchoolId().equals(musicGroup.getSchoolId())) {
            courseScheduleDao.updateByMusicGroupId(musicGroupId, musicGroup.getSchoolId());
        }
        // 删除乐团付费主体列表
        musicGroupPaymentEntitiesDao.delByGroupId(musicGroupId);
        //批量新增
        if (subFeeSettingDto.getMusicGroupPaymentEntities() != null && subFeeSettingDto.getMusicGroupPaymentEntities().size() > 0) {
            musicGroupPaymentEntitiesDao.batchAdd(subFeeSettingDto.getMusicGroupPaymentEntities(), musicGroupId);
        }
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "修改乐团基本信息数据", sysUser.getId(), JSONObject.toJSONString(subFeeSettingDto)));
    }

    @Override
    public SubFeeSettingDto findMusicGroupBasicInfo(String musicGroupId) {
        SubFeeSettingDto subFeeSettingDto = new SubFeeSettingDto();
        //获取乐团信息
        subFeeSettingDto.setMusicGroup(musicGroupDao.get(musicGroupId));
        //获取付费主体
        subFeeSettingDto.setMusicGroupPaymentEntities(musicGroupPaymentEntitiesDao.findByMusicGroupId(musicGroupId));
        //获取缴费周期
        List<Integer> paymentMonth = musicGroupPaymentCalenderDao.findByMusicGroupId(musicGroupId).stream().map(e -> e.getPaymentMonth()).collect(Collectors.toList());
        subFeeSettingDto.setMonths(paymentMonth);
        return subFeeSettingDto;
    }

    @Override
    public SubFeeSettingDto findMusicGroupSubjectInfo(String musicGroupId) {
        SubFeeSettingDto subFeeSettingDto = new SubFeeSettingDto();
        //获取乐团声部规划列表
        subFeeSettingDto.setMusicGroupSubjectPlans(musicGroupSubjectPlanDao.getMusicSubjectClassPlan(musicGroupId));
        //获取乐团声部商品组
        subFeeSettingDto.setMusicGroupSubjectGoodsGroups(musicGroupSubjectGoodsGroupDao.findGoodsGroup(musicGroupId, null));
        return subFeeSettingDto;
    }

    @Override
    public List<MusicGroup> queryListByIds(Set<String> musicGroupIds) {
        return musicGroupDao.queryListByIds(StringUtils.join(musicGroupIds, ","));
    }

    @Override
    public List<CourseScheduleTeachersDto> queryTeacherSalary(Long courseScheduleId) {
        return courseScheduleTeacherSalaryDao.queryTeacherSalary(courseScheduleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MusicGroup openPay(String musicGroupId, String expireDate) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = saveLog(musicGroupId, MusicGroupStatusEnum.APPLY);
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "开启缴费（报名中 -->  缴费中）", sysUser.getId(), ""));
        musicGroup.setPaymentExpireDate(DateUtil.toDate(expireDate));
        musicGroup.setStatus(MusicGroupStatusEnum.PAY);
        musicGroupDao.update(musicGroup);
        //三方乐团不发送缴费通知
        if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
            //获取所有已报名学员列表
            HashMap<Integer, String> map = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertMybatisMap(studentRegistrationDao.findMapByMusicGroupId(musicGroupId, 0))), HashMap.class);
            if (map != null && map.size() > 0) {
                String studentApplyUrl = sysConfigDao.findConfigValue(SysConfigService.STUDENT_APPLY_URL) + musicGroupId;
                String serverPhone = sysConfigDao.findConfigValue(SysConfigService.SERVER_PHONE);
                sysMessageService.batchSendMessage(MessageSender.YIMEI, MessageTypeEnum.SMS_PAYMENT_MESSAGE,
                        map, null, 0, "", "", musicGroup.getName(), studentApplyUrl, DateUtil.format(musicGroup.getPaymentExpireDate(), DateUtil.DATE_FORMAT_MIN), serverPhone);
            }
        }
        Set<Integer> roleIds = new HashSet<>(3);
        roleIds.add(SysUserRole.SECTION_MANAGER);
        roleIds.add(SysUserRole.EDUCATIONAL_TEACHER);
        roleIds.add(SysUserRole.OPERATION_EXECUTIVE);
        sysMessageService.batchSeoMessage(musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId()), MessageTypeEnum.BACKSTAGE_ACTION_PAYMENT, "", musicGroup.getName());
        //所有人开启缴费
        studentRegistrationDao.musicGroupOpenPay(musicGroupId, PaymentStatusEnum.OPEN);
        return musicGroup;
    }

    @Override
    public MusicGroup getMusicGroupDetail(String musicGroupId) {
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        musicGroup.setEducationalTeacherName(teacherDao.queryNameById(musicGroup.getEducationalTeacherId()));
        musicGroup.setTeamTeacherName(teacherDao.queryNameById(musicGroup.getTeamTeacherId()));
        musicGroup.setDirectorUserName(teacherDao.queryNameById(musicGroup.getDirectorUserId()));
        Organization organization = organizationDao.get(musicGroup.getOrganId());
        if (organization != null) {
            musicGroup.setOrganName(organization.getName());
        }
        School school = schoolDao.get(musicGroup.getSchoolId());
        if (school != null) {
            musicGroup.setSchoolName(school.getName());
            musicGroup.setAddress(school.getAddress());
        }
        ChargeType chargeType = chargeTypeDao.get(musicGroup.getChargeTypeId());
        if (chargeType != null) {
            musicGroup.setChargeTypeName(chargeType.getName());
        }
        int highClassGroupNum = studentRegistrationDao.findMusicGroupStudentNum(musicGroupId) / 5;
        musicGroup.setImproventClassesNum(highClassGroupNum);
        return musicGroup;
    }

    @Override
    public List<ImGroupMember> queryMusicGroupTeachers(String musicGroupId) {
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        List<ImGroupMember> groupMembers = new ArrayList<>();
        Set teacherIds = new HashSet(4);
        teacherIds.add(musicGroup.getEducationalTeacherId());
        teacherIds.add(musicGroup.getTeamTeacherId());
        teacherIds.add(musicGroup.getOperatorUserId());
        teacherIds.add(musicGroup.getDirectorUserId());
        teacherIds.removeAll(Collections.singleton(null));
        for (Object teacherId : teacherIds) {
            groupMembers.add(new ImGroupMember(teacherId.toString()));
        }
        return groupMembers;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void musicGroupFound(String musicGroupId) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团信息不存在");
        }
        //记录操作日志
        String event;
        if (musicGroup.getStatus() == MusicGroupStatusEnum.APPLY) {
            event = "确认开团(报名中 -> 筹备中)";
        } else if (musicGroup.getStatus() == MusicGroupStatusEnum.PAY) {
            event = "确认开团(缴费中 -> 筹备中)";
        } else {
            throw new BizException("当前乐团状态不支持此操作");
        }
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, event, sysUser.getId(), ""));
        musicGroup.setStatus(MusicGroupStatusEnum.PREPARE);
        musicGroupDao.update(musicGroup);
        if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
            //给家长发送乐团基础训练课短信
            //获取所有乐团学员列表
            List<StudentRegistration> students = studentRegistrationDao.queryStudentByMusicGroupId(musicGroupId);
            if (students != null && students.size() > 0) {
                // 获取所有家长电话
                Set<String> parentsPhones = students.stream().map(StudentRegistration::getParentsPhone).collect(Collectors.toSet());
                // 获取对应家长的用户编号
                Map<Integer, String> userIds = MapUtil.convertMybatisMap(studentRegistrationDao.findParentId(StringUtils.join(parentsPhones, ",")));
                userIds = JSONObject.parseObject(JSONObject.toJSONString(userIds), HashMap.class);
                if (userIds != null && userIds.size() > 0) {
                    String studentApplyUrl = sysConfigDao.findConfigValue(SysConfigService.STUDENT_APPLY_URL) + musicGroupId;
                    String serverPhone = sysConfigDao.findConfigValue(SysConfigService.SERVER_PHONE);
                    sysMessageService.batchSendMessage(MessageSender.YIMEI, MessageTypeEnum.SMS_BASICS_SKILL_APPLY_MESSAGE, userIds, null, 0, "", "", musicGroup.getName(), studentApplyUrl, serverPhone);
                }
            }
        }
        Set<Integer> roleIds = new HashSet<>(1);
        roleIds.add(SysUserRole.SECTION_MANAGER);
        sysMessageService.batchSeoMessage(musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId()), MessageTypeEnum.BACKSTAGE_MUSIC_GROUP_MARKING, "", musicGroup.getName());
    }
}
