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

import com.alibaba.fastjson.JSON;
import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.biz.dal.dto.MusicGroupPaymentCalenderDto.MusicGroupPaymentDateRange;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PayUserType;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentCalenderStatusEnum;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentType;
import com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.dal.page.BaseOrganQueryInfo;
import com.ym.mec.biz.dal.page.MusicGroupPaymentCalenderQueryInfo;
import com.ym.mec.biz.event.source.GroupEventSource;
import com.ym.mec.biz.event.source.SendSeoMessageSource;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.controller.BaseController;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.entity.HttpResponseResult;
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.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.ui.ModelMap;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PayUserType.SCHOOL;
import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PayUserType.STUDENT;
import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentCalenderStatusEnum.*;
import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentType.*;
import static com.ym.mec.biz.dal.enums.PaymentStatusEnum.YES;
import static com.ym.mec.biz.dal.enums.SysUserRoleEnum.ORGAN_MANAGER;

@Service
public class MusicGroupPaymentCalenderServiceImpl extends BaseServiceImpl<Long, MusicGroupPaymentCalender> implements MusicGroupPaymentCalenderService {

    @Autowired
    private MusicGroupPaymentCalenderDao musicGroupPaymentCalenderDao;
    @Autowired
    private MusicGroupPaymentCalenderDetailDao musicGroupPaymentCalenderDetailDao;
    @Autowired
    private MusicGroupStudentFeeDao musicGroupStudentFeeDao;
    @Autowired
    private MusicGroupPaymentCalenderCourseSettingsServiceImpl musicGroupPaymentCalenderCourseSettingsService;
    @Autowired
    private MusicGroupPaymentStudentCourseDetailDao musicGroupPaymentStudentCourseDetailDao;
    @Autowired
    private MusicGroupSchoolTermCourseDetailDao musicGroupSchoolTermCourseDetailDao;
    @Autowired
    private MusicGroupSchoolTermStudentCourseDetailDao musicGroupSchoolTermStudentCourseDetailDao;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private ClassGroupService classGroupService;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private CourseScheduleDao courseScheduleDao;
    @Autowired
    private MusicGroupBuildLogDao musicGroupBuildLogDao;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private OrganizationDao organizationDao;
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private SendSeoMessageSource sendSeoMessageSource;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private ImUserFriendService imUserFriendService;
    @Autowired
    private MusicGroupStudentClassAdjustDao musicGroupStudentClassAdjustDao;
    @Autowired
    private MusicGroupPaymentCalenderDetailService musicGroupPaymentCalenderDetailService;
    @Autowired
    private MusicGroupPaymentCalenderStudentDetailDao musicGroupPaymentCalenderStudentDetailDao;
    @Autowired
    private StudentRegistrationDao studentRegistrationDao;
    @Autowired
    private GroupEventSource groupEventSource;
    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;
    @Autowired
    private MemberRankPrivilegesService memberRankPrivilegesService;
    @Autowired
    private CloudTeacherOrderService cloudTeacherOrderService;
    @Autowired
    private MusicGroupPaymentCalenderActivityServiceImpl musicGroupPaymentCalenderActivityService;
    @Autowired
    private MusicGroupPaymentCalenderMemberServiceImpl musicGroupPaymentCalenderMemberService;
    @Autowired
    private MusicGroupPaymentCalenderRepairServiceImpl musicGroupPaymentCalenderRepairService;
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private ActivityUserMapperService activityUserMapperService;
    @Autowired
    private StudentRegistrationService studentRegistrationService;
    @Autowired
    private VipGroupActivityDao vipGroupActivityDao;

