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

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.MusicGroupPaymentCalender.PaymentCalenderStatusEnum;
import com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus;
import com.ym.mec.biz.dal.enums.GroupType;
import com.ym.mec.biz.dal.enums.MessageTypeEnum;
import com.ym.mec.biz.dal.enums.OrderDetailTypeEnum;
import com.ym.mec.biz.dal.page.ArrearageStudentsQueryInfo;
import com.ym.mec.biz.dal.page.MusicCalenderDetailQueryInfo;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.common.tenant.TenantContextHolder;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.collection.MapUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PayUserType.STUDENT;
import static com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentCalenderStatusEnum.AUDITING;
import static com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus.NON_PAYMENT;
import static com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus.PAID_COMPLETED;

@Service
public class MusicGroupPaymentCalenderDetailServiceImpl extends BaseServiceImpl<Long, MusicGroupPaymentCalenderDetail> implements MusicGroupPaymentCalenderDetailService {

    @Autowired
    private MusicGroupPaymentCalenderDetailDao musicGroupPaymentCalenderDetailDao;
    @Autowired
    private MusicGroupPaymentCalenderDao musicGroupPaymentCalenderDao;
    @Autowired
    private MusicGroupPaymentCalenderService musicGroupPaymentCalenderService;
    @Autowired
    private MusicGroupPaymentCalenderCourseSettingsDao musicGroupPaymentCalenderCourseSettingsDao;
    @Autowired
    private MusicGroupPaymentStudentCourseDetailDao musicGroupPaymentStudentCourseDetailDao;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private MusicGroupStudentFeeDao musicGroupStudentFeeDao;
    @Autowired
    private ActivityUserMapperService activityUserMapperService;
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private MusicGroupPaymentCalenderMemberService musicGroupPaymentCalenderMemberService;
    @Autowired
    private MusicGroupPaymentCalenderActivityService musicGroupPaymentCalenderActivityService;
    @Autowired
    private StudentPaymentOrderDetailDao studentPaymentOrderDetailDao;
    @Autowired
    private CloudTeacherOrderService cloudTeacherOrderService;
    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private VipGroupActivityDao vipGroupActivityDao;
    @Autowired
    private OperatingReportCloudService operatingReportCloudService;