    @Override
    public BaseDAO<Long, MusicGroupPaymentCalender> getDAO() {
        return musicGroupPaymentCalenderDao;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String create(MusicGroupPaymentCalenderDto musicGroupPaymentCalenderDto) {
        PaymentType paymentType = musicGroupPaymentCalenderDto.getPaymentType();
        if (paymentType != SPAN_GROUP_CLASS_ADJUST) {
            throw new BizException("操作失败：该入口不支持{}", paymentType.getDesc());
        }
        List<MusicGroupPaymentDateRange> musicGroupPaymentDateRangeList = musicGroupPaymentCalenderDto.getMusicGroupPaymentDateRangeList();
        if (musicGroupPaymentDateRangeList.size() > 1) {
            throw new BizException("创建缴费失败：不支持多周期缴费");
        }
        String musicGroupId = musicGroupPaymentCalenderDto.getMusicGroupId();
        MusicGroup musicGroup = musicGroupDao.getLocked(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团查询失败，请检查参数");
        }
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("请登录");
        }
        // 所有缴费项目已完成排课才能创建下一个缴费项目
        /*String organBatchNo = musicGroupPaymentStudentCourseDetailDao.getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(musicGroupId, null, null, musicGroupPaymentCalenderDto.getIgnoreBatchNoList());
        if (StringUtils.isNoneBlank(organBatchNo)) {
            if (StringUtils.isEmpty(musicGroupPaymentCalenderDto.getBatchNo()) || !musicGroupPaymentCalenderDto.getBatchNo().equals(organBatchNo)) {
                throw new BizException("当前乐团存在未排课的缴费项目，请先完成排课再操作");
            }
        }*/

        List<MusicGroupPaymentCalenderStudentDetail> calenderStudentDetails = musicGroupPaymentCalenderDto.getMusicGroupPaymentCalenderStudentDetails();

        PaymentCalenderStatusEnum status = musicGroupPaymentCalenderDto.getStatus();

        Date date = new Date();
        String batchNo = idGeneratorService.generatorId() + "";

        MusicGroupPaymentDateRange musicGroupPaymentDateRange = musicGroupPaymentDateRangeList.get(0);
        MusicGroupPaymentCalender musicGroupPaymentCalender = new MusicGroupPaymentCalender();
        musicGroupPaymentCalender.setAttribute1(musicGroupPaymentCalenderDto.getAttribute1());
        musicGroupPaymentCalender.setAttribute2(musicGroupPaymentCalenderDto.getAttribute2());
        musicGroupPaymentCalender.setDeadlinePaymentDate(musicGroupPaymentDateRange.getDeadlinePaymentDate());
        musicGroupPaymentCalender.setMemo(musicGroupPaymentCalenderDto.getMemo());
        musicGroupPaymentCalender.setMusicGroupId(musicGroupId);
        musicGroupPaymentCalender.setMusicGroupOrganizationCourseSettingId(musicGroupPaymentCalenderDto.getMusicGroupOrganizationCourseSettingId());

        musicGroupPaymentCalender.setOriginalTotalAmount(calenderStudentDetails.stream().map(e -> e.getCourseOriginalPrice()).reduce(BigDecimal.ZERO, BigDecimal::add));
        musicGroupPaymentCalender.setCurrentTotalAmount(calenderStudentDetails.stream().map(e -> e.getCourseCurrentPrice()).reduce(BigDecimal.ZERO, BigDecimal::add));
        musicGroupPaymentCalender.setPaymentType(paymentType);
        musicGroupPaymentCalender.setPayUserType(musicGroupPaymentCalenderDto.getPayUserType());
        musicGroupPaymentCalender.setStartPaymentDate(musicGroupPaymentDateRange.getStartPaymentDate());
        musicGroupPaymentCalender.setStudentIds(musicGroupPaymentCalenderDto.getStudentIds());
        musicGroupPaymentCalender.setOperator(sysUser.getId());
        musicGroupPaymentCalender.setCreateTime(date);
        musicGroupPaymentCalender.setUpdateTime(date);
        musicGroupPaymentCalender.setStatus(status);
        musicGroupPaymentCalender.setOrganId(musicGroup.getOrganId());
        if (musicGroupPaymentCalender.getStatus() != AUDITING) {
            if (date.after(musicGroupPaymentCalender.getStartPaymentDate())) {
                musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.OPEN);
            } else if (date.after(musicGroupPaymentCalender.getDeadlinePaymentDate())) {
                musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.OVER);
            } else {
                musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.NO);
            }
        }
        // 设置批次号
        musicGroupPaymentCalender.setBatchNo(batchNo);
        musicGroupPaymentCalenderDto.setBatchNo(batchNo);
        musicGroupPaymentCalenderDao.insert(musicGroupPaymentCalender);
        //如果是跨团班级合并,保存用户缴费详情
        //记录学员缴费详情
        musicGroupPaymentCalenderStudentDetailDao.batchInsert(musicGroupPaymentCalenderDto.getMusicGroupPaymentCalenderStudentDetails(), musicGroupPaymentCalender.getBatchNo());
        if (musicGroupPaymentCalender.getStatus() != AUDITING) {
            //如果是跨团班级合并,添加学员
            musicGroupPaymentCalenderDetailService.batchAdd(musicGroupPaymentCalender, musicGroupPaymentCalenderDto.getMusicGroupPaymentCalenderStudentDetails());
            //将0元未缴费学员缴费状态更新为已缴费
            this.updateNoPaymentAndZeroPaymentStatus(musicGroupPaymentCalender, true);
        }
        if (status == AUDITING) {
            // 如果是审核中
            Organization organization = organizationDao.get(musicGroup.getOrganId());
            sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                    null, null, MessageTypeEnum.BACKSTAGE_PAYMENT_CALENDER_AUDIT, organization.getName(), musicGroup.getName());
        } else {
            imUserFriendService.refreshGroupImUserFriend(musicGroupId, GroupType.MUSIC);
        }
        return batchNo;
    }

    public <T> void checkObjectNull(T t, Consumer consumer) {
        if (t == null) {
            consumer.accept(null);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult<ModelMap> create1(MusicGroupPaymentBaseCalender musicGroupPaymentBaseCalender) {
        checkObjectNull(musicGroupPaymentBaseCalender, o -> {
            throw new BizException("参数校验异常");
        });
        String musicGroupId = musicGroupPaymentBaseCalender.getMusicGroupId();
        MusicGroup musicGroup = musicGroupDao.getLocked(musicGroupId);
        checkObjectNull(musicGroup, o -> {
            throw new BizException("乐团查询失败，请检查参数");
        });

        SysUser sysUser = sysUserFeignService.queryUserInfo();
        checkObjectNull(sysUser, o -> {
            throw new BizException("请登录");
        });

        if (musicGroup.getStatus() != MusicGroupStatusEnum.PROGRESS && musicGroup.getStatus() != MusicGroupStatusEnum.PRE_BUILD_FEE) {
            throw new BizException("创建缴费失败：已存在缴费项目");
        }
        // 所有缴费项目已完成排课才能创建下一个缴费项目
        String orignBatchNo = musicGroupPaymentStudentCourseDetailDao.getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(musicGroupId, null, null, null);
        if (!musicGroupPaymentBaseCalender.getConfirmCreate() && StringUtils.isNoneBlank(orignBatchNo)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return BaseController.failed(HttpStatus.MULTI_STATUS,"当前乐团存在未排课的缴费项目，请再次确认操作");
        }

        // 不是进行中，只能创建一次缴费
        if (musicGroup.getStatus() != MusicGroupStatusEnum.PROGRESS) {
            List<MusicGroupPaymentCalender> list = musicGroupPaymentCalenderDao.findByMusicGroupId(musicGroupId);
            if (list.size() > 0) {
                throw new BizException("创建失败，已经存在缴费信息");
            }
        }
        //进行中加学员拓展信息
        CalenderAddStudent calenderAddStudent = musicGroupPaymentBaseCalender.getCalenderAddStudent();
        MusicGroupPaymentCalender musicGroupPaymentCalender = new MusicGroupPaymentCalender();
        //判断缴费项目类型
        if (musicGroup.getStatus() == MusicGroupStatusEnum.PRE_BUILD_FEE) {
            musicGroupPaymentBaseCalender.setPaymentType(MUSIC_APPLY);
        } else {
            if (calenderAddStudent != null && calenderAddStudent.getStudentIds() != null) {
                musicGroupPaymentBaseCalender.setPaymentType(ADD_STUDENT);
                //预计缴费人数
                musicGroupPaymentCalender.setAttribute1(calenderAddStudent.getClassGroupIds());
                musicGroupPaymentCalender.setStudentIds(calenderAddStudent.getStudentIds().toString());
                musicGroupPaymentCalender.setExpectNum(1);
                //校验是否可以加学员
                checkAddStudent(calenderAddStudent, musicGroup);
            } else {
                if (musicGroupPaymentBaseCalender.getMusicGroupOrganizationCourseSettingId() != null) {
                    musicGroupPaymentBaseCalender.setPaymentType(MUSIC_RENEW);
                } else {
                    musicGroupPaymentBaseCalender.setPaymentType(ADD_COURSE);
                }
            }
        }
        musicGroupPaymentBaseCalender.setMusicGroup(musicGroup);

        //计算缴费项目原价
        BigDecimal courseOriginalAmount = musicGroupPaymentCalenderCourseSettingsService.getOriginalAmount(musicGroupPaymentBaseCalender);
        BigDecimal memberOriginalAmount = musicGroupPaymentCalenderMemberService.getOriginalAmount(musicGroupPaymentBaseCalender);
        BigDecimal repairOriginalAmount = musicGroupPaymentCalenderRepairService.getOriginalAmount(musicGroupPaymentBaseCalender);
        BigDecimal activityOriginalAmount = musicGroupPaymentCalenderActivityService.getOriginalAmount(musicGroupPaymentBaseCalender);

        BigDecimal originalTotalAmount = courseOriginalAmount.add(memberOriginalAmount)
                .add(activityOriginalAmount)
                .add(repairOriginalAmount).setScale(0, BigDecimal.ROUND_HALF_UP);

        //计算缴费项目总金额(前端录入)
        BigDecimal courseActualAmount = musicGroupPaymentCalenderCourseSettingsService.getActualAmount(musicGroupPaymentBaseCalender);
        BigDecimal memberActualAmount = musicGroupPaymentCalenderMemberService.getActualAmount(musicGroupPaymentBaseCalender);
        BigDecimal repairActualAmount = musicGroupPaymentCalenderRepairService.getActualAmount(musicGroupPaymentBaseCalender);
        BigDecimal activityActualAmount = musicGroupPaymentCalenderActivityService.getActualAmount(musicGroupPaymentBaseCalender);

        BigDecimal actualTotalAmount = courseActualAmount.add(memberActualAmount)
                .add(repairActualAmount)
                .add(activityActualAmount).setScale(0, BigDecimal.ROUND_HALF_UP);

        PaymentCalenderStatusEnum status;
        if (musicGroupPaymentBaseCalender.getPayUserType() == SCHOOL) {
            status = AUDITING;
        } else {
            //计算项目原现价
            BigDecimal courseCurrentAmount = musicGroupPaymentCalenderCourseSettingsService.getCurrentAmount(musicGroupPaymentBaseCalender);
            //如果课程价格是0元，那么需要审核
            if(courseCurrentAmount.compareTo(BigDecimal.ZERO) == 0 &&
                    musicGroupPaymentBaseCalender.getMusicGroupPaymentCalenderCourseSettingsList() != null &&
                    musicGroupPaymentBaseCalender.getMusicGroupPaymentCalenderCourseSettingsList().size() > 0){
                status = AUDITING;
            }else {
                BigDecimal memberCurrentAmount = musicGroupPaymentCalenderMemberService.getCurrentAmount(musicGroupPaymentBaseCalender);
                BigDecimal repairCurrentAmount = musicGroupPaymentCalenderRepairService.getCurrentAmount(musicGroupPaymentBaseCalender);
                BigDecimal activityCurrentAmount = musicGroupPaymentCalenderActivityService.getCurrentAmount(musicGroupPaymentBaseCalender);
                BigDecimal currentTotalAmount = courseCurrentAmount.add(memberCurrentAmount)
                        .add(repairCurrentAmount)
                        .add(activityCurrentAmount).setScale(0, BigDecimal.ROUND_HALF_UP);
                status = actualTotalAmount.compareTo(currentTotalAmount) == 0 ? NO : AUDITING;
            }
        }

        Date date = new Date();

        musicGroupPaymentCalender.setDeadlinePaymentDate(musicGroupPaymentBaseCalender.getDeadlinePaymentDate());
        musicGroupPaymentCalender.setMemo(musicGroupPaymentBaseCalender.getMemo());
        musicGroupPaymentCalender.setMusicGroupId(musicGroupId);
        musicGroupPaymentCalender.setMusicGroupOrganizationCourseSettingId(musicGroupPaymentBaseCalender.getMusicGroupOrganizationCourseSettingId());
        musicGroupPaymentCalender.setPayUserType(musicGroupPaymentBaseCalender.getPayUserType());
        musicGroupPaymentCalender.setStartPaymentDate(musicGroupPaymentBaseCalender.getStartPaymentDate());
        musicGroupPaymentCalender.setOperator(sysUser.getId());
        musicGroupPaymentCalender.setCreateTime(date);
        musicGroupPaymentCalender.setUpdateTime(date);
        musicGroupPaymentCalender.setPaymentType(musicGroupPaymentBaseCalender.getPaymentType());
        musicGroupPaymentCalender.setCurrentTotalAmount(actualTotalAmount);
        musicGroupPaymentCalender.setOriginalTotalAmount(originalTotalAmount);
        musicGroupPaymentCalender.setStatus(status);
        musicGroupPaymentCalender.setOrganId(musicGroup.getOrganId());

        if (musicGroupPaymentCalender.getStatus() != AUDITING) {
            if (date.after(musicGroupPaymentCalender.getStartPaymentDate())) {
                musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.OPEN);
            } else if (date.after(musicGroupPaymentCalender.getDeadlinePaymentDate())) {
                musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.OVER);
            } else {
                musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.NO);
            }
        }

        // 设置批次号
        String batchNo = idGeneratorService.generatorId() + "";
        musicGroupPaymentCalender.setBatchNo(batchNo);
        musicGroupPaymentCalenderDao.insert(musicGroupPaymentCalender);
        Long calenderId = musicGroupPaymentCalender.getId();
        //保存会员缴费信息
        MusicGroupPaymentCalenderMember calenderMember = musicGroupPaymentBaseCalender.getCalenderMember();
        if (calenderMember != null) {
            calenderMember = musicGroupPaymentCalenderMemberService.initBean(calenderMember);
            calenderMember.setOriginalAmount(memberOriginalAmount);
            calenderMember.setCalenderId(calenderId);
            if (musicGroupPaymentBaseCalender.getPayUserType() == SCHOOL) {
                calenderMember.setActualAmount(BigDecimal.ZERO);
            }
            musicGroupPaymentCalenderMemberService.insert(calenderMember);
        }
        //保存乐保缴费信息
        MusicGroupPaymentCalenderRepair musicRepair = musicGroupPaymentBaseCalender.getMusicRepair();
        if (musicRepair != null) {
            musicRepair.setOriginalAmount(repairOriginalAmount);
            musicRepair.setCalenderId(calenderId);
            if (musicGroupPaymentBaseCalender.getPayUserType() == SCHOOL) {
                musicRepair.setActualAmount(BigDecimal.ZERO);
            }
            musicGroupPaymentCalenderRepairService.insert(musicRepair);
        }
        //保存活动缴费信息
        List<MusicGroupPaymentCalenderActivity> calenderActivityList = musicGroupPaymentBaseCalender.getCalenderActivityList();
        if (calenderActivityList != null && calenderActivityList.size() > 0) {
            musicGroupPaymentCalenderActivityService.initBean(calenderActivityList);
            if (musicGroupPaymentBaseCalender.getPayUserType() == SCHOOL) {
                calenderActivityList.forEach(e -> e.setActualAmount(BigDecimal.ZERO));
            }
            musicGroupPaymentCalenderActivityService.batchInsert(musicGroupPaymentBaseCalender, calenderId);
        }
        //保存课程费用列表
        musicGroupPaymentCalender.setMusicGroupPaymentCalenderCourseSettingsList(musicGroupPaymentBaseCalender.getMusicGroupPaymentCalenderCourseSettingsList());
        musicGroupPaymentCalenderCourseSettingsService.batchInsert(musicGroupPaymentCalender);

        // 如果是报名，需要修改乐团状态
        if (musicGroupPaymentBaseCalender.getPaymentType() == MUSIC_APPLY) {
            if (status != AUDITING) {
                musicGroup.setStatus(MusicGroupStatusEnum.APPLY);
                // 记录操作日志
                musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "报名缴费项目创建成功（创建缴费中 -> 报名中）", sysUser.getId(), ""));
            } else {
                musicGroup.setStatus(MusicGroupStatusEnum.FEE_AUDIT);
                // 记录操作日志
                musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "报名缴费项目创建成功（创建缴费 -> 费用审核中）", sysUser.getId(), ""));
            }
            musicGroup.setUpdateTime(date);
            musicGroupDao.update(musicGroup);
        }
        if (status == AUDITING) {
            // 如果是审核中
            Organization organization = organizationDao.get(musicGroup.getOrganId());
            sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                    null, null, MessageTypeEnum.BACKSTAGE_PAYMENT_CALENDER_AUDIT, organization.getName(), musicGroup.getName());
        } else {
            if (musicGroupPaymentCalender.getPaymentType() == PaymentType.ADD_STUDENT) {
                addStudent(musicGroupPaymentCalender, musicGroup);
                //将0元未缴费学员缴费状态更新为已缴费
                this.updateNoPaymentAndZeroPaymentStatus(musicGroupPaymentCalender, true);
                // 学生加到班级
                classGroupService.addStudentToClassGroupAndCourseArranging(calenderAddStudent.getStudentIds(), calenderAddStudent.getClassGroupIds(),
                        batchNo, musicGroupPaymentBaseCalender.getMusicGroupPaymentCalenderCourseSettingsList(), musicGroup);
                ExecutorService executor = Executors.newFixedThreadPool(5);
                CompletableFuture.runAsync(() -> {
                    imUserFriendService.refreshGroupImUserFriend(musicGroupId, GroupType.MUSIC);
                }, executor);
                executor.shutdown();
            }
        }
        ModelMap map = new ModelMap(1);
        map.put("musicGroupPaymentCalenderBatchNo", batchNo);
        return BaseController.succeed(map);
    }

    //校验缴费项目进行中加学员
    public void checkAddStudent(CalenderAddStudent calenderAddStudent, MusicGroup musicGroup) {
        //获取缴费状态在审核中或者已拒绝的缴费项目的学员
        Integer userId = calenderAddStudent.getStudentIds();
        if (musicGroup.getCourseViewType() == CourseViewTypeEnum.MEMBER_FEE) {
            //该学员是否在其他的会员团
            boolean hasMemberGroup = studentRegistrationDao.checkHasMemberGroup(musicGroup.getId(), userId);
            if (hasMemberGroup) {
                throw new BizException("操作失败：学员已在其他系统收费乐团中，不可报名该乐团请联系教务老师");
            }
        }

        String studentIds = musicGroupPaymentCalenderDao.queryCalenderStudentIds(musicGroup.getId(), null);
        if (StringUtils.isNotEmpty(studentIds)) {
            if (studentIds.contains(userId.toString())) {
                throw new BizException("创建缴费失败：所选学员有待审核或已拒绝的缴费项目");
            }
        }
        List<MusicGroupPaymentCalenderDetail> musicGroupPaymentCalenderDetailList = musicGroupPaymentCalenderDetailDao.queryNotPaymentStudentByUserIdAndMusicGroupId(userId, musicGroup.getId());
        if (musicGroupPaymentCalenderDetailList != null && musicGroupPaymentCalenderDetailList.size() > 0) {
            throw new BizException("创建缴费失败：已存在缴费项目");
        }
    }

    public Map<String, Object> getCalenderDetail(Map<String, Object> result, Long calenderId) {
        //课程
        List<MusicGroupPaymentCalenderCourseSettings> courseSettingsList = musicGroupPaymentCalenderCourseSettingsService.queryCalenderCourseSettings(calenderId);
        result.put("course", courseSettingsList==null?null:courseSettingsList.size() == 0?null:courseSettingsList);
        //乐保
        result.put("repair", musicGroupPaymentCalenderRepairService.findByCalenderId(calenderId));
        MusicGroupPaymentCalenderMember calenderMember = musicGroupPaymentCalenderMemberService.findByCalenderId(calenderId);
        //会员信息
        result.put("member", calenderMember);
        //活动相关信息
        List<MusicGroupPaymentCalenderActivity> byCalenderId = musicGroupPaymentCalenderActivityService.findByCalenderId(calenderId);
        result.put("activity", byCalenderId==null?null:byCalenderId.size() == 0?null:byCalenderId);
        if (calenderMember != null) {
            result.put("memberPrivilegesItemList", memberRankPrivilegesService.queryByMemberRankId(calenderMember.getMemberRankSettingId()));
        }
        return result;
    }

    @Override
    public Map<String, Object> getDetail(Long id) {
        Map<String, Object> result = new HashMap<>(10);
        //获取缴费项目详情
        MusicGroupPaymentCalender calender = musicGroupPaymentCalenderDao.get(id);
        //统计预计缴费人数
        Map<Long, Long> expectNumMap = MapUtil.convertIntegerMap(musicGroupPaymentCalenderDao.countExpectNum(id));
        if (expectNumMap != null) {
            calender.setExpectNum(expectNumMap.get(id) == null ? 0 : expectNumMap.get(id).intValue());
        }
        //统计实际缴费人数
        Map<Long, Long> actualNumMap = MapUtil.convertIntegerMap(musicGroupPaymentCalenderDao.countActualNum(id));
        if (actualNumMap != null) {
            calender.setActualNum(actualNumMap.get(id) == null ? 0 : actualNumMap.get(id).intValue());
        }

        if (calender.getOrganId() != null) {
            Organization organization = organizationDao.get(calender.getOrganId());
            calender.setOrganName(organization.getName());
        }
        if (StringUtils.isNotEmpty(calender.getMusicGroupId())) {
            MusicGroup musicGroup = musicGroupDao.get(calender.getMusicGroupId());
            calender.setMusicGroupName(musicGroup.getName());
        }
        result.put("calender", calender);
        //汇总收款金额
        BigDecimal sumActualAmount = musicGroupPaymentCalenderDetailDao.sumActualAmount(id);
        result.put("sumActualAmount", sumActualAmount);
        //进行中加学员
        if (calender.getPaymentType() == ADD_STUDENT) {
            String studentIds = calender.getStudentIds();
            if (StringUtils.isNotEmpty(studentIds)) {
                SysUser sysUser = studentDao.getUser(Integer.parseInt(studentIds));
                result.put("phone", sysUser.getPhone());
                result.put("username", sysUser.getUsername());
            }
        }
        //获取跨团合班学员缴费详情
        result.put("musicMerger", musicGroupPaymentCalenderStudentDetailDao.findByBatchNo(calender.getBatchNo()));
        return getCalenderDetail(result, id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String merge(MusicGroupPaymentCalenderDto musicGroupPaymentCalenderDto) {

        String batchNo = musicGroupPaymentCalenderDto.getBatchNo();

        List<MusicGroupPaymentCalender> musicGroupPaymentCalenderList = musicGroupPaymentCalenderDao.findByBatchNo(batchNo);
        if (musicGroupPaymentCalenderList == null || musicGroupPaymentCalenderList.size() == 0) {
            throw new BizException("[批次号]参数错误");
        }
        PaymentCalenderStatusEnum status = musicGroupPaymentCalenderList.get(0).getStatus();
        if (status != PaymentCalenderStatusEnum.REJECT && status != PaymentCalenderStatusEnum.DRAFT) {
            throw new BizException("{}的缴费状态不允许修改", status.getDesc());
        }
        PaymentType paymentType = musicGroupPaymentCalenderDto.getPaymentType();
        if (paymentType != SPAN_GROUP_CLASS_ADJUST) {
            throw new BizException("操作失败：该入口不支持{}", paymentType.getDesc());
        }
        List<MusicGroupPaymentDateRange> musicGroupPaymentDateRangeList = musicGroupPaymentCalenderDto.getMusicGroupPaymentDateRangeList();
        if (musicGroupPaymentDateRangeList.size() > 1) {
            throw new BizException("创建缴费失败：不支持多周期缴费");
        }
        String musicGroupId = musicGroupPaymentCalenderDto.getMusicGroupId();

        MusicGroup musicGroup = musicGroupDao.getLocked(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团查询失败，请检查参数");
        }
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("请登录");
        }

        List<Long> calenderIds = musicGroupPaymentCalenderList.stream().map(MusicGroupPaymentCalender::getId).collect(Collectors.toList());
        //删除原来数据
        musicGroupPaymentCalenderDao.delByIds(calenderIds);
        musicGroupPaymentCalenderCourseSettingsService.deleteByMusicGroupPaymentCalenderId(calenderIds);

        status = PaymentCalenderStatusEnum.NO;

        Date date = new Date();

        MusicGroupStudentClassAdjust adjust = musicGroupStudentClassAdjustDao.findByBatchNo(batchNo);
        //获取默认的学员缴费详情
        List<Integer> studentIdList = JSON.parseArray(adjust.getStudentIds(), Integer.class);
        //获取欠费学员列表
        List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(musicGroup.getId(), studentIdList,null);
        if (noPaymentUserIds.size() > 0) {
            throw new BizException("操作失败：有欠费的学员不允许创建缴费");
        }
        //获取缴费状态在审核中或者已拒绝的缴费项目的学员
        String studentIds = musicGroupPaymentCalenderDao.queryCalenderStudentIds(musicGroupId, batchNo);
        if (StringUtils.isNotEmpty(studentIds)) {
            for (Integer integer : studentIdList) {
                if (studentIds.contains(integer.toString())) {
                    throw new BizException("操作失败：所选学员有待审核或已拒绝的缴费项目");
                }
            }
        }

        List<MusicGroupPaymentCalenderStudentDetail> musicGroupPaymentCalenderStudentDetails = classGroupService.queryStudentPaymentCalenders(adjust.getMasterClassGroupId(),
                adjust.getClassGroupStudents(), studentIdList);
        List<MusicGroupPaymentCalenderStudentDetail> calenderStudentDetails = musicGroupPaymentCalenderDto.getMusicGroupPaymentCalenderStudentDetails();

        boolean containsAll = musicGroupPaymentCalenderStudentDetails.containsAll(calenderStudentDetails);
        if (!containsAll) {
            status = AUDITING;
        }
        //删除之前的记录
        musicGroupPaymentCalenderStudentDetailDao.delByBatchNo(batchNo);
        //保存现有记录
        musicGroupPaymentCalenderStudentDetailDao.batchInsert(calenderStudentDetails, batchNo);

        MusicGroupPaymentDateRange musicGroupPaymentDateRange = musicGroupPaymentDateRangeList.get(0);
        MusicGroupPaymentCalender musicGroupPaymentCalender = new MusicGroupPaymentCalender();
        musicGroupPaymentCalender.setAttribute1(musicGroupPaymentCalenderDto.getAttribute1());
        musicGroupPaymentCalender.setAttribute2(musicGroupPaymentCalenderDto.getAttribute2());
        musicGroupPaymentCalender.setDeadlinePaymentDate(musicGroupPaymentDateRange.getDeadlinePaymentDate());
        musicGroupPaymentCalender.setMemo(musicGroupPaymentCalenderDto.getMemo());
        musicGroupPaymentCalender.setMusicGroupId(musicGroupId);
        musicGroupPaymentCalender.setMusicGroupOrganizationCourseSettingId(musicGroupPaymentCalenderDto.getMusicGroupOrganizationCourseSettingId());
        musicGroupPaymentCalender.setOriginalTotalAmount(calenderStudentDetails.stream().map(e -> e.getCourseOriginalPrice()).reduce(BigDecimal.ZERO, BigDecimal::add));
        musicGroupPaymentCalender.setCurrentTotalAmount(calenderStudentDetails.stream().map(e -> e.getCourseCurrentPrice()).reduce(BigDecimal.ZERO, BigDecimal::add));
        musicGroupPaymentCalender.setPaymentType(paymentType);
        musicGroupPaymentCalender.setPayUserType(musicGroupPaymentCalenderDto.getPayUserType());
        musicGroupPaymentCalender.setStartPaymentDate(musicGroupPaymentDateRange.getStartPaymentDate());
        musicGroupPaymentCalender.setStudentIds(musicGroupPaymentCalenderDto.getStudentIds());
        musicGroupPaymentCalender.setOperator(sysUser.getId());
        musicGroupPaymentCalender.setCreateTime(date);
        musicGroupPaymentCalender.setUpdateTime(date);
        musicGroupPaymentCalender.setStatus(status);
        musicGroupPaymentCalender.setOrganId(musicGroup.getOrganId());
        if (musicGroupPaymentCalender.getStatus() != AUDITING) {
            if (date.after(musicGroupPaymentCalender.getStartPaymentDate())) {
                musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.OPEN);
            } else if (date.after(musicGroupPaymentCalender.getDeadlinePaymentDate())) {
                musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.OVER);
            } else {
                musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.NO);
            }
        }
        // 设置批次号
        musicGroupPaymentCalender.setBatchNo(batchNo);
        musicGroupPaymentCalenderDto.setBatchNo(batchNo);
        musicGroupPaymentCalenderDao.insert(musicGroupPaymentCalender);