    @Override
    public BaseDAO<Long, MusicGroupPaymentCalenderDetail> getDAO() {
        return musicGroupPaymentCalenderDetailDao;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String openPayment(String ids, Date startPaymentDate, Date deadlinePaymentDate) {
        if (StringUtils.isEmpty(ids)) {
            throw new BizException("参数校验失败");
        }
        //获取可开启缴费列表
        List<MusicGroupPaymentCalenderDetail> calenderDetails = musicGroupPaymentCalenderDetailDao.queryCanOpenList(ids);
        if (calenderDetails.size() == 0) {
            return "操作失败：所选学员已开启缴费，或已完成缴费";
        }
        int length = ids.split(",").length;
        Date date = new Date();

        Long calenderId = calenderDetails.get(0).getMusicGroupPaymentCalenderId();
        MusicGroupPaymentCalender calender = musicGroupPaymentCalenderService.get(calenderId);
        calenderDetails.forEach(e -> {
            e.setUpdateTime(date);
            e.setOpen(1);
            e.setStartPaymentDate(startPaymentDate);
            e.setDeadlinePaymentDate(deadlinePaymentDate);
        });
        musicGroupPaymentCalenderDetailDao.batchUpdate(calenderDetails);
        Set<Integer> studentIds = calenderDetails.stream().map(e -> e.getUserId()).collect(Collectors.toSet());
        //推送消息
        if (calender.getPayUserType() == STUDENT && studentIds.size() > 0) {
            Map<Integer, String> push = new HashMap<>();
            for (Integer userId : studentIds) {
                push.put(userId, userId + "");
            }
            MusicGroup musicGroup = musicGroupDao.get(calender.getMusicGroupId());
            String baseUrl = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);
            String memo = "4?" + baseUrl + "/#/musicGroupRenew?calenderId=" + calender.getId() + "&id=" + calender.getMusicGroupId();
            // 发送续费通知
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_WAIT_RENEW_MESSAGE, push,
                    null, 0, memo, "STUDENT", musicGroup.getName());
            //获取未缴费且不是0元的学员列表
            Map<Integer, String> studentMaps = MapUtil.convertMybatisMap(musicGroupPaymentCalenderDetailDao.queryNoPaymentAndNotZeroStudent(calender.getId(), studentIds));
            if (studentMaps.size() > 0) {
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.STUDENT_SMS_WAIT_RENEW_MESSAGE, studentMaps,
                        null, 0, memo, null, musicGroup.getName());
            }
        }
        StringBuffer append = new StringBuffer("操作成功: 成功开启缴费").append(studentIds.size()).append("条,失败").append(length - studentIds.size()).append("条");
        return append.toString();
    }

    @Override
    public List<SimpleUserDto> findMusicGroupStudentWithSubject(String musicGroupId, Integer subjectId) {
        if (Objects.isNull(musicGroupId)) {
            throw new BizException("请指定乐团");
        }
        return musicGroupPaymentCalenderDetailDao.findMusicGroupStudentWithSubject(musicGroupId, subjectId);
    }

    @Override
    public void refreshUserMusicGroupPaymentStatusTask() {
        musicGroupPaymentCalenderDetailDao.refreshUserMusicGroupPaymentStatusTask();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchAdd(MusicGroupPaymentCalender musicGroupPaymentCalender, List<MusicGroupPaymentCalenderStudentDetail> musicGroupPaymentCalenderStudentDetails) {
        Map<Integer, List<MusicGroupPaymentCalenderStudentDetail>> collect = musicGroupPaymentCalenderStudentDetails.stream().collect(Collectors.groupingBy(e -> e.getUserId()));
        MusicGroupPaymentCalenderDetail musicGroupPaymentCalenderDetail = null;
        Long musicGroupPaymentCalenderId = musicGroupPaymentCalender.getId();
        for (Integer studentId : collect.keySet()) {
            musicGroupPaymentCalenderDetail = new MusicGroupPaymentCalenderDetail();
            musicGroupPaymentCalenderDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalenderId);
            musicGroupPaymentCalenderDetail.setPaymentStatus(PaymentStatus.NON_PAYMENT);
            List<MusicGroupPaymentCalenderStudentDetail> calenderStudentDetails = collect.get(studentId);
            BigDecimal totalPrice = calenderStudentDetails.stream().map(e -> e.getCourseCurrentPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
//			musicGroupPaymentCalenderDetail.setExpectAmount(totalPrice);
            if (musicGroupPaymentCalender.getStatus() != AUDITING) {
                if (totalPrice.doubleValue() == 0d) {
                    musicGroupPaymentCalenderDetail.setPaymentStatus(PaymentStatus.PAID_COMPLETED);
                    musicGroupPaymentCalender.setActualNum(musicGroupPaymentCalender.getActualNum() + 1);
//					musicGroupPaymentCalenderDetail.setActualAmount(totalPrice);
                }
            }
            musicGroupPaymentCalenderDetail.setMusicGroupId(musicGroupPaymentCalender.getMusicGroupId());
            musicGroupPaymentCalenderDetail.setUserId(studentId);
            musicGroupPaymentCalenderDetail.setStartPaymentDate(musicGroupPaymentCalender.getStartPaymentDate());
            musicGroupPaymentCalenderDetail.setDeadlinePaymentDate(musicGroupPaymentCalender.getDeadlinePaymentDate());
            musicGroupPaymentCalenderDetail.setResponsibleUserId(musicGroupPaymentCalender.getOperator());
            musicGroupPaymentCalenderDetailDao.insert(musicGroupPaymentCalenderDetail);
        }
        musicGroupPaymentCalender.setExpectNum(collect.keySet().size());
        musicGroupPaymentCalenderService.update(musicGroupPaymentCalender);
        //给学员推送缴费通知
        if (musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.OPEN) {
            musicGroupPaymentCalenderService.pushWaitRenewMessage(musicGroupPaymentCalenderId, musicGroupDao.get(musicGroupPaymentCalender.getMusicGroupId()), collect.keySet());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchAdd(String batchNo, Set<Integer> userIdList) {
        List<MusicGroupPaymentCalender> musicGroupPaymentCalenderList = musicGroupPaymentCalenderDao.findByBatchNo(batchNo);
        if (CollectionUtils.isEmpty(musicGroupPaymentCalenderList)) {
            throw new BizException("操作失败：缴费项目不存在");
        }
        MusicGroupPaymentCalender musicGroupPaymentCalender = musicGroupPaymentCalenderList.get(0);
        String musicGroupId = musicGroupPaymentCalender.getMusicGroupId();
        // 所有缴费项目已完成排课才能创建下一个缴费项目
        List<String> batchNoList = new ArrayList<>();
        batchNoList.add(batchNo);
		/*String orignBatchNo = musicGroupPaymentStudentCourseDetailDao.getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(musicGroupId, null, null,batchNoList);
		if (StringUtils.isNoneBlank(orignBatchNo)) {
			throw new BizException("当前乐团存在未排课的缴费项目，请先完成排课再操作");
		}*/
        //获取欠费学员列表
        List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(musicGroupId, new ArrayList<>(userIdList), null);
        if (noPaymentUserIds.size() > 0) {
            throw new BizException("操作失败：有欠费的学员不允许创建缴费");
        }
        //获取缴费状态在审核中或者已拒绝的缴费项目的学员
        String studentIds = musicGroupPaymentCalenderDao.queryCalenderStudentIds(musicGroupId, batchNo);
        if (StringUtils.isNotEmpty(studentIds)) {
            for (Integer integer : userIdList) {
                if (studentIds.contains(integer.toString())) {
                    throw new BizException("操作失败：所选学员有待审核或已拒绝的缴费项目");
                }
            }
        }
        Long musicGroupPaymentCalenderId = musicGroupPaymentCalender.getId();

        if (musicGroupPaymentCalender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.MUSIC_APPLY) {
            throw new BizException("操作失败：报名缴费项不允许添加学员");
        }
        if (musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.AUDITING
                || musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.REJECT) {
            throw new BizException("当前缴费状态不能添加学生");
        }
        //判断学生是否已存在
        Set<Integer> userList = musicGroupPaymentCalenderDetailDao.queryStudentIds(musicGroupPaymentCalenderId);
        if (Collections.disjoint(userList, userIdList) == false) {
            throw new BizException("操作失败：包含已存在的学员");
        }

        List<MusicGroupPaymentCalenderCourseSettings> courseSettingsList = musicGroupPaymentCalenderCourseSettingsDao.getWithPaymentCalender(musicGroupPaymentCalenderId);

        if (courseSettingsList != null && courseSettingsList.size() > 0) {
            List<StudentSubTotalCourseTimesDto> studentCourseTypeDtos = musicGroupPaymentStudentCourseDetailDao.queryStudentSubTotalCourseTimes(musicGroupId);

            Set<String> courseTypes = new HashSet<String>();
            for (StudentSubTotalCourseTimesDto dto : studentCourseTypeDtos) {
                if (userIdList.contains(dto.getUserId())) {
                    courseTypes.addAll(dto.getMapDtos().stream().filter(t -> t.getValue() > 0).map(t -> t.getKey()).collect(Collectors.toSet()));
                }
            }

            for (MusicGroupPaymentCalenderCourseSettings mgpccs : courseSettingsList) {
                if (courseTypes.contains(mgpccs.getCourseType().name())) {
                    throw new BizException("操作失败：存在未排完的[{}]", mgpccs.getCourseType().getMsg());
                }
            }
        }

        Date date = new Date();
        MusicGroupPaymentCalenderDetail musicGroupPaymentCalenderDetail = null;
        Map<Integer, Long> userMap = new HashMap<>();
        Map<Integer, Integer> activityuserMap = new HashMap<>();
        List<MusicGroupPaymentCalenderDetail> musicGroupPaymentCalenderDetailList = new ArrayList<MusicGroupPaymentCalenderDetail>();
        //创建缴费明细
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);

        List<MusicGroupPaymentCalenderActivity> calenderActivities = musicGroupPaymentCalenderActivityService.findByCalenderId(musicGroupPaymentCalenderId);
        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(musicGroupPaymentCalenderId);
        for (Integer studentId : userIdList) {
            musicGroupPaymentCalenderDetail = new MusicGroupPaymentCalenderDetail();
            musicGroupPaymentCalenderDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalenderId);
            musicGroupPaymentCalenderDetail.setCreateTime(date);
            if (musicGroupPaymentCalender.getCurrentTotalAmount().compareTo(BigDecimal.ZERO) == 0) {
                musicGroupPaymentCalenderDetail.setPaymentStatus(PaymentStatus.PAID_COMPLETED);
            } else {
                musicGroupPaymentCalenderDetail.setPaymentStatus(PaymentStatus.NON_PAYMENT);
            }
            musicGroupPaymentCalenderDetail.setUpdateTime(date);
            musicGroupPaymentCalenderDetail.setUserId(studentId);
            musicGroupPaymentCalenderDetail.setStartPaymentDate(musicGroupPaymentCalender.getStartPaymentDate());
            musicGroupPaymentCalenderDetail.setDeadlinePaymentDate(musicGroupPaymentCalender.getDeadlinePaymentDate());
            musicGroupPaymentCalenderDetail.setResponsibleUserId(musicGroupPaymentCalender.getOperator());
            musicGroupPaymentCalenderDetailList.add(musicGroupPaymentCalenderDetail);
            if (musicGroupPaymentCalender.getCurrentTotalAmount().compareTo(BigDecimal.ZERO) == 0) {
                // 添加会员
                if (calenderMember != null) {
                    CloudTeacherOrder cloudTeacherOrder = new CloudTeacherOrder();
                    cloudTeacherOrder.setOrganId(musicGroup.getOrganId());
                    cloudTeacherOrder.setType(calenderMember.getPeriod());
                    cloudTeacherOrder.setAmount(BigDecimal.ZERO);
                    cloudTeacherOrder.setStudentId(studentId);
                    cloudTeacherOrder.setLevel(calenderMember.getMemberRankSettingId());
                    cloudTeacherOrder.setTime(calenderMember.getNum().intValue());
                    cloudTeacherOrder.setStatus(1);
                    cloudTeacherOrder.setRemark("缴费项目0元新增学员");
                    cloudTeacherOrder.setMusicGroupId(musicGroupId);
                    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(studentId);
                        activityUserMapper.setUserId(studentId);
                        activityUserMapper.setTeacherId(student.getTeacherId());
                        VipGroupActivity activity = collect.get(activityUserMapper.getActivityId());
                        activityUserMapperService.copyProperty(activityUserMapper,activity,false,true);
                        if ("网管课".equals(calenderActivity.getCategoryName())) {
                            activityUserMapper.setPracticeFlag(1);
                        } else {
                            activityUserMapper.setVipFlag(1);
                        }
                        activityUserMapperList.add(activityUserMapper);
                    }
                    activityUserMapperService.batchInsert(activityUserMapperList);
                    activityUserMapperList.stream().forEach(e -> activityuserMap.put(e.getUserId(), e.getId()));
                }
            }
        }

        if (musicGroupPaymentCalenderDetailList.size() > 0) {
            musicGroupPaymentCalenderDetailDao.batchInsert(musicGroupPaymentCalenderDetailList);
            musicGroupPaymentCalenderDetailList.stream().forEach(e -> userMap.put(e.getUserId(), e.getId()));
        }
        //更新预计缴费人数
        musicGroupPaymentCalender.setExpectNum(musicGroupPaymentCalender.getExpectNum() + userIdList.size());
        musicGroupPaymentCalender.setUpdateTime(date);
        if (musicGroupPaymentCalender.getCurrentTotalAmount().compareTo(BigDecimal.ZERO) == 0) {
            musicGroupPaymentCalender.setActualNum(musicGroupPaymentCalender.getActualNum() + userIdList.size());
        }
        musicGroupPaymentCalenderService.update(musicGroupPaymentCalender);

        //创建学生课排课分钟数
        if (courseSettingsList != null && courseSettingsList.size() > 0) {
            List<MusicGroupPaymentStudentCourseDetail> musicGroupPaymentStudentCourseDetailList = new ArrayList<>();
            MusicGroupPaymentStudentCourseDetail musicGroupPaymentStudentCourseDetail = null;
            for (Integer studentId : userIdList) {
                for (MusicGroupPaymentCalenderCourseSettings courseSettings : courseSettingsList) {
                    if (courseSettings.getCourseTotalMinuties() == null || courseSettings.getCourseTotalMinuties() == 0) {
                        continue;
                    }
                    musicGroupPaymentStudentCourseDetail = new MusicGroupPaymentStudentCourseDetail();
                    musicGroupPaymentStudentCourseDetail.setCourseType(courseSettings.getCourseType());
                    musicGroupPaymentStudentCourseDetail.setCreateTime(date);
                    musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalenderId);
                    musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderDetailId(userMap.get(studentId));
                    musicGroupPaymentStudentCourseDetail.setTotalCourseMinutes(courseSettings.getCourseTotalMinuties());
                    musicGroupPaymentStudentCourseDetail.setCourseOriginalPrice(courseSettings.getCourseOriginalPrice());
                    musicGroupPaymentStudentCourseDetail.setCourseCurrentPrice(courseSettings.getCourseCurrentPrice());
                    musicGroupPaymentStudentCourseDetail.setUpdateTime(date);
                    musicGroupPaymentStudentCourseDetail.setUsedCourseMinutes(0);
                    musicGroupPaymentStudentCourseDetail.setUserId(studentId);
                    musicGroupPaymentStudentCourseDetail.setCloudTeacherPaymentFlag(musicGroupPaymentCalender.getCloudTeacherPaymentFlag());
                    musicGroupPaymentStudentCourseDetailList.add(musicGroupPaymentStudentCourseDetail);
                }
            }
            if (musicGroupPaymentStudentCourseDetailList.size() > 0) {
                musicGroupPaymentStudentCourseDetailDao.batchInsert(musicGroupPaymentStudentCourseDetailList);
            }
        }
        //给学员推送缴费通知
        if (musicGroupPaymentCalender.getPayUserType() == STUDENT && musicGroupPaymentCalender.getStatus() == PaymentCalenderStatusEnum.OPEN) {
            musicGroupPaymentCalenderService.pushWaitRenewMessage(musicGroupPaymentCalender.getId(),
                    musicGroupDao.get(musicGroupPaymentCalender.getMusicGroupId()), userIdList);
        }
    }

    @Override
    public List<FeeStudentDto> queryFeeStudents(String musicGroupId, String search, Integer subjectId) {
        return musicGroupStudentFeeDao.queryFeeStudents(musicGroupId, search, subjectId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDel(String musicGroupPaymentCalenderDetailIds) {
        List<MusicGroupPaymentCalenderDetail> details = musicGroupPaymentCalenderDetailDao.queryListByIds(musicGroupPaymentCalenderDetailIds);
        if (details == null || details.size() == 0) {
            throw new BizException("删除失败: 数据不可为空");
        }
        Long musicGroupPaymentCalenderId = details.get(0).getMusicGroupPaymentCalenderId();
        MusicGroupPaymentCalender musicGroupPaymentCalender = musicGroupPaymentCalenderDao.get(musicGroupPaymentCalenderId);
        if (musicGroupPaymentCalender == null) {
            throw new BizException("查询缴费项目失败[{}]", musicGroupPaymentCalender);
        }
        long count = 0;
        if (musicGroupPaymentCalender.getPayUserType() == STUDENT) {
            // 是否已缴费
            count = details.stream().filter(e -> e.getPaymentStatus() != NON_PAYMENT).count();
            if (count > 0) {
                throw new BizException("删除失败: 存在已缴费的学员");
            }
        }
        List<Long> musicGroupPaymentCalenderDetailIdList = new ArrayList<Long>();
        for (String s : musicGroupPaymentCalenderDetailIds.split(",")) {
            musicGroupPaymentCalenderDetailIdList.add(Long.parseLong(s));
        }
        //是否已排课
        List<MusicGroupPaymentStudentCourseDetail> musicGroupPaymentStudentCourseDetailList = musicGroupPaymentStudentCourseDetailDao.queryByMusicGroupPaymentStudentCourseDetailId(musicGroupPaymentCalenderDetailIdList);
        count = musicGroupPaymentStudentCourseDetailList.stream().filter(e -> e.getUsedCourseMinutes() > 0).count();
        if (count > 0) {
            throw new BizException("删除失败：存在已排课的学员");
        }

        int currentNum = musicGroupPaymentCalender.getExpectNum() - details.size();
        musicGroupPaymentCalender.setExpectNum(currentNum < 0 ? 0 : currentNum);
        musicGroupPaymentCalender.setUpdateTime(new Date());
        musicGroupPaymentCalenderDao.update(musicGroupPaymentCalender);

        musicGroupPaymentCalenderDetailDao.batchDel(musicGroupPaymentCalenderDetailIds);
        musicGroupPaymentStudentCourseDetailDao.deleteByMusicGroupPaymentCalenderDetailId(musicGroupPaymentCalenderDetailIdList);
    }

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

        List<MusicArrearageStudentDto> dataList = null;
        int count = musicGroupPaymentCalenderDetailDao.countArrearageStudents(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = musicGroupPaymentCalenderDetailDao.queryArrearageStudents(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public List<MusicGroup> getNoPaymentStudentMusicGroups(String organIdsStr) {
        Set<Integer> organIds = null;
        if (StringUtils.isNotBlank(organIdsStr)) {
            organIds = Arrays.stream(organIdsStr.split(",")).map(Integer::new).collect(Collectors.toSet());
        }
        return musicGroupPaymentCalenderDetailDao.getNoPaymentStudentMusicGroups(organIds, TenantContextHolder.getTenantId());
    }

    @Override
    public void pushWaitRenewMessage(Long calenderId, String studentIds) {
        List<MusicGroupPaymentCalenderDetail> calenderDetails = musicGroupPaymentCalenderDetailDao.queryNoPaymentCanPushByCalenderId(calenderId, studentIds);
        if (calenderDetails == null || calenderDetails.size() == 0) {
            throw new BizException("发送失败：没有可以发送缴费提醒的学员");
        }
        Set<Integer> studentIdList = calenderDetails.stream().map(e -> e.getUserId()).collect(Collectors.toSet());
        MusicGroupPaymentCalender paymentCalender = musicGroupPaymentCalenderDao.get(calenderId);
        //未缴费
        Map<Integer, String> studentMaps = MapUtil.convertMybatisMap(musicGroupPaymentCalenderDetailDao.queryNoPaymentAndNotZeroStudent(calenderId, studentIdList));
        MusicGroup musicGroup = musicGroupDao.get(paymentCalender.getMusicGroupId());
        String baseUrl = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);
        String memo = "4?" + baseUrl + "/#/musicGroupRenew?calenderId=" + calenderId + "&id=" + musicGroup.getId();
        Map<Integer, String> push = new HashMap<>();
        for (Integer userId : studentIdList) {
            push.put(userId, userId.toString());
        }
        // 发送续费通知
        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_WAIT_RENEW_MESSAGE, push,
                null, 0, memo, "STUDENT", musicGroup.getName());
        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.STUDENT_SMS_WAIT_RENEW_MESSAGE, studentMaps,
                null, 0, memo, null, musicGroup.getName());
    }

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

        List<MusicGroupPaymentCalenderDetailDto> dataList = null;
        int count = musicGroupPaymentCalenderDetailDao.countDetailPage(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = musicGroupPaymentCalenderDetailDao.queryDetailPage(params);
            List<StudentPaymentOrderDetail> orderDetail = studentPaymentOrderDetailDao.findByCalenderId(dataList.get(0).getMusicGroupPaymentCalenderId());
            Map<Integer, List<StudentPaymentOrderDetail>> orderDetailMap = orderDetail.stream().collect(Collectors.groupingBy(StudentPaymentOrderDetail::getUserId));
            for (MusicGroupPaymentCalenderDetailDto row : dataList) {
                List<StudentPaymentOrderDetail> orderDetailList = orderDetailMap.get(row.getUserId());
                if (orderDetailList != null && orderDetailList.size() > 0) {
                    BigDecimal totalAmount = orderDetailList.stream().map(e -> e.getPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
                    //辅件
                    BigDecimal accessoriesAmount = orderDetailList.stream().filter(e -> e.getType() == OrderDetailTypeEnum.ACCESSORIES).map(e -> e.getPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
                    row.setAccessoriesAmount(accessoriesAmount);
                    //会员金额
                    BigDecimal cloudAmount = orderDetailList.stream().filter(e -> e.getType() == OrderDetailTypeEnum.CLOUD_TEACHER || e.getType() == OrderDetailTypeEnum.CLOUD_TEACHER_PLUS).map(e -> e.getPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
                    row.setCloudAmount(cloudAmount);
                    //乐器
                    BigDecimal musicalAmount = orderDetailList.stream().filter(e -> e.getType() == OrderDetailTypeEnum.MUSICAL).map(e -> e.getPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
                    row.setMusicalAmount(musicalAmount);
                    //乐保
                    BigDecimal maintenanceAmount = orderDetailList.stream().filter(e -> e.getType() == OrderDetailTypeEnum.MAINTENANCE).map(e -> e.getPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
                    row.setMaintenanceAmount(maintenanceAmount);
                    //活动
                    BigDecimal activityAmount = orderDetailList.stream().filter(e -> e.getType() == OrderDetailTypeEnum.PRACTICE || e.getType() == OrderDetailTypeEnum.VIP).map(e -> e.getPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
                    row.setActivityAmount(activityAmount);

                    totalAmount = totalAmount.subtract(accessoriesAmount).subtract(cloudAmount).subtract(musicalAmount).subtract(maintenanceAmount).subtract(activityAmount);
                    row.setCourseAmount(totalAmount);
                }
            }
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCalenderDetail(StudentPaymentOrder studentPaymentOrder, StudentRegistration studentRegistration) {
        Date nowDate = new Date();
        Integer tenantId = studentPaymentOrder.getTenantId();
        //缴费详情 calender detail
        MusicGroupPaymentCalender musicGroupPaymentCalender = musicGroupPaymentCalenderService.get(studentPaymentOrder.getCalenderId());
        Long currentPaymentCalenderId = studentPaymentOrder.getCalenderId();
        //查询缴费项目关联的订单
        List<StudentPaymentOrder> orderList = studentPaymentOrderDao.findByCalenderId(currentPaymentCalenderId, studentPaymentOrder.getUserId());
        if (orderList.size() == 1) {
            // 更新实际缴费人数
            if (musicGroupPaymentCalender.getActualNum() == null) {
                musicGroupPaymentCalender.setActualNum(1);
            } else {
                musicGroupPaymentCalender.setActualNum(musicGroupPaymentCalender.getActualNum() + 1);
            }
            if (musicGroupPaymentCalender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.MUSIC_APPLY) {
                if (musicGroupPaymentCalender.getExpectNum() == null) {
                    musicGroupPaymentCalender.setExpectNum(1);
                } else {
                    musicGroupPaymentCalender.setExpectNum(musicGroupPaymentCalender.getExpectNum() + 1);
                }
            }
            musicGroupPaymentCalender.setUpdateTime(nowDate);
            musicGroupPaymentCalenderDao.update(musicGroupPaymentCalender);
        }
        MusicGroupPaymentCalenderDetail musicGroupPaymentCalenderDetail = musicGroupPaymentCalenderDetailDao.findByCalenderIdAndUserId(currentPaymentCalenderId, studentPaymentOrder.getUserId());
        if (musicGroupPaymentCalenderDetail == null) {
            musicGroupPaymentCalenderDetail = new MusicGroupPaymentCalenderDetail();
            musicGroupPaymentCalenderDetail.setTenantId(tenantId);
            musicGroupPaymentCalenderDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalender.getId());
            musicGroupPaymentCalenderDetail.setUserId(studentPaymentOrder.getUserId());
            musicGroupPaymentCalenderDetail.setResponsibleUserId(musicGroupPaymentCalender.getOperator());
            musicGroupPaymentCalenderDetail.setPaymentStatus(PAID_COMPLETED);
            musicGroupPaymentCalenderDetail.setPayTime(nowDate);
            musicGroupPaymentCalenderDetail.setPaymentOrderId(studentPaymentOrder.getId());
            musicGroupPaymentCalenderDetail.setUseInCourse(0);
            musicGroupPaymentCalenderDetail.setOpen(1);
            musicGroupPaymentCalenderDetail.setUserStatus(null);
            musicGroupPaymentCalenderDetail.setDeadlinePaymentDate(musicGroupPaymentCalender.getDeadlinePaymentDate());
            musicGroupPaymentCalenderDetail.setStartPaymentDate(musicGroupPaymentCalender.getStartPaymentDate());
            musicGroupPaymentCalenderDetail.setCreateTime(nowDate);
            musicGroupPaymentCalenderDetail.setUpdateTime(nowDate);
            musicGroupPaymentCalenderDetailDao.insert(musicGroupPaymentCalenderDetail);
        } else {
            musicGroupPaymentCalenderDetail.setPaymentStatus(PAID_COMPLETED);
            musicGroupPaymentCalenderDetail.setPayTime(nowDate);
            musicGroupPaymentCalenderDetail.setPaymentOrderId(studentPaymentOrder.getId());
            musicGroupPaymentCalenderDetailDao.update(musicGroupPaymentCalenderDetail);
        }

        //保存、更新云教练缴费项目预收
        operatingReportCloudService.updateSet(musicGroupPaymentCalender,studentPaymentOrder.getId());

        Boolean cloudTeacherPaymentFlag = false;
        if(musicGroupPaymentCalender.getCloudTeacherPaymentFlag()){
            List<MusicGroupPaymentCalenderCourseSettings> courseSettings = musicGroupPaymentCalenderCourseSettingsDao.queryCalenderCourseSettings(musicGroupPaymentCalender.getId());
            BigDecimal reduce = courseSettings.stream().map(e -> e.getCourseCurrentPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
            cloudTeacherPaymentFlag = reduce.compareTo(BigDecimal.ZERO) == 0;
        }
        //续费项目加学员时就生成了课程时长，报名项目在缴费成功后才需要添加课程时长
        if (musicGroupPaymentCalender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.MUSIC_APPLY) {
            List<MusicGroupPaymentStudentCourseDetail> musicGroupPaymentStudentCourseDetails = new ArrayList<>();
            List<String> orderDetailTypes = studentPaymentOrderDetailDao.getOrderDetailType(studentPaymentOrder.getId());
            List<MusicGroupPaymentCalenderCourseSettings> courseSettingsList = musicGroupPaymentCalenderCourseSettingsDao
                    .getWithPaymentCalender(musicGroupPaymentCalender.getId());
            for (MusicGroupPaymentCalenderCourseSettings courseSetting : courseSettingsList) {
                if (musicGroupPaymentCalender.getPayUserType().equals(MusicGroupPaymentCalender.PayUserType.STUDENT)
                        && !orderDetailTypes.contains(courseSetting.getCourseType().getCode())) {
                    continue;
                }
                if (courseSetting.getCourseTotalMinuties() == null || courseSetting.getCourseTotalMinuties() == 0) {
                    continue;
                }
                MusicGroupPaymentStudentCourseDetail musicGroupPaymentStudentCourseDetail = new MusicGroupPaymentStudentCourseDetail();
                musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalender.getId());
                musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderDetailId(musicGroupPaymentCalenderDetail.getId());
                musicGroupPaymentStudentCourseDetail.setUserId(studentPaymentOrder.getUserId());
                musicGroupPaymentStudentCourseDetail.setCourseType(courseSetting.getCourseType());
                musicGroupPaymentStudentCourseDetail.setTotalCourseMinutes(courseSetting.getCourseTotalMinuties());
                musicGroupPaymentStudentCourseDetail.setCourseOriginalPrice(courseSetting.getCourseOriginalPrice());
                musicGroupPaymentStudentCourseDetail.setCourseCurrentPrice(courseSetting.getCourseCurrentPrice());
                musicGroupPaymentStudentCourseDetail.setUsedCourseMinutes(0);
                musicGroupPaymentStudentCourseDetail.setCreateTime(nowDate);
                musicGroupPaymentStudentCourseDetail.setUpdateTime(nowDate);
                musicGroupPaymentStudentCourseDetail.setTenantId(tenantId);
                musicGroupPaymentStudentCourseDetail.setCloudTeacherPaymentFlag(cloudTeacherPaymentFlag);
                musicGroupPaymentStudentCourseDetails.add(musicGroupPaymentStudentCourseDetail);
            }
            if (musicGroupPaymentStudentCourseDetails.size() > 0) {
                musicGroupPaymentStudentCourseDetailDao.batchInsert(musicGroupPaymentStudentCourseDetails);
            }
        }
    }
}