//        List<MusicGroupPaymentCalenderCourseSettings> currentMusicGroupPaymentCalenderCourseSettings = musicGroupPaymentCalender
//                .getMusicGroupPaymentCalenderCourseSettingsList();

        if (musicGroupPaymentCalender.getStatus() != AUDITING) {
            // 如果是进行中加学生
            if (musicGroupPaymentCalender.getPaymentType() == PaymentType.ADD_STUDENT) {
                addStudent(musicGroupPaymentCalender, musicGroup);
            } else if (musicGroupPaymentCalender.getPaymentType() == SPAN_GROUP_CLASS_ADJUST) {
                //如果是跨团班级合并,添加学员
                musicGroupPaymentCalenderDetailService.batchAdd(musicGroupPaymentCalender, musicGroupPaymentCalenderDto.getMusicGroupPaymentCalenderStudentDetails());
            }
            //将0元未缴费学员缴费状态更新为已缴费
            this.updateNoPaymentAndZeroPaymentStatus(musicGroupPaymentCalender, true);
        }

        if (status == AUDITING) {
            // 如果是审核中
            Organization organization = organizationDao.get(musicGroup.getOrganId());
            sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                    null, null, MessageTypeEnum.BACKSTAGE_PAYMENT_CALENDER_AUDIT, organization.getName(), musicGroup.getName());
        } else {
            //删除和解冻班级，课程信息
            List<Map> classGroupStudents = JSON.parseArray(adjust.getClassGroupStudents(), Map.class);
            List<Long> courseIds = JSON.parseArray(adjust.getSubLockCourseIds(), Long.class);
            List<Long> allLockCourseIds = JSON.parseArray(adjust.getAllLockCourseIds(), Long.class);
            classGroupService.spanGroupClassAdjustPass(adjust.getMasterClassGroupId()
                    , studentIdList, courseIds, classGroupStudents, allLockCourseIds, batchNo, adjust.getMasterTotalPrice());
        }
        return batchNo;
    }

    //将0元未缴费学员缴费状态更新为已缴费
    @Transactional(rollbackFor = Exception.class)
    public void updateNoPaymentAndZeroPaymentStatus(MusicGroupPaymentCalender musicGroupPaymentCalender, Boolean updateFlag) {
        if (musicGroupPaymentCalender.getCurrentTotalAmount().compareTo(BigDecimal.ZERO) == 0) {
            int j = musicGroupPaymentCalenderDetailDao.updateNoPaymentAndZeroPaymentStatus(musicGroupPaymentCalender.getId());
            if (j > 0) {
                musicGroupPaymentCalender.setActualNum((musicGroupPaymentCalender.getActualNum() == null ? 0 : musicGroupPaymentCalender.getActualNum()) + j);
                if (updateFlag) {
                    musicGroupPaymentCalenderDao.update(musicGroupPaymentCalender);
                }
            }
        }
    }

    @Override
    public boolean makesureSchoolePaid(Long id, String memo) {
        MusicGroupPaymentCalender musicGroupPaymentCalender = musicGroupPaymentCalenderDao.get(id);
        if (musicGroupPaymentCalender == null) {
            throw new BizException("查询缴费信息失败");
        }

        if (musicGroupPaymentCalender.getPayUserType() != PayUserType.SCHOOL) {
            throw new BizException("只有学校缴费才能确认缴费状态");
        }

        musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.PAID);
        musicGroupPaymentCalender.setMemo(memo);
        musicGroupPaymentCalender.setUpdateTime(new Date());
        musicGroupPaymentCalenderDao.update(musicGroupPaymentCalender);

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addStudent(MusicGroupPaymentCalender musicGroupPaymentCalender,
                           MusicGroup musicGroup) {
        //如果是进行中加学生
        Date date = new Date();
        String studentIdStr = musicGroupPaymentCalender.getStudentIds();
        if (StringUtils.isNoneBlank(studentIdStr)) {
            //当前乐团是否有预排课计划
            MusicGroupSchoolTermCourseDetail termCourseDetail = musicGroupSchoolTermCourseDetailDao.findByCourseDateAndMusicGroupId(musicGroup.getId(), null, 0);
//            List<MusicGroupPaymentStudentCourseDetail> musicGroupPaymentStudentCourseDetailList = new ArrayList<MusicGroupPaymentStudentCourseDetail>();
//            MusicGroupPaymentStudentCourseDetail musicGroupPaymentStudentCourseDetail = null;

            List<MusicGroupPaymentCalenderActivity> calenderActivities = musicGroupPaymentCalenderActivityService.findByCalenderId(musicGroupPaymentCalender.getId());
            Map<Integer, VipGroupActivity> collect = new HashMap<>();
            if(CollectionUtils.isNotEmpty(calenderActivities)){
                List<VipGroupActivity> vipGroupActivities = vipGroupActivityDao.queryByIds(calenderActivities.stream().
                        map(e -> e.getActivityId().toString()).distinct().collect(Collectors.joining(",")));
                collect = vipGroupActivities.stream().collect(Collectors.groupingBy(e -> e.getId(),
                        Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
            }
            MusicGroupPaymentCalenderMember calenderMember = musicGroupPaymentCalenderMemberService.findByCalenderId(musicGroupPaymentCalender.getId());
            for (String studentId : studentIdStr.split(",")) {
                if (termCourseDetail != null) {
                    //是否已经预排部分课程
                    List<CourseSchedule> courseSchedules = courseScheduleDao.queryPreCourseListByMusicGroupId(musicGroup.getId());
                    if (courseSchedules.size() > 0) {
                        throw new BizException("操作失败：该乐团存在预排课课程，请优先完成预排课");
                    } else {
                        MusicGroupSchoolTermStudentCourseDetail studentCourseDetail = new MusicGroupSchoolTermStudentCourseDetail();
                        studentCourseDetail.setMusicGroupSchoolTermCourseDetailId(termCourseDetail.getId());
                        studentCourseDetail.setUserId(Integer.parseInt(studentId));
                        studentCourseDetail.setMemberCourseMinutes(termCourseDetail.getTotalCourseTime());
                        musicGroupSchoolTermStudentCourseDetailDao.insert(studentCourseDetail);
                    }
                }
                // 学生加到calenderDetail
                MusicGroupPaymentCalenderDetail musicGroupPaymentCalenderDetail = new MusicGroupPaymentCalenderDetail();
                musicGroupPaymentCalenderDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalender.getId());
                musicGroupPaymentCalenderDetail.setCreateTime(date);
                musicGroupPaymentCalenderDetail.setPaymentStatus(PaymentStatus.NON_PAYMENT);
                musicGroupPaymentCalenderDetail.setUpdateTime(date);
                musicGroupPaymentCalenderDetail.setUserId(Integer.parseInt(studentId));
                musicGroupPaymentCalenderDetail.setStartPaymentDate(musicGroupPaymentCalender.getStartPaymentDate());
                musicGroupPaymentCalenderDetail.setDeadlinePaymentDate(musicGroupPaymentCalender.getDeadlinePaymentDate());

                musicGroupPaymentCalenderDetailDao.insert(musicGroupPaymentCalenderDetail);
                //如果是0元那么更新fee表和studentRegistration表
                if (musicGroupPaymentCalender.getCurrentTotalAmount().compareTo(BigDecimal.ZERO) == 0) {
                    // 添加会员有效时长
                    if (calenderMember != null) {
                        CloudTeacherOrder cloudTeacherOrder = new CloudTeacherOrder();
                        cloudTeacherOrder.setLevel(calenderMember.getMemberRankSettingId());
                        cloudTeacherOrder.setOrganId(musicGroup.getOrganId());
                        cloudTeacherOrder.setType(calenderMember.getPeriod());
                        cloudTeacherOrder.setStudentId(Integer.parseInt(studentId));
                        cloudTeacherOrder.setOrderId(musicGroup.getOrganId().longValue());
                        cloudTeacherOrder.setTime(calenderMember.getNum().intValue());
                        cloudTeacherOrder.setAmount(BigDecimal.ZERO);
                        cloudTeacherOrder.setStatus(1);
                        cloudTeacherOrder.setRemark("进行中乐团0元加学生");
                        cloudTeacherOrder.setMusicGroupId(musicGroup.getId());
                        cloudTeacherOrderService.save(cloudTeacherOrder,calenderMember.getAutoActivationFlag());
                    }
                    //添加小课包
                    if (calenderActivities != null && calenderActivities.size() > 0) {
                        List<ActivityUserMapper> activityUserMapperList = new ArrayList<>();
                        for (MusicGroupPaymentCalenderActivity calenderActivity : calenderActivities) {
                            ActivityUserMapper activityUserMapper = new ActivityUserMapper();
                            activityUserMapper.setActualPrice(BigDecimal.ZERO);
                            activityUserMapper.setSubNoCoursePrice(BigDecimal.ZERO);
                            activityUserMapper.setActivityId(calenderActivity.getActivityId());
                            Student student = studentDao.get(Integer.parseInt(studentId));
                            activityUserMapper.setUserId(Integer.parseInt(studentId));
                            activityUserMapper.setTeacherId(student.getTeacherId());
                            if ("网管课".equals(calenderActivity.getCategoryName())) {
                                activityUserMapper.setPracticeFlag(1);
                            } else {
                                activityUserMapper.setVipFlag(1);
                            }
                            activityUserMapperService.copyProperty(activityUserMapper,collect.get(activityUserMapper.getActivityId()),false,true);
                            activityUserMapperList.add(activityUserMapper);
                        }
                        activityUserMapperService.batchInsert(activityUserMapperList);
                    }
                    //如果是进行中加学员
                    StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(Integer.parseInt(studentId), musicGroupPaymentCalender.getMusicGroupId());
                    studentRegistration.setPaymentStatus(YES);
                    studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
                    studentRegistrationDao.update(studentRegistration);

                    //统计变更学员数
                    groupEventSource.musicGroupStudentChangeEvent(musicGroupPaymentCalender.getMusicGroupId(), StudentMusicGroupStatusEnum.NORMAL, new ArrayList<>(Arrays.asList(Integer.parseInt(studentId))));
                }
                /*if (musicGroupPaymentCalenderCourseSettingsList != null && musicGroupPaymentCalenderCourseSettingsList.size() > 0) {
                    // 学生加课程明细
                    for (MusicGroupPaymentCalenderCourseSettings courseSettings : musicGroupPaymentCalenderCourseSettingsList) {
                        if (courseSettings.getIsStudentOptional() == true) {
                            continue;
                        }
                        musicGroupPaymentStudentCourseDetail = new MusicGroupPaymentStudentCourseDetail();
                        musicGroupPaymentStudentCourseDetail.setCourseType(courseSettings.getCourseType());
                        musicGroupPaymentStudentCourseDetail.setCreateTime(date);
                        musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalender.getId());
                        musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderDetailId(musicGroupPaymentCalenderDetail.getId());
                        musicGroupPaymentStudentCourseDetail.setTotalCourseMinutes(courseSettings.getCourseTotalMinuties());
                        musicGroupPaymentStudentCourseDetail.setCourseOriginalPrice(courseSettings.getCourseOriginalPrice());
                        musicGroupPaymentStudentCourseDetail.setCourseCurrentPrice(courseSettings.getCourseCurrentPrice());
                        musicGroupPaymentStudentCourseDetail.setUpdateTime(date);
                        musicGroupPaymentStudentCourseDetail.setUsedCourseMinutes(courseSettings.getCourseTotalMinuties());
                        musicGroupPaymentStudentCourseDetail.setUserId(Integer.parseInt(studentId));
                        musicGroupPaymentStudentCourseDetailList.add(musicGroupPaymentStudentCourseDetail);
                    }
                }
                if (musicGroupPaymentStudentCourseDetailList.size() > 0) {
                    musicGroupPaymentStudentCourseDetailDao.batchInsert(musicGroupPaymentStudentCourseDetailList);
                }*/
            }
        }
    }

    @Override
    public void autoUpdateMusicGroupStudentFeeStatus() {
        Date date = new Date();
        String format = DateUtil.format(date, DateUtil.DEFAULT_PATTERN);
        // 获取距离缴费开启指定天数后的缴费明细
        String configValue = sysConfigDao.findConfigValue("push_payment_detail");
        Map<Long, Long> maps = MapUtil.convertIntegerMap(musicGroupPaymentCalenderDao.queryCalenderByDay(configValue, format));
        if (maps != null && maps.size() > 0) {
            Set<Long> calenderId = maps.keySet();
            List<CalenderPushDto> calenderPushDtos = musicGroupPaymentCalenderDao.getCalenderPushDto(calenderId);
            Map<Long, List<CalenderPushDto>> collect = calenderPushDtos.stream().collect(Collectors.groupingBy(CalenderPushDto::getCalenderId));
            calenderId.forEach(e -> {
                CalenderPushDto calenderPushDto = collect.get(e).get(0);
                Map<Integer, String> receivers = new HashMap<>(1);
                receivers.put(calenderPushDto.getTeacherId(), calenderPushDto.getTeacherPhone());
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.SYSTEM_SMS_PUSH_PAYMENT_DETAIL, receivers, null, 0,
                        null, null, calenderPushDto.getMusicGroupName(), calenderPushDto.getPaymentValidStartDate(), calenderPushDto.getPaymentValidEndDate(),
                        maps.get(e));
                Map<Integer, String> receivers1 = new HashMap<>(1);
                receivers1.put(calenderPushDto.getTeacherId(), calenderPushDto.getTeacherId().toString());
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.SYSTEM_SMS_PUSH_PAYMENT_DETAIL, receivers1, null, 0,
                        null, "SYSTEM", calenderPushDto.getMusicGroupName(), calenderPushDto.getPaymentValidStartDate(), calenderPushDto.getPaymentValidEndDate(),
                        maps.get(e));
            });
        }
        // 获取离截止还有指定时间的缴费项，并发送推送消息给指定老师
        String configValue1 = sysConfigDao.findConfigValue("push_create_payment_calender");
        List<Long> calenderIds = musicGroupPaymentCalenderDao.queryEndIds(configValue1, format, null);
        if (calenderIds != null && calenderIds.size() > 0) {
            List<CalenderPushDto> calenderPushDtos = musicGroupPaymentCalenderDao.getCalenderPushDto(calenderIds);
            Map<Long, List<CalenderPushDto>> collect = calenderPushDtos.stream().collect(Collectors.groupingBy(CalenderPushDto::getCalenderId));
            calenderIds.forEach(e -> {
                CalenderPushDto calenderPushDto = collect.get(e).get(0);
                Map<Integer, String> receivers = new HashMap<>(1);
                receivers.put(calenderPushDto.getTeacherId(), calenderPushDto.getTeacherPhone());
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.SYSTEM_SMS_PUSH_PAYMENT_CREATE, receivers, null, 0,
                        null, null, calenderPushDto.getMusicGroupName(), calenderPushDto.getPaymentValidStartDate(), calenderPushDto.getPaymentValidEndDate());
                Map<Integer, String> receivers1 = new HashMap<>(1);
                receivers1.put(calenderPushDto.getTeacherId(), calenderPushDto.getTeacherId().toString());
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.SYSTEM_SMS_PUSH_PAYMENT_CREATE, receivers1, null, 0,
                        null, "SYSTEM", calenderPushDto.getMusicGroupName(), calenderPushDto.getPaymentValidStartDate(), calenderPushDto.getPaymentValidEndDate());
            });
        }

        // 乐团报名到期，提醒教务老师创建缴费
        List<CalenderPushDto> calenderPushDtos = musicGroupPaymentCalenderDao.getMusicCalenderPushDto(configValue1, format);
        if (calenderPushDtos != null && calenderPushDtos.size() > 0) {
            calenderPushDtos.forEach(e -> {
                Map<Integer, String> receivers = new HashMap<>(1);
                receivers.put(e.getTeacherId(), e.getTeacherPhone());
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.SYSTEM_SMS_PUSH_PAYMENT_CREATE, receivers, null, 0,
                        null, null, e.getMusicGroupName(), e.getPaymentValidStartDate(), e.getPaymentValidEndDate());
                Map<Integer, String> receivers1 = new HashMap<>(1);
                receivers1.put(e.getTeacherId(), e.getTeacherId().toString());
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.SYSTEM_SMS_PUSH_PAYMENT_CREATE, receivers1, null, 0,
                        null, "SYSTEM", e.getMusicGroupName(), e.getPaymentValidStartDate(), e.getPaymentValidEndDate());
            });
        }
    }

    @Override
    public PageInfo<MusicGroupPaymentCalenderAuditDto> auditList(MusicGroupPaymentCalenderQueryInfo queryInfo) {
        PageInfo<MusicGroupPaymentCalenderAuditDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);

        List<MusicGroupPaymentCalenderAuditDto> dataList = null;
        int count = musicGroupPaymentCalenderDao.countAuditList(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = musicGroupPaymentCalenderDao.queryAuditList(params);
            List<Integer> collect = dataList.stream().map(e -> e.getOrganId()).collect(Collectors.toList());
            collect.removeAll(Collections.singleton(null));
            Map<Integer, String> organNameMap = getMap("organization", "id_", "name_", collect, queryInfo.getTenantId(), Integer.class, String.class);
            List<Integer> operatorIds = dataList.stream().map(e -> e.getOperator()).collect(Collectors.toList());
            operatorIds.removeAll(Collections.singleton(null));
            Map<Integer, String> realNameMap = getMap("sys_user", "id_", "real_name_", operatorIds, queryInfo.getTenantId(), Integer.class, String.class);
            dataList.forEach(e -> {
                e.setOrganName(organNameMap.get(e.getOrganId()));
                e.setOperatorName(realNameMap.get(e.getOperator()));
            });
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public MusicGroupPaymentCalenderAuditDetailDto auditListDetail(String batchNo) {
        MusicGroupPaymentCalenderAuditDetailDto calenderAuditDetailDto = new MusicGroupPaymentCalenderAuditDetailDto();
        MusicGroupPaymentCalenderAuditDto auditDto = musicGroupPaymentCalenderDao.getAuditDetail(batchNo);
        calenderAuditDetailDto.setAuditDto(auditDto);
        //获取缴费周期
        List<MusicGroupPaymentCalender> groupPaymentCalenders = musicGroupPaymentCalenderDao.findByBatchNo(batchNo);
        if (groupPaymentCalenders == null || groupPaymentCalenders.size() == 0) {
            throw new BizException("缴费项目异常，请联系管理员");
        }
        calenderAuditDetailDto.setMusicGroupPaymentCalenders(groupPaymentCalenders);
        MusicGroupPaymentCalender paymentCalender = groupPaymentCalenders.get(0);
//		if(paymentCalender.getMemberRankSettingId() != null){
//			MemberRankSetting memberRankSetting = memberRankSettingDao.get(paymentCalender.getMemberRankSettingId());
//			if(memberRankSetting != null){
//				paymentCalender.setMemberRankSettingName(memberRankSetting.getName());
//			}
//		}
        if (paymentCalender.getPaymentType() == ADD_STUDENT) {
            try {
                String studentIds = groupPaymentCalenders.get(0).getStudentIds();
                if (StringUtils.isNotEmpty(studentIds)) {
                    SysUser sysUser = sysUserFeignService.queryUserById(Integer.parseInt(studentIds));
                    calenderAuditDetailDto.setPhone(sysUser.getPhone());
                    calenderAuditDetailDto.setUsername(sysUser.getUsername());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //获取收费标准
        calenderAuditDetailDto.setMusicGroupPaymentCalenderCourseSettings(musicGroupPaymentCalenderCourseSettingsService.queryCalenderCourseSettingsByBatchNo(batchNo));
        //获取跨团合班学员缴费详情
        calenderAuditDetailDto.setMusicGroupPaymentCalenderStudentDetails(musicGroupPaymentCalenderStudentDetailDao.findByBatchNo(batchNo));
        return calenderAuditDetailDto;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditPass(String batchNs, String auditMemo) {
        String[] split = batchNs.split(",");
        Date date = new Date();
        for (String batchNo : split) {
            List<MusicGroupPaymentCalender> musicGroupPaymentCalenders = musicGroupPaymentCalenderDao.findByBatchNo(batchNo);
            if (musicGroupPaymentCalenders == null || musicGroupPaymentCalenders.size() == 0) {
                throw new BizException("缴费项目不存在");
            }
            MusicGroupPaymentCalender calender = musicGroupPaymentCalenders.get(0);
            MusicGroup musicGroup = musicGroupDao.get(calender.getMusicGroupId());
            for (MusicGroupPaymentCalender musicGroupPaymentCalender : musicGroupPaymentCalenders) {
                //如果是报名项目，将乐团改为审核中，缴费项目修改状态，审核状态改为审核通过
                if (musicGroupPaymentCalender.getPayUserType() == SCHOOL) {
                    if (musicGroupPaymentCalender.getCurrentTotalAmount().compareTo(BigDecimal.ZERO) > 0) {
                        musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.OPEN);
                    } else {
                        musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.PAID);
                    }
                } else if (date.after(musicGroupPaymentCalender.getStartPaymentDate())) {
                    musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.OPEN);
                } else if (date.after(musicGroupPaymentCalender.getDeadlinePaymentDate())) {
                    musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.OVER);
                } else {
                    musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.NO);
                }
                musicGroupPaymentCalender.setAuditMemo(auditMemo);
                musicGroupPaymentCalender.setUpdateTime(date);

                if (musicGroupPaymentCalender.getPaymentType() == PaymentType.ADD_STUDENT) {
                    musicGroupPaymentCalender.setExpectNum(1);
//                    List<MusicGroupPaymentCalenderCourseSettings> musicGroupPaymentCalenderCourseSettings = musicGroupPaymentCalenderCourseSettingsService.queryCalenderCourseSettings(musicGroupPaymentCalender.getId());
                    addStudent(musicGroupPaymentCalender, musicGroup);
                }
            }
            if (calender.getPaymentType() == ADD_STUDENT || calender.getPaymentType() == SPAN_GROUP_CLASS_ADJUST) {
                // 所有缴费项目已完成排课才能创建下一个缴费项目
                List<String> batchNoList = new ArrayList<>();
                batchNoList.add(batchNo);
                String orignBatchNo = musicGroupPaymentStudentCourseDetailDao.getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(calender.getMusicGroupId(), null, null, batchNoList);
                if (StringUtils.isNoneBlank(orignBatchNo)) {
                    throw new BizException("{} 存在未排课的缴费项目，请先完成排课再操作", musicGroup.getName());
                }
                List<Integer> userIds = Arrays.stream(calender.getStudentIds().split(",")).mapToInt(Integer::valueOf).boxed().collect(Collectors.toList());
                //获取欠费学员列表
                List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(calender.getMusicGroupId(), userIds,null);
                if (noPaymentUserIds.size() > 0) {
                    throw new BizException("{} 有欠费的学员不允许创建缴费", musicGroup.getName());
                }
                //获取缴费状态在审核中或者已拒绝的缴费项目的学员
                String studentIds = musicGroupPaymentCalenderDao.queryCalenderStudentIds(calender.getMusicGroupId(), batchNo);
                if (StringUtils.isNotEmpty(studentIds)) {
                    for (Integer integer : userIds) {
                        if (studentIds.contains(integer.toString())) {
                            throw new BizException("{} 的 {} 缴费项目，所选学员有待审核或已拒绝的缴费项目", musicGroup.getName(), calender.getPaymentType().getCode());
                        }
                    }
                }
            }
            //如果是报名，并且所有的报名都审核通过，需要修改乐团状态
            if (calender.getPaymentType() == MUSIC_APPLY) {
                //统计乐团还在审核中或者审核被拒的缴费
                int count = musicGroupPaymentCalenderDao.countAuditReject(calender.getMusicGroupId(), calender.getId());
                if (count == 0) {
                    musicGroup.setStatus(MusicGroupStatusEnum.APPLY);
                    musicGroup.setUpdateTime(date);
                    musicGroupDao.update(musicGroup);
                    SysUser sysUser = sysUserFeignService.queryUserInfo();
                    if (sysUser == null || sysUser.getId() == null) {
                        throw new BizException("请重新登录");
                    }
                    //记录操作日志
                    musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroup.getId(), "报名缴费项目通过（费用审核中 -> 报名中）", sysUser.getId(), ""));
                }
            } else if (calender.getPaymentType() == ADD_STUDENT) {
                // 学生加到班级
                String classGroupIdStr = calender.getAttribute1();
                if (StringUtils.isNotBlank(classGroupIdStr)) {
                    classGroupService.addStudentToClassGroupAndCourseArranging(Integer.parseInt(calender.getStudentIds()), classGroupIdStr, batchNo,
                            musicGroupPaymentCalenderCourseSettingsService.queryCalenderCourseSettingsByBatchNo(batchNo), musicGroup);
                }
//                MusicGroupStudentClassAdjust musicGroupStudentClassAdjust = musicGroupStudentClassAdjustDao.findByBatchNo(batchNo);
//                if (musicGroupStudentClassAdjust != null) {
//                    如果是合班缴费
//                    autoClassGroupAdjust(musicGroupStudentClassAdjust);
//                }
            } else if (calender.getPaymentType() == SPAN_GROUP_CLASS_ADJUST) {
                List<MusicGroupPaymentCalenderStudentDetail> calenderStudentDetails = musicGroupPaymentCalenderStudentDetailDao.findByBatchNo(batchNo);
                //将学员加入新乐团、扣除原乐团剩余课程余额、补充到现有乐团
                Map<Integer, List<MusicGroupPaymentCalenderStudentDetail>> collect = calenderStudentDetails.stream().collect(Collectors.groupingBy(e -> e.getUserId()));
                MusicGroupStudentClassAdjust adjust = musicGroupStudentClassAdjustDao.findByBatchNo(batchNo);
                List<Map> classGroupStudents = JSON.parseArray(adjust.getClassGroupStudents(), Map.class);
                for (Map<Integer, String> classGroupStudent : classGroupStudents) {
                    Integer classGroupId = classGroupStudent.keySet().iterator().next();
                    studentRegistrationService.insertStudent(classGroupStudent.get(classGroupId), musicGroupDao.findByClassGroupId(classGroupId).getId(), musicGroup.getId(), collect,null);
                }
                //删除和解冻班级，课程信息
                List<Integer> studentIds = JSON.parseArray(adjust.getStudentIds(), Integer.class);
                List<Long> courseIds = JSON.parseArray(adjust.getSubLockCourseIds(), Long.class);
                List<Long> allLockCourseIds = JSON.parseArray(adjust.getAllLockCourseIds(), Long.class);
                //如果是跨团班级合并,添加学员
                musicGroupPaymentCalenderDetailService.batchAdd(calender, calenderStudentDetails);
                classGroupService.spanGroupClassAdjustPass(adjust.getMasterClassGroupId()
                        , studentIds, courseIds, classGroupStudents, allLockCourseIds, batchNo, adjust.getMasterTotalPrice());
            }
            for (MusicGroupPaymentCalender musicGroupPaymentCalender : musicGroupPaymentCalenders) {
                //将0元未缴费学员缴费状态更新为已缴费
                this.updateNoPaymentAndZeroPaymentStatus(musicGroupPaymentCalender, false);
            }
            musicGroupPaymentCalenderDao.batchUpdate(musicGroupPaymentCalenders);
            if (calender.getPaymentType() == ADD_STUDENT) {
                imUserFriendService.refreshGroupImUserFriend(calender.getMusicGroupId(), GroupType.MUSIC);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditRefuse(String batchNs, String auditMemo) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null || sysUser.getId() == null) {
            throw new BizException("请重新登录");
        }
        String[] split = batchNs.split(",");
        Date date = new Date();
        for (String batchNo : split) {
            List<MusicGroupPaymentCalender> musicGroupPaymentCalenders = musicGroupPaymentCalenderDao.findByBatchNo(batchNo);
            if (musicGroupPaymentCalenders == null || musicGroupPaymentCalenders.size() == 0) {
                throw new BizException("缴费项目不存在");
            }
            for (MusicGroupPaymentCalender musicGroupPaymentCalender : musicGroupPaymentCalenders) {
                musicGroupPaymentCalender.setStatus(PaymentCalenderStatusEnum.REJECT);
                musicGroupPaymentCalender.setUpdateTime(date);
                musicGroupPaymentCalender.setAuditMemo(auditMemo);
            }
            MusicGroupPaymentCalender calender = musicGroupPaymentCalenders.get(0);
            //如果是报名，并且所有的报名都审核通过，需要修改乐团状态
            if (calender.getPaymentType() == MUSIC_APPLY) {
                MusicGroup musicGroup = musicGroupDao.get(calender.getMusicGroupId());
                musicGroup.setStatus(MusicGroupStatusEnum.PRE_BUILD_FEE);
                musicGroup.setUpdateTime(date);
                musicGroupDao.update(musicGroup);
                //记录操作日志
                musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroup.getId(), "报名缴费项目失败（费用审核中 -> 审核拒绝）", sysUser.getId(), ""));
            }
            musicGroupPaymentCalenderDao.batchUpdate(musicGroupPaymentCalenders);
        }
    }

    //推送待续费通知
    public void pushWaitRenewMessage(Long calenderId, MusicGroup musicGroup, Set<Integer> studentIds) {
        if (studentIds == null) {
            studentIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentStudentIds(calenderId);
        }
        if (studentIds.size() > 0) {
            String baseUrl = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);
            StringBuffer memo = new StringBuffer("4?").append(baseUrl).append("/#/musicGroupRenew?calenderId=").append(calenderId).append("&id=").append(musicGroup.getId());
            Map<Integer, String> push = new HashMap<>(studentIds.size());
            studentIds.forEach(e -> push.put(e, e.toString()));
            // 发送续费通知
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_WAIT_RENEW_MESSAGE, push,
                    null, 0, memo.toString(), "STUDENT", musicGroup.getName());

            //获取未缴费且不是0元的学员列表
            Map<Integer, String> studentMaps = MapUtil.convertMybatisMap(musicGroupPaymentCalenderDetailDao.queryNoPaymentAndNotZeroStudent(calenderId, studentIds));
            if (studentMaps.size() > 0) {
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.STUDENT_SMS_WAIT_RENEW_MESSAGE, studentMaps,
                        null, 0, memo.toString(), null, musicGroup.getName());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void revoke(String batchNo) {
        List<MusicGroupPaymentCalender> calenders = musicGroupPaymentCalenderDao.findByBatchNo(batchNo);
        if (calenders.size() == 0) {
            throw new BizException("缴费批次不存在");
        }
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        Date date = new Date();
        calenders.forEach(e -> {
            if (e.getPaymentType() == ADD_STUDENT) {
                throw new BizException("{} 的缴费项目不允许撤回", e.getStatus().getDesc());
            }
            if (e.getStatus() != AUDITING) {
                throw new BizException("{} 的缴费状态不允许撤回", e.getStatus().getDesc());
            }
            if (e.getPaymentType() == MUSIC_APPLY) {
                //如果是报名，并且所有的报名都审核通过，需要修改乐团状态
                MusicGroup musicGroup = musicGroupDao.get(e.getMusicGroupId());
                musicGroup.setStatus(MusicGroupStatusEnum.PRE_BUILD_FEE);
                musicGroup.setUpdateTime(date);
                musicGroupDao.update(musicGroup);
                //记录操作日志
                musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroup.getId(), "报名缴费项目撤回（费用审核中 -> 撤回）", sysUser.getId(), ""));
            }
            e.setStatus(DRAFT);
        });
        musicGroupPaymentCalenderDao.batchUpdate(calenders);
    }

    @Override
    public List<MusicGroupPaymentCalender> findByBatchNo(String batchNo) {
        return musicGroupPaymentCalenderDao.findByBatchNo(batchNo);
    }

    @Override
    public PageInfo<MusicGroupPaymentCalenderResultDto> queryCalenderPage(MusicGroupPaymentCalenderQueryInfo queryInfo) {
        PageInfo<MusicGroupPaymentCalenderResultDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);

        List<MusicGroupPaymentCalenderResultDto> dataList = null;
        int count = musicGroupPaymentCalenderDao.countCalender(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = musicGroupPaymentCalenderDao.queryCalenderPage(params);
            Set<Integer> organIdList = dataList.stream().map(e -> e.getOrganId()).collect(Collectors.toSet());
            Map<Integer, String> organNameMap = getMap("organization", "id_", "name_", organIdList, queryInfo.getTenantId(), Integer.class, String.class);
            List<Integer> operatorIds = dataList.stream().map(e -> e.getOperator()).collect(Collectors.toList());
            operatorIds.removeAll(Collections.singleton(null));
            Map<Integer, String> realNameMap = getMap("sys_user", "id_", "real_name_", operatorIds, queryInfo.getTenantId(), Integer.class, String.class);
            dataList.forEach(e -> {
                e.setOrganName(organNameMap.get(e.getOrganId()));
                e.setOperatorName(realNameMap.get(e.getOperator()));
            });
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult<ModelMap> merge1(MusicGroupPaymentBaseCalender musicGroupPaymentBaseCalender) {
        del(musicGroupPaymentBaseCalender.getCalenderId());
        return create1(musicGroupPaymentBaseCalender);
    }

    @Override
    public MusicGroupPaymentCalender getMusicGroupRegCalender(String musicGroupId) {
        return musicGroupPaymentCalenderDao.getMusicGroupRegCalender(musicGroupId);
    }

    private BigDecimal getActualAmount(MusicGroupPaymentCalenderBase baseCalender) {
        if (baseCalender != null) {
            return baseCalender.getActualAmount();
        }
        return BigDecimal.ZERO;
    }

    @Override
    public BigDecimal getRepairAmount(Long calenderId) {
        return getActualAmount(musicGroupPaymentCalenderRepairService.findByCalenderId(calenderId));
    }

    @Override
    public BigDecimal getMemberAmount(Long calenderId) {
        return getActualAmount(musicGroupPaymentCalenderMemberService.findByCalenderId(calenderId));
    }

    @Override
    public BigDecimal getActivityAmount(List<Long> buyCalenderActivityIdList) {
        List<MusicGroupPaymentCalenderActivity> activityList = musicGroupPaymentCalenderActivityService.findByIds(buyCalenderActivityIdList);
        return activityList.stream().map(e -> e.getActualAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    @Override
    public MusicGroupPaymentCalender getApplyCalenderByMusicId(String musicGroupId) {
        return musicGroupPaymentCalenderDao.findByMusicGroupRegCalender(musicGroupId);
    }

    @Override
    public PageInfo<HasFreeCourseTimesDto> queryHasFreeCourseTimesStudent(BaseOrganQueryInfo queryInfo) {
        PageInfo<HasFreeCourseTimesDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List<HasFreeCourseTimesDto> dataList = null;

        int count = musicGroupDao.countHasFreeCourseTimes(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = musicGroupDao.queryHasFreeCourseTimes(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public Map<Long, Integer> findCooperationByIds(List<Long> calenderIds) {
        return (Map<Long, Integer>)MapUtil.convertIntegerMap(musicGroupPaymentCalenderDao.findCooperationByIds(calenderIds));
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public boolean autoUpdateMusicGroupPaymentCalenderStatus() {
        Date date = new Date();
        List<PaymentCalenderStatusEnum> statusList = new ArrayList<>();
        statusList.add(PaymentCalenderStatusEnum.NO);
        statusList.add(PaymentCalenderStatusEnum.OPEN);
        List<MusicGroupPaymentCalender> musicGroupPaymentCalenderList = musicGroupPaymentCalenderDao.queryByPaymentStatus(null, statusList, PayUserType.STUDENT.getCode());

        List<MusicGroupPaymentCalender> updateMusicGroupPaymentCalenderList = new ArrayList<MusicGroupPaymentCalender>();
        for (MusicGroupPaymentCalender mgpc : musicGroupPaymentCalenderList) {
            if (mgpc.getDeadlinePaymentDate() != null && date.after(mgpc.getDeadlinePaymentDate()) && mgpc.getStatus() == PaymentCalenderStatusEnum.OPEN) {
                // “进行中”更新至“已结束”
                mgpc.setUpdateTime(date);
                mgpc.setStatus(PaymentCalenderStatusEnum.OVER);
                //将0元未缴费学员缴费状态更新为已缴费
                this.updateNoPaymentAndZeroPaymentStatus(mgpc, false);
                updateMusicGroupPaymentCalenderList.add(mgpc);
                //如果是进行中加学员，将报名表状态改为NORMAL
                if (mgpc.getPaymentType() == MusicGroupPaymentCalender.PaymentType.ADD_STUDENT) {
                    studentRegistrationDao.updatePaymentStatusByClaenderId(mgpc.getId());
                }
            } else if (mgpc.getStartPaymentDate() != null && date.after(mgpc.getStartPaymentDate()) && mgpc.getStatus() == PaymentCalenderStatusEnum.NO) {
                MusicGroup musicGroup = musicGroupDao.get(mgpc.getMusicGroupId());
                if (musicGroup == null) {
                    continue;
                }
                //如果乐团还在审核中
                if (musicGroup.getStatus() == MusicGroupStatusEnum.DRAFT || musicGroup.getStatus() == MusicGroupStatusEnum.AUDIT || musicGroup.getStatus() == MusicGroupStatusEnum.AUDIT_FAILED || musicGroup.getStatus() == MusicGroupStatusEnum.CLOSE) {
                    continue;
                }
                // “未开始”更新至“进行中”
                mgpc.setUpdateTime(date);
                mgpc.setStatus(PaymentCalenderStatusEnum.OPEN);
                //将0元未缴费学员缴费状态更新为已缴费
                this.updateNoPaymentAndZeroPaymentStatus(mgpc, false);
                updateMusicGroupPaymentCalenderList.add(mgpc);
                if (mgpc.getPayUserType() == STUDENT) {
                    //推送待续费通知
                    pushWaitRenewMessage(mgpc.getId(), musicGroup, null);
                }
            }
        }
        if (updateMusicGroupPaymentCalenderList.size() > 0) {
            musicGroupPaymentCalenderDao.batchUpdate(updateMusicGroupPaymentCalenderList);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchInsert(List<MusicGroupPaymentCalender> musicGroupPaymentCalenders) {
        if (musicGroupPaymentCalenders != null && musicGroupPaymentCalenders.size() > 0) {
            musicGroupPaymentCalenderDao.delByGroupId(musicGroupPaymentCalenders.get(0).getMusicGroupId());
            musicGroupPaymentCalenders.forEach(e -> {
                musicGroupPaymentCalenderDao.insert(e);
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void del(Long id) {
        if (id == null) {
            throw new BizException("参数校验失败");
        }
        MusicGroupPaymentCalender calender = musicGroupPaymentCalenderDao.getForLock(id);
        if (calender == null) {
            throw new BizException("缴费信息不存在");
        }

        //缴费项目中没有学生即可删除缴费项目
        List<MusicGroupPaymentCalenderDetail> musicGroupPaymentCalenderDetailList = musicGroupPaymentCalenderDetailDao.queryByCalenderId(id, null);
        if (musicGroupPaymentCalenderDetailList != null && musicGroupPaymentCalenderDetailList.size() > 0) {
            throw new BizException("操作失败：缴费项目中已存在学员");
        }
        MusicGroupStudentClassAdjust adjust = musicGroupStudentClassAdjustDao.findByBatchNo(calender.getBatchNo());
        if (!Objects.isNull(adjust)) {
//            throw new BizException("操作失败：班级调整的缴费项目不支持");
            List<Map> classGroupStudents = JSON.parseArray(adjust.getClassGroupStudents(), Map.class);
            //删除班级关联的学员
            List<Integer> classGroupIds = new ArrayList<>();
            if (classGroupStudents != null && classGroupStudents.size() > 0) {
                for (Map<Integer, String> classGroupStudent : classGroupStudents) {
                    classGroupIds.addAll(classGroupStudent.keySet());
                }
            }
            List<Long> allLockCourseIds = JSON.parseArray(adjust.getAllLockCourseIds(), Long.class);
            //解冻课程
            courseScheduleDao.batchUpdateLockByCourseIds(allLockCourseIds, 0,null);
            //解冻班级
            classGroupIds.add(adjust.getMasterClassGroupId());
            classGroupService.batchUpdateLockByClassGroupIds(classGroupIds, 0);
            musicGroupStudentClassAdjustDao.delete(adjust.getId());
        }

        if (calender.getPaymentType() == PaymentType.MUSIC_APPLY) {
            // 是否存在缴费中的
            List<StudentPaymentOrder> studentPaymentOrderList = studentPaymentOrderDao.queryByDealStatus(calender.getMusicGroupId(), OrderTypeEnum.APPLY,
                    DealStatusEnum.ING);
            if (studentPaymentOrderList != null && studentPaymentOrderList.size() > 0) {
                throw new BizException("操作失败：存在缴费中的学生");
            }
        }

        musicGroupPaymentCalenderDao.delete(id);
        musicGroupPaymentCalenderDetailDao.deleteByCalenderId(id);
        musicGroupPaymentStudentCourseDetailDao.deleteByMusicGroupPaymentCalenderId(id);
        musicGroupPaymentCalenderActivityService.delByCalenderId(id);
        musicGroupPaymentCalenderMemberService.deleteByCalenderId(id);
        musicGroupPaymentCalenderRepairService.deleteByCalenderId(id);
        List<Long> calenderIds = new ArrayList<Long>();
        calenderIds.add(id);
        musicGroupPaymentCalenderCourseSettingsService.deleteByMusicGroupPaymentCalenderId(calenderIds);

        //如果乐团是“费用审核”，则需要修改状态
        MusicGroup musicGroup = musicGroupDao.get(calender.getMusicGroupId());
        if (musicGroup != null) {
            if (musicGroup.getStatus() == MusicGroupStatusEnum.FEE_AUDIT) {
                musicGroup.setStatus(MusicGroupStatusEnum.PRE_BUILD_FEE);
                musicGroup.setUpdateTime(new Date());
                musicGroupDao.update(musicGroup);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByBatchNo(String batchNo) {
        if (StringUtils.isBlank(batchNo)) {
            throw new BizException("参数错误");
        }
        List<MusicGroupPaymentCalender> musicGroupPaymentCalenderList = musicGroupPaymentCalenderDao.findByBatchNo(batchNo);
        for (MusicGroupPaymentCalender musicGroupPaymentCalender : musicGroupPaymentCalenderList) {
            del(musicGroupPaymentCalender.getId());
        }
        return true;
    }

    @Override
    public MusicGroupPaymentCalender findByMusicGroupRegCalender(String musicGroupId) {
        return musicGroupPaymentCalenderDao.findByMusicGroupRegCalender(musicGroupId);
    }

    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public MusicGroupStudentFee updateCalender(Long calenderDetailId, Integer userId) {
        Date date = new Date();
        MusicGroupPaymentCalenderDetail calenderDetail = musicGroupPaymentCalenderDetailDao.get(calenderDetailId);
        MusicGroupPaymentCalender calender = this.get(calenderDetail.getMusicGroupPaymentCalenderId());
        MusicGroupStudentFee musicGroupStudentFee = musicGroupStudentFeeDao.findByUser(userId, calender.getMusicGroupId());
//		if(calender.getIsGiveMusicNetwork() && musicGroupStudentFee != null){
//			//赠送网管课
//			musicGroupStudentFee.setRemainNetworkClassTimes(musicGroupStudentFee.getRemainNetworkClassTimes() + 1);
//		}
        //更新学生的缴费记录状态
        calenderDetail.setPaymentStatus(MusicGroupStudentFee.PaymentStatus.PAID_COMPLETED);
//		calenderDetail.setActualAmount(calenderDetail.getExpectAmount().add(calenderDetail.getExpectMemberAmount()));
        calenderDetail.setPayTime(date);
        calenderDetail.setUpdateTime(date);
        musicGroupPaymentCalenderDetailDao.update(calenderDetail);

        //更新实际缴费人数
        Integer actualNum = calender.getActualNum() == null ? 0 : calender.getActualNum();
        calender.setActualNum(actualNum + 1);
        calender.setUpdateTime(date);
        musicGroupPaymentCalenderDao.update(calender);
        return musicGroupStudentFee;
    }

}
