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

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

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 org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSON;
import com.ym.mec.biz.dal.dao.ClassGroupStudentMapperDao;
import com.ym.mec.biz.dal.dao.CourseScheduleDao;
import com.ym.mec.biz.dal.dao.CourseScheduleStudentPaymentDao;
import com.ym.mec.biz.dal.dao.ExtracurricularExercisesReplyDao;
import com.ym.mec.biz.dal.dao.MusicGroupDao;
import com.ym.mec.biz.dal.dao.StudentCourseHomeworkDao;
import com.ym.mec.biz.dal.dao.StudentDao;
import com.ym.mec.biz.dal.dao.StudentExtracurricularExercisesSituationDao;
import com.ym.mec.biz.dal.dao.StudentRegistrationDao;
import com.ym.mec.biz.dal.dto.BasicUserDto;
import com.ym.mec.biz.dal.dto.ClassGroupStudentMapperDto;
import com.ym.mec.biz.dal.dto.IndexBaseDto;
import com.ym.mec.biz.dal.dto.StudentServeCourseDto;
import com.ym.mec.biz.dal.dto.StudentServeCourseHomeworkDto;
import com.ym.mec.biz.dal.dto.StudentServeDto;
import com.ym.mec.biz.dal.entity.CourseSchedule;
import com.ym.mec.biz.dal.entity.CourseSchedule.CourseScheduleType;
import com.ym.mec.biz.dal.entity.CourseScheduleStudentPayment;
import com.ym.mec.biz.dal.entity.ExtracurricularExercisesReply;
import com.ym.mec.biz.dal.entity.IndexBaseMonthData;
import com.ym.mec.biz.dal.entity.MusicGroup;
import com.ym.mec.biz.dal.entity.StudentCourseHomework;
import com.ym.mec.biz.dal.entity.StudentExtracurricularExercisesSituation;
import com.ym.mec.biz.dal.entity.StudentRegistration;
import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
import com.ym.mec.biz.dal.enums.CourseStatusEnum;
import com.ym.mec.biz.dal.enums.GroupType;
import com.ym.mec.biz.dal.enums.IndexDataType;
import com.ym.mec.biz.dal.enums.MusicGroupStatusEnum;
import com.ym.mec.biz.dal.enums.TeachTypeEnum;
import com.ym.mec.biz.dal.enums.YesOrNoEnum;
import com.ym.mec.biz.service.StudentExtracurricularExercisesSituationService;
import com.ym.mec.biz.service.StudentServeService;
import com.ym.mec.biz.service.SysConfigService;
import com.ym.mec.biz.service.SysTenantConfigService;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.tenant.TenantContextHolder;
import com.ym.mec.util.date.DateUtil;

/**
 * @Author Joburgess
 * @Date 2020.05.27
 */
@Service
public class StudentServeServiceImpl implements StudentServeService {

    @Autowired
    private CourseScheduleDao courseScheduleDao;
    @Autowired
    private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private StudentCourseHomeworkDao studentCourseHomeworkDao;
    @Autowired
    private ExtracurricularExercisesReplyDao extracurricularExercisesReplyDao;
    @Autowired
    private StudentExtracurricularExercisesSituationDao studentExtracurricularExercisesSituationDao;
    @Autowired
    private StudentExtracurricularExercisesSituationService studentExtracurricularExercisesSituationService;
    @Autowired
    private StudentServeService studentServeService;
    @Autowired
    private SysTenantConfigService sysTenantConfigService;
    @Autowired
    private ClassGroupStudentMapperDao classGroupStudentMapperDao;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private StudentRegistrationDao studentRegistrationDao;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exercisesSituationStatistics(String monday, Integer tenantId) {
        LocalDate nowDate = LocalDateTime.now(DateUtil.zoneId).toLocalDate();

        int lastWeekTodayUpdateNum = studentExtracurricularExercisesSituationDao.findLastWeekTodayUpdateNum(nowDate.plusDays(-nowDate.getDayOfWeek().getValue()).toString(), tenantId);
        if(lastWeekTodayUpdateNum<=0){
            nowDate = nowDate.plusDays(-nowDate.getDayOfWeek().getValue());
        }

        if(StringUtils.isNotBlank(monday)){
            nowDate=LocalDate.parse(monday, DateUtil.dateFormatter);
        }

        LocalDate monDayDate = nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
        LocalDate sunDayDate = nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.SUNDAY.getValue());
        Date nextMonday = Date.from(sunDayDate.plusDays(1).atStartOfDay(DateUtil.zoneId).toInstant());

        List<Integer> beServeStudentIds=studentDao.getServeStudentIds(tenantId);
        List<Integer> serveStudentIds=new ArrayList<>();
        List<StudentServeCourseDto> serveStudentCourseStartTimes = studentDao.getServeStudentCourseStartTimes(monDayDate.toString(),tenantId);
        Map<Integer, List<StudentServeCourseDto>> studentTimesMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(serveStudentCourseStartTimes)){
            studentTimesMap = serveStudentCourseStartTimes.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getStudentId));
        }
        for (Integer beServeStudentId : beServeStudentIds) {
            List<StudentServeCourseDto> studentServeCourseDtos = studentTimesMap.get(beServeStudentId);
            if(CollectionUtils.isEmpty(studentServeCourseDtos)
                    ||Objects.isNull(studentServeCourseDtos.get(0).getServiceTagUpdateTime())){
                serveStudentIds.add(beServeStudentId);
                continue;
            }
            long thisWeekCourses = studentServeCourseDtos.stream().filter(e -> !e.getCourseStartTime().before(e.getServiceTagUpdateTime()) && e.getCourseStartTime().compareTo(nextMonday) <= 0).count();
            if(thisWeekCourses>0){
                serveStudentIds.add(beServeStudentId);
            }
        }

        BigDecimal currentPage=BigDecimal.ONE,
                pageSize=new BigDecimal(1000),
                total=new BigDecimal(serveStudentIds.size()),
                totalPage=total.divide(pageSize, BigDecimal.ROUND_UP);

        List<StudentExtracurricularExercisesSituation> results=new ArrayList<>();

        while (currentPage.compareTo(totalPage)<=0){
            List<Integer> studentIds=serveStudentIds.stream().skip(pageSize.multiply(currentPage.subtract(BigDecimal.ONE)).longValue()).limit(pageSize.longValue()).collect(Collectors.toList());

            List<StudentServeDto> serviceStudents;
            if(sunDayDate.isBefore(LocalDate.now())){
                serviceStudents = studentDao.getBeServiceStudentsInfoWithStudentsForHistory(monDayDate.toString(), nextMonday,studentIds);
            }else{
                serviceStudents = studentDao.getBeServiceStudentsInfoWithStudents(monDayDate.toString(), new Date(),studentIds);
            }
            if(CollectionUtils.isEmpty(serviceStudents)){
                return;
            }

            Map<Integer, List<StudentServeDto>> studentCoursesMap = serviceStudents.stream().collect(Collectors.groupingBy(StudentServeDto::getUserId));

            //本周不服务学员列表
            Set<Integer> dontServeInCurrentWeekStudentIds=new HashSet<>();
            //本周有课学员编号集合
            Set<Integer> haveClassStudentIds=new HashSet<>();
            //本周无课学员编号集合
            Set<Integer> noClassStudentIds=new HashSet<>();
            for (Map.Entry<Integer, List<StudentServeDto>> studentCoursesEntry : studentCoursesMap.entrySet()) {

                List<StudentServeDto> haveCourseStudents = studentCoursesEntry.getValue().stream().filter(e -> Objects.nonNull(e.getCourseStartTime())).collect(Collectors.toList());
                if(CollectionUtils.isEmpty(haveCourseStudents)){
                    noClassStudentIds.add(studentCoursesEntry.getKey());
                    continue;
                }
                StudentServeDto studentServeDto = haveCourseStudents.stream().min(Comparator.comparing(StudentServeDto::getCourseStartTime)).get();
                if(Objects.isNull(studentServeDto.getCourseStartTime())){
                    noClassStudentIds.add(studentCoursesEntry.getKey());
                    continue;
                }
                if(!studentServeDto.getCourseStartTime().before(nextMonday)){
                    dontServeInCurrentWeekStudentIds.add(studentCoursesEntry.getKey());
                    continue;
                }
                long count = haveCourseStudents.stream().filter(e -> (GroupType.PRACTICE.equals(e.getGroupType()) ||
                        GroupType.VIP.equals(e.getGroupType()))
                        &&nextMonday.after(e.getCourseStartTime())).count();
                if(count>0){
                    haveClassStudentIds.add(studentCoursesEntry.getKey());
                }else{
                    noClassStudentIds.add(studentCoursesEntry.getKey());
                }
            }

            Set<Integer> allServeStudentIds=new HashSet<>();
            allServeStudentIds.addAll(haveClassStudentIds);
            allServeStudentIds.addAll(noClassStudentIds);

            Map<Integer, List<StudentServeCourseHomeworkDto>> studentHomeworkMap=new HashMap<>();
            Map<Integer, List<ExtracurricularExercisesReply>> studentExercisesMap=new HashMap<>();

            if (!CollectionUtils.isEmpty(allServeStudentIds)){
                List<StudentServeCourseHomeworkDto> studentHomeworks = studentCourseHomeworkDao.findStudentHomeworkWithCourseDateRange(monDayDate.toString(), sunDayDate.toString(), new ArrayList<>(allServeStudentIds));
                List<StudentServeCourseHomeworkDto> studentHomeworksTmp =new ArrayList<>();
                for (StudentServeCourseHomeworkDto studentHomework : studentHomeworks) {
                    LocalDate courseStartLocalDate = LocalDateTime.ofInstant(studentHomework.getCourseStartTime().toInstant(), DateUtil.zoneId).toLocalDate();
                    switch (courseStartLocalDate.getDayOfWeek()){
                        case SATURDAY:
                            if(DateUtil.daysBetween(studentHomework.getCourseStartTime(), studentHomework.getHomeworkCreateTime())<4){
                                studentHomeworksTmp.add(studentHomework);
                            }
                            break;
                        case SUNDAY:
                            if(DateUtil.daysBetween(studentHomework.getCourseStartTime(), studentHomework.getHomeworkCreateTime())<3){
                                studentHomeworksTmp.add(studentHomework);
                            }
                            break;
                        default:
                            LocalDate homeworkCreateTime = LocalDateTime.ofInstant(studentHomework.getHomeworkCreateTime().toInstant(), DateUtil.zoneId).toLocalDate();
                            if(courseStartLocalDate.get(DateUtil.weekFields.weekOfYear())==homeworkCreateTime.get(DateUtil.weekFields.weekOfYear())){
                                studentHomeworksTmp.add(studentHomework);
                            }
                            break;
                    }
                }
                studentHomeworkMap = studentHomeworksTmp.stream()
                        .collect(Collectors.groupingBy(StudentServeCourseHomeworkDto::getUserId));
            }

            if(!CollectionUtils.isEmpty(allServeStudentIds)){
                List<ExtracurricularExercisesReply> studentExercises = extracurricularExercisesReplyDao.getStudentExercisesWithTimeZone(monDayDate.toString(), sunDayDate.toString(), new ArrayList<>(allServeStudentIds), TenantContextHolder.getTenantId());
                studentExercisesMap = studentExercises.stream().collect(Collectors.groupingBy(ExtracurricularExercisesReply::getUserId));
            }

            for (Map.Entry<Integer, List<StudentServeDto>> studentCoursesEntry : studentCoursesMap.entrySet()) {

                if(dontServeInCurrentWeekStudentIds.contains(studentCoursesEntry.getKey())){
                    continue;
                }

                StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation();
                studentExtracurricularExercisesSituation.setStudentId(studentCoursesEntry.getKey());
                studentExtracurricularExercisesSituation.setTeacherId(studentCoursesEntry.getValue().get(0).getTeacherId());
                studentExtracurricularExercisesSituation.setExpectExercisesNum(1);
                studentExtracurricularExercisesSituation.setActualExercisesNum(0);
                studentExtracurricularExercisesSituation.setExercisesReplyNum(0);
                studentExtracurricularExercisesSituation.setExercisesMessageNum(0);
                studentExtracurricularExercisesSituation.setExercisesMessageTimelyNum(0);
                studentExtracurricularExercisesSituation.setWeekOfYear(nowDate.get(DateUtil.weekFields.weekOfYear()));
                studentExtracurricularExercisesSituation.setMonday(DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"));
                studentExtracurricularExercisesSituation.setSunday(DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"));

                if(haveClassStudentIds.contains(studentCoursesEntry.getKey())){
                    studentExtracurricularExercisesSituation.setServeType("HOMEWORK");
                }

                if(noClassStudentIds.contains(studentCoursesEntry.getKey())){
                    studentExtracurricularExercisesSituation.setServeType("EXERCISE");
                }

                List<StudentServeCourseHomeworkDto> studentHomeworks = studentHomeworkMap.get(studentCoursesEntry.getKey());
                if(!CollectionUtils.isEmpty(studentHomeworks)){
                    studentExtracurricularExercisesSituation.setActualExercisesNum(1);
                    long replyNum = studentHomeworks.stream().filter(e -> YesOrNoEnum.YES.equals(e.getStatus())).count();
                    studentExtracurricularExercisesSituation.setExercisesReplyNum(replyNum>0?1:0);
                    long haveSubmitTimes = studentHomeworks.stream().filter(e -> Objects.nonNull(e.getSubmitTime())).count();
                    if(replyNum>0&&haveSubmitTimes>0){
                        Date lastSubmitTime = studentHomeworks.stream().filter(e->Objects.nonNull(e.getSubmitTime())).max(Comparator.comparing(StudentServeCourseHomeworkDto::getSubmitTime)).get().getSubmitTime();
                        studentExtracurricularExercisesSituation.setLastSubmitTime(lastSubmitTime);
                    }
                    int exercisesMessageNum=0;
                    int exercisesMessageTimelyNum=0;
                    for (StudentServeCourseHomeworkDto studentHomework : studentHomeworks) {
                        if(!YesOrNoEnum.YES.equals(studentHomework.getStatus())){
                            continue;
                        }
                        if(!YesOrNoEnum.YES.equals(studentHomework.getIsReplied())){
                            continue;
                        }
                        exercisesMessageNum+=1;
                        if(new Integer(1).equals(studentHomework.getIsRepliedTimely())){
                            exercisesMessageTimelyNum+=1;
                        }
                    }
                    studentExtracurricularExercisesSituation.setExercisesMessageNum(exercisesMessageNum>0?1:0);
                    studentExtracurricularExercisesSituation.setExercisesMessageTimelyNum(exercisesMessageTimelyNum>0?1:0);
                }

                List<ExtracurricularExercisesReply> studentExercises = studentExercisesMap.get(studentCoursesEntry.getKey());
                if(!CollectionUtils.isEmpty(studentExercises)){
                    studentExtracurricularExercisesSituation.setActualExercisesNum(1);
                    long replyNum = studentExercises.stream().filter(e -> e.getStatus()==1).count();
                    if(studentExtracurricularExercisesSituation.getExercisesReplyNum()<=0){
                        studentExtracurricularExercisesSituation.setExercisesReplyNum(replyNum>0?1:0);
                    }
                    long haveSubmitTimes = studentExercises.stream().filter(e->Objects.nonNull(e.getSubmitTime())).count();
                    if(replyNum>0&&haveSubmitTimes>0){
                        Date lastSubmitTime = studentExercises.stream().filter(e->Objects.nonNull(e.getSubmitTime())).max(Comparator.comparing(ExtracurricularExercisesReply::getSubmitTime)).get().getSubmitTime();
                        if(Objects.isNull(studentExtracurricularExercisesSituation.getLastSubmitTime())||lastSubmitTime.after(studentExtracurricularExercisesSituation.getLastSubmitTime())){
                            studentExtracurricularExercisesSituation.setLastSubmitTime(lastSubmitTime);
                        }
                    }
                    int exercisesMessageNum=0;
                    int exercisesMessageTimelyNum=0;
                    for (ExtracurricularExercisesReply studentHomework : studentExercises) {
                        if(!new Integer(1).equals(studentHomework.getStatus())){
                            continue;
                        }
                        if(!new Integer(1).equals(studentHomework.getIsReplied())){
                            continue;
                        }
                        exercisesMessageNum+=1;
                        if(new Integer(1).equals(studentHomework.getIsRepliedTimely())){
                            exercisesMessageTimelyNum+=1;
                        }
                    }
                    if(studentExtracurricularExercisesSituation.getExercisesMessageNum()<=0){
                        studentExtracurricularExercisesSituation.setExercisesMessageNum(exercisesMessageNum>0?1:0);
                    }
                    if(studentExtracurricularExercisesSituation.getExercisesMessageTimelyNum()<=0){
                        studentExtracurricularExercisesSituation.setExercisesMessageTimelyNum(exercisesMessageTimelyNum>0?1:0);
                    }
                }
                results.add(studentExtracurricularExercisesSituation);
            }

            currentPage=currentPage.add(BigDecimal.ONE);
        }

        studentExtracurricularExercisesSituationService.deleteByMonday(monDayDate.toString(), null);

        BigDecimal currentPage1=BigDecimal.ONE,
                pageSize1=new BigDecimal(10000),
                total1=new BigDecimal(results.size()),
                totalPage1=total1.divide(pageSize1, BigDecimal.ROUND_UP);

        while (currentPage1.compareTo(totalPage1)<=0){
            List<StudentExtracurricularExercisesSituation> rows=results.stream().skip(pageSize1.multiply(currentPage1.subtract(BigDecimal.ONE)).longValue()).limit(pageSize1.longValue()).collect(Collectors.toList());
            studentExtracurricularExercisesSituationService.batchInsert(rows);
            currentPage1=currentPage1.add(BigDecimal.ONE);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exercisesSituationStatistics2(String monday, Integer tenantId) {
        LocalDate nowDate = LocalDateTime.now(DateUtil.zoneId).toLocalDate();
        
        //统计上周的服务指标总数
        int preWeekServiceNum = studentExtracurricularExercisesSituationDao.countWeekServiceNum(nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue()).plusDays(-7).toString(), tenantId);
        
        //统计上周数据今日更新的条数
        int lastWeekTodayUpdateNum = studentExtracurricularExercisesSituationDao.findLastWeekTodayUpdateNum(nowDate.plusDays(-nowDate.getDayOfWeek().getValue()).toString(), tenantId);
        
        if(preWeekServiceNum>0 && lastWeekTodayUpdateNum<=0){
            nowDate = nowDate.plusDays(-nowDate.getDayOfWeek().getValue());
        }

        if(StringUtils.isNotBlank(monday)){
            nowDate=LocalDate.parse(monday, DateUtil.dateFormatter);
        }

        LocalDate monDayDate = nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
        LocalDate sunDayDate = nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.SUNDAY.getValue());
        Date nextMonday = Date.from(sunDayDate.plusDays(1).atStartOfDay(DateUtil.zoneId).toInstant());
        
        /**
         * 学员在读才生成服务指标，若本周有声部课或合奏课，则布置课后训练；否则，布置课外训练（课外训练看是指定由哪个班级的老师来布置）
         * 学员在每一个进行中的乐团，且已开始上课都需要布置作业
         */
        
        //查询进行中乐团在读的学生列表
        List<StudentRegistration> studentRegistrationList = studentRegistrationDao.queryServiceStudentByMusicGroupStatus(DateUtil.dateToString(nextMonday, "yyyy-MM-dd"), tenantId);
        if(studentRegistrationList == null || studentRegistrationList.size() == 0){
        	return;
        }
        
        Map<String,List<Integer>> musicGroupStudentMap = studentRegistrationList.stream().collect(Collectors.groupingBy(StudentRegistration :: getMusicGroupId, Collectors.mapping(StudentRegistration :: getUserId, Collectors.toList())));
        
        List<Integer> studentIds = studentRegistrationList.stream().map(t -> t.getUserId()).distinct().collect(Collectors.toList());

        Set<String> holidayDays = new HashSet<>();
        String holidaySetting = sysTenantConfigService.getTenantConfigValue(SysConfigService.HOLIDAY_SETTING,tenantId);
        if(StringUtils.isNotBlank(holidaySetting)){
            holidayDays = new HashSet<>(JSON.parseArray(holidaySetting, String.class));
        }
        LocalDate everyDay=monDayDate;
        boolean weekInHoliday = true;
        while (everyDay.compareTo(sunDayDate)<=0){
            if(!holidayDays.contains(everyDay.toString())){
                weekInHoliday = false;
                break;
            }
            everyDay = everyDay.plusDays(1);
        }

        //节假日不产生服务指标
        if(weekInHoliday){
            studentExtracurricularExercisesSituationService.deleteByMonday(monDayDate.toString(), studentIds);
            return;
        }
        
        //查询截止到本周有课的信息
        List<StudentServeCourseDto> studentCutoffWeekCourseInfo = studentDao.getStudentFutureCourseInfo("2019-01-01", sunDayDate.toString(), studentIds, tenantId);
        
        Map<String,List<Integer>> musicGroupStudentIdListMap = new HashMap<String, List<Integer>>();
        
        Map<String, List<StudentServeCourseDto>> musicGroupStudentServiceCourseMap = studentCutoffWeekCourseInfo.stream().collect((Collectors.groupingBy(StudentServeCourseDto::getMusicGroupId)));
        //学员在单乐团中课程去重
        for(Entry<String, List<StudentServeCourseDto>> entry : musicGroupStudentServiceCourseMap.entrySet()){
        	musicGroupStudentIdListMap.put(entry.getKey(), entry.getValue().stream().map(t -> t.getStudentId()).distinct().collect(Collectors.toList()));
        }
        
        //查询本周有声部或合奏的学生
        List<StudentServeCourseDto> studentCurrentWeekCourseInfo = studentDao.getStudentFutureCourseInfo(monDayDate.toString(), sunDayDate.toString(), studentIds, tenantId);
        Map<String, List<StudentServeCourseDto>> studentCurrentWeekCourseMap = studentCurrentWeekCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getMusicGroupId));
        
        //本周学生在不同乐团中上的第一节课
        Map<String,Map<Integer,StudentServeCourseDto>> musicGroupStudentCurrentWeekCourseMap = new HashMap<String, Map<Integer,StudentServeCourseDto>>();
        
        Map<Integer,List<StudentServeCourseDto>> userCourseListMap = null;
        Map<Integer,StudentServeCourseDto> userCourseMap = null;
        String musicGroupId = null;
        Optional<StudentServeCourseDto> optional = null;
        
        //查询学生在乐团中的第一节课
        for(Entry<String, List<StudentServeCourseDto>> entry : studentCurrentWeekCourseMap.entrySet()){
        	musicGroupId = entry.getKey();
        	
        	userCourseMap = musicGroupStudentCurrentWeekCourseMap.get(musicGroupId);
        	if(userCourseMap == null){
        		userCourseMap = new HashMap<Integer, StudentServeCourseDto>();
        	}
        	//获取学生本周所有课程
        	userCourseListMap = entry.getValue().stream().collect(Collectors.groupingBy(StudentServeCourseDto :: getStudentId));
        	
        	for(Entry<Integer, List<StudentServeCourseDto>> stuCourseListEntry : userCourseListMap.entrySet()){
            	//获取学生本周第一节课
        		optional = stuCourseListEntry.getValue().stream().filter(dto -> (dto.getType() == CourseScheduleType.SINGLE || dto.getType() == CourseScheduleType.TRAINING_SINGLE)).min(Comparator.comparing(StudentServeCourseDto::getCourseStartTime));
        		if(optional.isPresent()){
        			userCourseMap.put(stuCourseListEntry.getKey(), optional.get());
        		}else{
        			userCourseMap.put(stuCourseListEntry.getKey(), stuCourseListEntry.getValue().stream().min(Comparator.comparing(StudentServeCourseDto::getCourseStartTime)).get());
        		}
        	}
    		musicGroupStudentCurrentWeekCourseMap.put(musicGroupId, userCourseMap);
        }
        
        StudentServeCourseDto studentServeCourseDto = null;
        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation = null;
        List<StudentExtracurricularExercisesSituation> results=new ArrayList<StudentExtracurricularExercisesSituation>();
        
        Map<Integer,Map<Integer,Set<Long>>> studentTeacherCourseMap = new HashMap<Integer, Map<Integer,Set<Long>>>();
        Map<Integer,Map<Integer,Set<Long>>> studentTeacherNotOverCourseMap = new HashMap<Integer, Map<Integer,Set<Long>>>();
        Map<Integer,Map<Integer,Integer>> studentTeacherCourseNumMap = new HashMap<Integer, Map<Integer,Integer>>();
		
		Map<Integer, Set<Long>> teacherCourseMap = null;
		Map<Integer, Set<Long>> teacherNotOverCourseMap = null;
		Integer teacherId = null;
		Set<Long> courseIdList = null;
		ClassGroupTypeEnum teacherType;
		Map<Integer,Integer> teacherCourseNumMap = null;
		List<Integer> musicGroupStudentIdList = null;
        
        //理论上一个学生一个乐团只布置一次作业
		for (Entry<String, List<Integer>> entry : musicGroupStudentIdListMap.entrySet()) {
			
			musicGroupId = entry.getKey();
			
			musicGroupStudentIdList = musicGroupStudentMap.get(musicGroupId);
			
			MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
			if(musicGroup == null || musicGroup.getStatus() != MusicGroupStatusEnum.PROGRESS){
				continue;
			}
			Map<Integer,Integer> studentTeacherMapper = null;
			
			teacherType = musicGroup.getExtracurricularTeacher() == null ? ClassGroupTypeEnum.NORMAL : musicGroup.getExtracurricularTeacher();
			List<ClassGroupStudentMapperDto> classGroupStudentMapperDtoList = classGroupStudentMapperDao.queryByClassGroupType(musicGroupId, teacherType, TeachTypeEnum.BISHOP, entry.getValue());
			if(classGroupStudentMapperDtoList != null){
				studentTeacherMapper = classGroupStudentMapperDtoList.stream().collect(Collectors.toMap(ClassGroupStudentMapperDto :: getUserId, ClassGroupStudentMapperDto :: getTeacherId));
			}
			
			userCourseMap = musicGroupStudentCurrentWeekCourseMap.get(musicGroupId);
			
			for(Integer studentId : entry.getValue()){
				
				if(musicGroupStudentIdList == null || musicGroupStudentIdList.contains(studentId) == false){
					continue;
				}
				
				//在当前乐团，学生本周是否有课
				if(userCourseMap == null || userCourseMap.get(studentId) == null){//如果本周没课
					
					if(studentTeacherMapper == null || (teacherId = studentTeacherMapper.get(studentId)) == null){
						continue;
					}
					
					teacherCourseNumMap = studentTeacherCourseNumMap.get(studentId);
					if(teacherCourseNumMap == null){
						teacherCourseNumMap = new HashMap<Integer, Integer>();
					}
					teacherCourseNumMap.put(teacherId, teacherCourseNumMap.get(teacherId) == null ? 1 : teacherCourseNumMap.get(teacherId) + 1);
					studentTeacherCourseNumMap.put(studentId, teacherCourseNumMap);
					
					//本周没有课，布置课外训练
					studentExtracurricularExercisesSituation = new StudentExtracurricularExercisesSituation(studentId, teacherId,
							nowDate.get(DateUtil.weekFields.weekOfYear()), DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(
									sunDayDate.toString(), "yyyy-MM-dd"), "EXERCISE", null);
					
					
					studentExtracurricularExercisesSituation.setExpectExercisesNum(teacherCourseNumMap.get(teacherId));
					if(results.contains(studentExtracurricularExercisesSituation)){
						results.remove(studentExtracurricularExercisesSituation);
					}
					results.add(studentExtracurricularExercisesSituation);
				}else{//如果本周有课

					studentServeCourseDto = userCourseMap.get(studentId);
					teacherId = studentServeCourseDto.getActualTeacherId();
					
					teacherCourseMap = studentTeacherCourseMap.get(studentId);
					if(teacherCourseMap == null){
						teacherCourseMap = new HashMap<Integer, Set<Long>>();
					}
					courseIdList = teacherCourseMap.get(teacherId);
					if(courseIdList == null){
						courseIdList = new HashSet<Long>();
					}
					courseIdList.add(studentServeCourseDto.getCourseScheduleId());
					teacherCourseMap.put(teacherId, courseIdList);
					studentTeacherCourseMap.put(studentId, teacherCourseMap);
					
					studentExtracurricularExercisesSituation = new StudentExtracurricularExercisesSituation(studentId, teacherId,
							nowDate.get(DateUtil.weekFields.weekOfYear()), DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(
									sunDayDate.toString(), "yyyy-MM-dd"), "HOMEWORK", StringUtils.join(courseIdList, ","));
                    studentExtracurricularExercisesSituation.setExpectExercisesNum(courseIdList.size());
                    
                    teacherNotOverCourseMap = studentTeacherNotOverCourseMap.get(studentId);
					if(teacherNotOverCourseMap == null){
						teacherNotOverCourseMap = new HashMap<Integer, Set<Long>>();
					}
					courseIdList = teacherNotOverCourseMap.get(teacherId);
					if(courseIdList == null){
						courseIdList = new HashSet<Long>();
					}
                    if(studentServeCourseDto.getStatus() != CourseStatusEnum.OVER){
    					courseIdList.add(studentServeCourseDto.getCourseScheduleId());
    					teacherNotOverCourseMap.put(teacherId, courseIdList);
    					studentTeacherNotOverCourseMap.put(studentId, teacherCourseMap);
                    }
                    
                    studentExtracurricularExercisesSituation.setNotOverCourseIds(StringUtils.join(courseIdList, ","));
                    studentExtracurricularExercisesSituation.setNotOverCourseNum(courseIdList.size());
					if(results.contains(studentExtracurricularExercisesSituation)){
						results.remove(studentExtracurricularExercisesSituation);
					}
                    results.add(studentExtracurricularExercisesSituation);
				}
			}
			
		}

        if(!CollectionUtils.isEmpty(results)){
            List<Integer> allStudentIds = new ArrayList<>();
            allStudentIds = results.stream().map(StudentExtracurricularExercisesSituation::getStudentId).collect(Collectors.toList());

            Map<Integer, List<StudentServeCourseHomeworkDto>> studentHomeworkMap=new HashMap<>();
            Map<Integer, List<ExtracurricularExercisesReply>> studentExercisesMap=new HashMap<>();

            List<StudentServeCourseHomeworkDto> allStudentHomeworks = studentCourseHomeworkDao.findStudentHomeworkWithCourseDateRange(monDayDate.toString(), sunDayDate.toString(), new ArrayList<>(allStudentIds));
            List<StudentServeCourseHomeworkDto> studentHomeworksTmp =new ArrayList<>();
            for (StudentServeCourseHomeworkDto studentHomework : allStudentHomeworks) {
                LocalDate courseStartLocalDate = LocalDateTime.ofInstant(studentHomework.getCourseStartTime().toInstant(), DateUtil.zoneId).toLocalDate();
                switch (courseStartLocalDate.getDayOfWeek()){
                    case SATURDAY:
                        if(DateUtil.daysBetween(studentHomework.getCourseStartTime(), studentHomework.getHomeworkCreateTime())<4){
                            studentHomeworksTmp.add(studentHomework);
                        }
                        break;
                    case SUNDAY:
                        if(DateUtil.daysBetween(studentHomework.getCourseStartTime(), studentHomework.getHomeworkCreateTime())<3){
                            studentHomeworksTmp.add(studentHomework);
                        }
                        break;
                    default:
                        LocalDate homeworkCreateTime = LocalDateTime.ofInstant(studentHomework.getHomeworkCreateTime().toInstant(), DateUtil.zoneId).toLocalDate();
                        if(courseStartLocalDate.get(DateUtil.weekFields.weekOfYear())==homeworkCreateTime.get(DateUtil.weekFields.weekOfYear())){
                            studentHomeworksTmp.add(studentHomework);
                        }
                        break;
                }
            }
            if(!CollectionUtils.isEmpty(studentHomeworksTmp)){
                studentHomeworkMap = studentHomeworksTmp.stream()
                        .collect(Collectors.groupingBy(StudentServeCourseHomeworkDto::getUserId));
            }

            List<ExtracurricularExercisesReply> allStudentExercises = extracurricularExercisesReplyDao.getStudentExercisesWithTimeZone(monDayDate.toString(), sunDayDate.toString(), new ArrayList<>(allStudentIds), tenantId);
            if(!CollectionUtils.isEmpty(allStudentExercises)){
                studentExercisesMap = allStudentExercises.stream().collect(Collectors.groupingBy(ExtracurricularExercisesReply::getUserId));
            }

            for (StudentExtracurricularExercisesSituation weekServiceWithStudent : results) {
                List<StudentServeCourseHomeworkDto> studentAllHomeworks = studentHomeworkMap.get(weekServiceWithStudent.getStudentId());
                weekServiceWithStudent.setActualExercisesNum(0);
                if(!CollectionUtils.isEmpty(studentAllHomeworks)&&weekServiceWithStudent.getServeType().equals("HOMEWORK")){
                    Set<String> courseIds = Arrays.stream(weekServiceWithStudent.getCourseIds().split(",")).collect(Collectors.toSet());
                    List<StudentServeCourseHomeworkDto> studentHomeworks = studentAllHomeworks.stream().filter(s -> courseIds.contains(s.getCourseScheduleId().toString())).collect(Collectors.toList());
                    if(!CollectionUtils.isEmpty(studentHomeworks)){
                        weekServiceWithStudent.setActualExercisesNum(studentHomeworks.size()>weekServiceWithStudent.getExpectExercisesNum()?weekServiceWithStudent.getExpectExercisesNum():studentHomeworks.size());
                        long replyNum = studentHomeworks.stream().filter(e -> YesOrNoEnum.YES.equals(e.getStatus())).count();
                        weekServiceWithStudent.setExercisesReplyNum(replyNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) replyNum);
                        long haveSubmitTimes = studentHomeworks.stream().filter(e -> Objects.nonNull(e.getSubmitTime())).count();
                        if(replyNum>0&&haveSubmitTimes>0){
                            Date lastSubmitTime = studentHomeworks.stream().filter(e->Objects.nonNull(e.getSubmitTime())).max(Comparator.comparing(StudentServeCourseHomeworkDto::getSubmitTime)).get().getSubmitTime();
                            weekServiceWithStudent.setLastSubmitTime(lastSubmitTime);
                        }
                        int exercisesMessageNum=0;
                        int exercisesMessageTimelyNum=0;
                        for (StudentServeCourseHomeworkDto studentHomework : studentHomeworks) {
                            if(!YesOrNoEnum.YES.equals(studentHomework.getStatus())){
                                continue;
                            }
                            if(!YesOrNoEnum.YES.equals(studentHomework.getIsReplied())){
                                continue;
                            }
                            exercisesMessageNum+=1;
                            if(new Integer(1).equals(studentHomework.getIsRepliedTimely())){
                                exercisesMessageTimelyNum+=1;
                            }
                        }
                        weekServiceWithStudent.setExercisesMessageNum(exercisesMessageNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) exercisesMessageNum);
                        weekServiceWithStudent.setExercisesMessageTimelyNum(exercisesMessageTimelyNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) exercisesMessageNum);
                    }
                }

                List<ExtracurricularExercisesReply> studentAllExercises = studentExercisesMap.get(weekServiceWithStudent.getStudentId());
                if(!CollectionUtils.isEmpty(studentAllExercises)&&weekServiceWithStudent.getServeType().equals("EXERCISE")){
                    List<ExtracurricularExercisesReply> studentExercises = studentAllExercises.stream().filter(s -> weekServiceWithStudent.getTeacherId().equals(s.getExtracurricularExercises().getTeacherId())).collect(Collectors.toList());
                    if(!CollectionUtils.isEmpty(studentExercises)){
                        weekServiceWithStudent.setActualExercisesNum(studentExercises.size()>weekServiceWithStudent.getExpectExercisesNum()?weekServiceWithStudent.getExpectExercisesNum():studentExercises.size());
                        long replyNum = studentExercises.stream().filter(e -> e.getStatus()==1).count();
                        if(weekServiceWithStudent.getExercisesReplyNum()<weekServiceWithStudent.getActualExercisesNum()){
                            weekServiceWithStudent.setExercisesReplyNum(replyNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) replyNum);
                        }
                        long haveSubmitTimes = studentExercises.stream().filter(e->Objects.nonNull(e.getSubmitTime())).count();
                        if(replyNum>0&&haveSubmitTimes>0){
                            Date lastSubmitTime = studentExercises.stream().filter(e->Objects.nonNull(e.getSubmitTime())).max(Comparator.comparing(ExtracurricularExercisesReply::getSubmitTime)).get().getSubmitTime();
                            if(Objects.isNull(weekServiceWithStudent.getLastSubmitTime())||lastSubmitTime.after(weekServiceWithStudent.getLastSubmitTime())){
                                weekServiceWithStudent.setLastSubmitTime(lastSubmitTime);
                            }
                        }
                        int exercisesMessageNum=0;
                        int exercisesMessageTimelyNum=0;
                        for (ExtracurricularExercisesReply studentHomework : studentExercises) {
                            if(!new Integer(1).equals(studentHomework.getStatus())){
                                continue;
                            }
                            if(!new Integer(1).equals(studentHomework.getIsReplied())){
                                continue;
                            }
                            exercisesMessageNum+=1;
                            if(new Integer(1).equals(studentHomework.getIsRepliedTimely())){
                                exercisesMessageTimelyNum+=1;
                            }
                        }
                        if(weekServiceWithStudent.getExercisesMessageNum()<weekServiceWithStudent.getActualExercisesNum()){
                            weekServiceWithStudent.setExercisesMessageNum(exercisesMessageNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) exercisesMessageNum);
                        }
                        if(weekServiceWithStudent.getExercisesMessageTimelyNum()<weekServiceWithStudent.getActualExercisesNum()){
                            weekServiceWithStudent.setExercisesMessageTimelyNum(exercisesMessageTimelyNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) exercisesMessageTimelyNum);
                        }
                    }
                }
            }

            studentExtracurricularExercisesSituationService.deleteByMonday(monDayDate.toString(), null);

            BigDecimal currentPage1=BigDecimal.ONE,
                    pageSize1=new BigDecimal(10000),
                    total1=new BigDecimal(results.size()),
                    totalPage1=total1.divide(pageSize1, BigDecimal.ROUND_UP);

            while (currentPage1.compareTo(totalPage1)<=0){
                List<StudentExtracurricularExercisesSituation> rows=results.stream().skip(pageSize1.multiply(currentPage1.subtract(BigDecimal.ONE)).longValue()).limit(pageSize1.longValue()).collect(Collectors.toList());

                studentExtracurricularExercisesSituationService.batchInsert(rows);

                currentPage1=currentPage1.add(BigDecimal.ONE);
            }
            return;
        }
    }

    @Override
    public void updateExercisesSituation(Date date,List<Integer> studentIds, Integer teacherId) {
//        if(true){
//            return;
//        }
        LocalDate nowDate = LocalDateTime.ofInstant(date.toInstant(), DateUtil.zoneId).toLocalDate();
        if(Objects.isNull(date)){
            nowDate = LocalDateTime.now(DateUtil.zoneId).toLocalDate();
        }

        LocalDate monDayDate = nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
        LocalDate sunDayDate = nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.SUNDAY.getValue());

        Map<Integer, List<StudentServeCourseHomeworkDto>> studentHomeworkMap=new HashMap<>();
        Map<Integer, List<ExtracurricularExercisesReply>> studentExercisesMap=new HashMap<>();

        List<StudentServeCourseHomeworkDto> allStudentHomeworks = studentCourseHomeworkDao.findStudentHomeworkWithCourseDateRange(monDayDate.toString(), sunDayDate.toString(), new ArrayList<>(studentIds));
        List<StudentServeCourseHomeworkDto> studentHomeworksTmp =new ArrayList<>();
        for (StudentServeCourseHomeworkDto studentHomework : allStudentHomeworks) {
            LocalDate courseStartLocalDate = LocalDateTime.ofInstant(studentHomework.getCourseStartTime().toInstant(), DateUtil.zoneId).toLocalDate();
            switch (courseStartLocalDate.getDayOfWeek()){
                case SATURDAY:
                    if(DateUtil.daysBetween(studentHomework.getCourseStartTime(), studentHomework.getHomeworkCreateTime())<4){
                        studentHomeworksTmp.add(studentHomework);
                    }
                    break;
                case SUNDAY:
                    if(DateUtil.daysBetween(studentHomework.getCourseStartTime(), studentHomework.getHomeworkCreateTime())<3){
                        studentHomeworksTmp.add(studentHomework);
                    }
                    break;
                default:
                    LocalDate homeworkCreateTime = LocalDateTime.ofInstant(studentHomework.getHomeworkCreateTime().toInstant(), DateUtil.zoneId).toLocalDate();
                    if(courseStartLocalDate.get(DateUtil.weekFields.weekOfYear())==homeworkCreateTime.get(DateUtil.weekFields.weekOfYear())){
                        studentHomeworksTmp.add(studentHomework);
                    }
                    break;
            }
        }
        if(!CollectionUtils.isEmpty(studentHomeworksTmp)){
            studentHomeworkMap = studentHomeworksTmp.stream()
                    .collect(Collectors.groupingBy(StudentServeCourseHomeworkDto::getUserId));
        }


        List<ExtracurricularExercisesReply> allStudentExercises = extracurricularExercisesReplyDao.getStudentExercisesWithTimeZone(monDayDate.toString(), sunDayDate.toString(), new ArrayList<>(studentIds), TenantContextHolder.getTenantId());
        if(!CollectionUtils.isEmpty(allStudentExercises)){
            studentExercisesMap = allStudentExercises.stream().collect(Collectors.groupingBy(ExtracurricularExercisesReply::getUserId));
        }

        List<StudentExtracurricularExercisesSituation> weekServiceWithStudents = studentExtracurricularExercisesSituationDao.findWeekServiceWithStudents(monDayDate.toString(), teacherId, studentIds);
        if(CollectionUtils.isEmpty(weekServiceWithStudents)){
            return;
        }

        for (StudentExtracurricularExercisesSituation weekServiceWithStudent : weekServiceWithStudents) {
            List<StudentServeCourseHomeworkDto> studentAllHomeworks = studentHomeworkMap.get(weekServiceWithStudent.getStudentId());
            weekServiceWithStudent.setActualExercisesNum(0);
            if(!CollectionUtils.isEmpty(studentAllHomeworks)&&weekServiceWithStudent.getServeType().equals("HOMEWORK")&&StringUtils.isNotBlank(weekServiceWithStudent.getCourseIds())){
                Set<String> courseIds = Arrays.stream(weekServiceWithStudent.getCourseIds().split(",")).collect(Collectors.toSet());
                List<StudentServeCourseHomeworkDto> studentHomeworks = studentAllHomeworks.stream().filter(s -> courseIds.contains(s.getCourseScheduleId().toString())).collect(Collectors.toList());
                if(!CollectionUtils.isEmpty(studentHomeworks)){
                    weekServiceWithStudent.setActualExercisesNum(studentHomeworks.size()>weekServiceWithStudent.getExpectExercisesNum()?weekServiceWithStudent.getExpectExercisesNum():studentHomeworks.size());
                    long replyNum = studentHomeworks.stream().filter(e -> YesOrNoEnum.YES.equals(e.getStatus())).count();
                    weekServiceWithStudent.setExercisesReplyNum(replyNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) replyNum);
                    long haveSubmitTimes = studentHomeworks.stream().filter(e -> Objects.nonNull(e.getSubmitTime())).count();
                    if(replyNum>0&&haveSubmitTimes>0){
                        Date lastSubmitTime = studentHomeworks.stream().filter(e->Objects.nonNull(e.getSubmitTime())).max(Comparator.comparing(StudentServeCourseHomeworkDto::getSubmitTime)).get().getSubmitTime();
                        weekServiceWithStudent.setLastSubmitTime(lastSubmitTime);
                    }
                    int exercisesMessageNum=0;
                    int exercisesMessageTimelyNum=0;
                    for (StudentServeCourseHomeworkDto studentHomework : studentHomeworks) {
                        if(!YesOrNoEnum.YES.equals(studentHomework.getStatus())){
                            continue;
                        }
                        if(!YesOrNoEnum.YES.equals(studentHomework.getIsReplied())){
                            continue;
                        }
                        exercisesMessageNum+=1;
                        if(new Integer(1).equals(studentHomework.getIsRepliedTimely())){
                            exercisesMessageTimelyNum+=1;
                        }
                    }
                    weekServiceWithStudent.setExercisesMessageNum(exercisesMessageNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) exercisesMessageNum);
                    weekServiceWithStudent.setExercisesMessageTimelyNum(exercisesMessageTimelyNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) exercisesMessageTimelyNum);
                }
            }

            List<ExtracurricularExercisesReply> studentAllExercises = studentExercisesMap.get(weekServiceWithStudent.getStudentId());
            if(!CollectionUtils.isEmpty(studentAllExercises)&&weekServiceWithStudent.getServeType().equals("EXERCISE")){
                List<ExtracurricularExercisesReply> studentExercises = studentAllExercises.stream().filter(s -> weekServiceWithStudent.getTeacherId().equals(s.getExtracurricularExercises().getTeacherId())).collect(Collectors.toList());
                if(!CollectionUtils.isEmpty(studentExercises)){
                    weekServiceWithStudent.setActualExercisesNum(studentExercises.size()>weekServiceWithStudent.getExpectExercisesNum()?weekServiceWithStudent.getExpectExercisesNum():studentExercises.size());
                    long replyNum = studentExercises.stream().filter(e -> e.getStatus()==1).count();
                    if(weekServiceWithStudent.getExercisesReplyNum()<weekServiceWithStudent.getActualExercisesNum()){
                        weekServiceWithStudent.setExercisesReplyNum(replyNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) replyNum);
                    }
                    long haveSubmitTimes = studentExercises.stream().filter(e->Objects.nonNull(e.getSubmitTime())).count();
                    if(replyNum>0&&haveSubmitTimes>0){
                        Date lastSubmitTime = studentExercises.stream().filter(e->Objects.nonNull(e.getSubmitTime())).max(Comparator.comparing(ExtracurricularExercisesReply::getSubmitTime)).get().getSubmitTime();
                        if(Objects.isNull(weekServiceWithStudent.getLastSubmitTime())||lastSubmitTime.after(weekServiceWithStudent.getLastSubmitTime())){
                            weekServiceWithStudent.setLastSubmitTime(lastSubmitTime);
                        }
                    }
                    int exercisesMessageNum=0;
                    int exercisesMessageTimelyNum=0;
                    for (ExtracurricularExercisesReply studentHomework : studentExercises) {
                        if(!new Integer(1).equals(studentHomework.getStatus())){
                            continue;
                        }
                        if(!new Integer(1).equals(studentHomework.getIsReplied())){
                            continue;
                        }
                        exercisesMessageNum+=1;
                        if(new Integer(1).equals(studentHomework.getIsRepliedTimely())){
                            exercisesMessageTimelyNum+=1;
                        }
                    }
                    if(weekServiceWithStudent.getExercisesMessageNum()<weekServiceWithStudent.getActualExercisesNum()){
                        weekServiceWithStudent.setExercisesMessageNum(exercisesMessageNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) exercisesMessageNum);
                    }
                    if(weekServiceWithStudent.getExercisesMessageTimelyNum()<weekServiceWithStudent.getActualExercisesNum()){
                        weekServiceWithStudent.setExercisesMessageTimelyNum(exercisesMessageTimelyNum>weekServiceWithStudent.getActualExercisesNum()?weekServiceWithStudent.getActualExercisesNum(): (int) exercisesMessageTimelyNum);
                    }
                }
            }
        }
        studentExtracurricularExercisesSituationDao.batchUpdate(weekServiceWithStudents);
    }

    @Override
    public Map<String, Object> checkeIsAssignHomework(Long courseScheduleId, String studentIdsStr, Integer teacherId, Integer tenantId) {
        Map<String, Object> result=new HashMap<>();
        
        Set<Long> teacherServeCourseIds = studentServeService.getTeacherServeCourseIds(teacherId);
        if(teacherServeCourseIds.contains(courseScheduleId)){
            result.put("enableAssignHomework", 1);//是否要布置作业
        }else{
            result.put("enableAssignHomework", 0);
        }

        if(Objects.isNull(courseScheduleId) && Objects.isNull(studentIdsStr)){
            result.put("isAssignHomework", 0);//是否有布置作业
            return result;
        }

        List<Integer> studentIds=new ArrayList<>();
        if(StringUtils.isNotBlank(studentIdsStr)){
            studentIds= Arrays.asList(studentIdsStr.split(",")).stream().map(id->Integer.valueOf(id)).collect(Collectors.toList());
        }

        LocalDate localDate=LocalDate.now();

        if(Objects.nonNull(courseScheduleId)){
            List<BasicUserDto> students = courseScheduleStudentPaymentDao.findStudents(courseScheduleId);
            result.put("courseStudentNum", students.size());
            CourseSchedule courseSchedule = courseScheduleDao.get(courseScheduleId);
            if(Objects.isNull(courseSchedule)){
                throw new BizException("课程[{}]信息查询失败", courseScheduleId);
            }

            localDate=LocalDateTime.ofInstant(courseSchedule.getClassDate().toInstant(), DateUtil.zoneId).toLocalDate();
            List<CourseScheduleStudentPayment> courseScheduleStudentPayments = courseScheduleStudentPaymentDao.findByCourseSchedule(courseScheduleId);
            if(CollectionUtils.isEmpty(courseScheduleStudentPayments)){
                result.put("isAssignHomework", 0);
                return result;
            }
            studentIds = courseScheduleStudentPayments.stream().map(CourseScheduleStudentPayment::getUserId).collect(Collectors.toList());
        }

        LocalDate monDayDate = localDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
        LocalDate sunDayDate = localDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.SUNDAY.getValue());

		if (tenantId == 1) {
			// 课后作业
			Set<Integer> hss = studentCourseHomeworkDao.checkStudentHaveHomeworkInDateRange(monDayDate.toString(), sunDayDate.toString(), studentIds);
			// 课外训练
			for (Integer studentId : studentIds) {
				if (!hss.contains(studentId)) {
					result.put("isAssignHomework", 0);
					return result;
				}
			}
			result.put("isAssignHomework", 1);
		} else {
			if(courseScheduleId != null){
				List<Long> courseIds = new ArrayList<Long>();
				courseIds.add(courseScheduleId);
				
				List<StudentCourseHomework> courseHomeworkList = studentCourseHomeworkDao.findByCourses(courseIds);
				if (courseHomeworkList == null || courseHomeworkList.size() == 0) {
					result.put("isAssignHomework", 0);// 是否有布置作业
				} else {
					result.put("isAssignHomework", 1);// 是否有布置作业
				}
			}
		}
        return result;
    }

    @Override
    public Set<Long> getTeacherServeCourseIds(Integer teacherId) {
        List<StudentExtracurricularExercisesSituation> teacherNoStartServices = studentExtracurricularExercisesSituationDao.findTeacherNoStartServices(teacherId);
        List<String> courseIdsList = teacherNoStartServices.stream().filter(s->StringUtils.isNotBlank(s.getCourseIds())).map(StudentExtracurricularExercisesSituation::getCourseIds).collect(Collectors.toList());
        Set<Long> courseIds = new HashSet<>();
        for (String courseIdStr : courseIdsList) {
            courseIds.addAll(Arrays.stream(courseIdStr.split(",")).mapToLong(Long::valueOf).boxed().collect(Collectors.toSet()));
        }
        return courseIds;
    }

    @Override
    public Set<Long> getTeacherHomeworkCourseIdsWithMonday(Integer teacherId, Date date) {
        Set<Long> courseIds = new HashSet<>();
        if(Objects.isNull(teacherId)){
            return courseIds;
        }
        String mondayStr = null;
        if(Objects.nonNull(date)){
            Date monday = DateUtil.getWeekMondayWithDate(date);
            mondayStr = DateUtil.dateToString(monday, DateUtil.ISO_EXPANDED_DATE_FORMAT);
        }

        List<String> courseIdsStrs = studentExtracurricularExercisesSituationDao.getTeacherHomeworkCourseIdsWithMonday(teacherId, mondayStr);
        if(CollectionUtils.isEmpty(courseIdsStrs)){
            return courseIds;
        }
        for (String courseIdsStr : courseIdsStrs) {
            courseIds.addAll(Arrays.stream(courseIdsStr.split(",")).mapToLong(Long::valueOf).boxed().collect(Collectors.toSet()));
        }
        return courseIds;
    }

    @Override
    public Set<Integer> getStudentWithCourse(Long courseId) {
        CourseSchedule courseSchedule = courseScheduleDao.get(courseId);
        if(Objects.isNull(courseSchedule)){
            return new HashSet<>();
        }
        LocalDate nowDate = LocalDateTime.ofInstant(courseSchedule.getClassDate().toInstant(), DateUtil.zoneId).toLocalDate();

        LocalDate monDayDate = nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
        List<StudentExtracurricularExercisesSituation> serviceWithCourse = studentExtracurricularExercisesSituationDao.findServiceWithCourse(monDayDate.toString(), courseId);
        if(CollectionUtils.isEmpty(serviceWithCourse)){
            return new HashSet<>();
        }
        return serviceWithCourse.stream().map(StudentExtracurricularExercisesSituation::getStudentId).collect(Collectors.toSet());
    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeStudentServiceTag() {
        /**
         * 当前服务指标已开启，但在系统中没有剩余课时，且在乐团中不是在读状态，这种用户需要关闭服务指标
         */
        //获取需要关闭服务指标的学员
        List<Integer> studentIds = studentDao.queryCloseServiceTagIds();
        if(studentIds.size() > 0){
            studentDao.updateServiceTag(studentIds,0);
        }
    }

    @Override
    public void cleanStudentMember() {
        studentDao.cleanStudentMember();
        //试用会员清除
        studentDao.cleanExperienceStudentMember();
    }

    @Override
    public List<IndexBaseDto> musicGroupHomeworkStat(String musicGroupId, Integer studentId, String startDayStr, String endDayStr) {
    	if(StringUtils.isBlank(musicGroupId)){
    		throw new BizException("参数[乐团编号]错误");
    	}
    	
    	MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
    	
    	if(musicGroup == null){
    		throw new BizException("乐团[{}]信息不存在", musicGroupId);
    	}
    	
    	Integer tenantId = musicGroup.getTenantId();
    	
        List<IndexBaseDto> result = new ArrayList<>();
        List<StudentRegistration> musicGroupStu = studentRegistrationDao.getMusicGroupStu(musicGroupId);
        List<Integer> studentIds = new ArrayList<>();
        if(Objects.nonNull(studentId)){
            studentIds.add(studentId);
        }else if(!CollectionUtils.isEmpty(musicGroupStu)){
            studentIds = musicGroupStu.stream().map(StudentRegistration::getUserId).collect(Collectors.toList());
        }

        LocalDate startDate = LocalDate.parse(startDayStr, DateUtil.dateFormatter);
        LocalDate endDate = LocalDate.parse(endDayStr, DateUtil.dateFormatter);
        List<String> mondayDateStrs = new ArrayList<>();
        while (startDate.compareTo(endDate)<0){
            LocalDate monDayDate = startDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
            mondayDateStrs.add(monDayDate.toString());
            startDate = startDate.plusDays(7);
        }

        Map<IndexDataType, List<IndexBaseMonthData>> typeDateMap = new HashMap<>();

        List<IndexBaseMonthData> d1 = new ArrayList<>();
        List<IndexBaseMonthData> d2 = new ArrayList<>();
        List<IndexBaseMonthData> d3 = new ArrayList<>();
        if(StringUtils.isNotBlank(musicGroupId) && !CollectionUtils.isEmpty(studentIds)){
            d1 = studentExtracurricularExercisesSituationDao.getHomeworkData(startDayStr, endDayStr, musicGroupId,null, studentIds);
            d2 = studentExtracurricularExercisesSituationDao.getHomeworkData(startDayStr, endDayStr, musicGroupId, "submit", studentIds);
            d3 = studentExtracurricularExercisesSituationDao.getHomeworkData(startDayStr, endDayStr, musicGroupId, "comment", studentIds);
        }
        musicGroupHomeworkDataDeal(d1, mondayDateStrs, IndexDataType.HOMEWORK_CREATE_RATE, tenantId);
        typeDateMap.put(IndexDataType.HOMEWORK_CREATE_RATE, d1);

        musicGroupHomeworkDataDeal(d2, mondayDateStrs, IndexDataType.HOMEWORK_SUBMIT_RATE, tenantId);
        typeDateMap.put(IndexDataType.HOMEWORK_SUBMIT_RATE, d2);

        musicGroupHomeworkDataDeal(d3, mondayDateStrs, IndexDataType.HOMEWORK_COMMENT_RATE, tenantId);
        typeDateMap.put(IndexDataType.HOMEWORK_COMMENT_RATE, d3);

        for (Map.Entry<IndexDataType, List<IndexBaseMonthData>> typeDateMapEntry : typeDateMap.entrySet()) {
            IndexBaseDto indexBaseData = new IndexBaseDto(typeDateMapEntry.getKey(),typeDateMapEntry.getKey().getMsg());
            typeDateMapEntry.getValue().sort(Comparator.comparing(IndexBaseMonthData::getMonth));
            indexBaseData.setIndexMonthData(typeDateMapEntry.getValue(), null);
            result.add(indexBaseData);
        }
        return result;
    }

    private List<IndexBaseMonthData> musicGroupHomeworkDataDeal(List<IndexBaseMonthData> dataList, List<String> mondayDateStrs, IndexDataType dataType, Integer tenantId){
        if(Objects.isNull(dataList)){
            dataList = new ArrayList<>();
        }
        Set<String> hasMondayDates = dataList.stream().map(d -> DateUtil.dateToString(d.getMonth(), "yyyy-MM-dd")).collect(Collectors.toSet());

        for (String mondayDate : mondayDateStrs) {
            if(hasMondayDates.contains(mondayDate)){
                continue;
            }
            IndexBaseMonthData indexBaseMonthData = new IndexBaseMonthData(DateUtil.stringToDate(mondayDate, "yyyy-MM-dd"), null, tenantId);
            indexBaseMonthData.setDataType(dataType);
            indexBaseMonthData.setTotalNum(BigDecimal.ZERO);
            indexBaseMonthData.setActivateNum(BigDecimal.ZERO);
            indexBaseMonthData.setPercent(BigDecimal.ZERO);
            indexBaseMonthData.setDataType(dataType);
            dataList.add(indexBaseMonthData);
        }
        return dataList;
    }

    @Override
    public List<IndexBaseDto> musicGroupHomeworkStatWithStu(String musicGroupId, Integer studentId, String startDayStr, String endDayStr) {
    	
    	if(StringUtils.isBlank(musicGroupId)){
    		throw new BizException("参数[乐团编号]错误");
    	}
    	
    	MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
    	
    	if(musicGroup == null){
    		throw new BizException("乐团[{}]信息不存在", musicGroupId);
    	}
    	
    	Integer tenantId = musicGroup.getTenantId();
    	
        List<IndexBaseDto> result = new ArrayList<>();
        List<StudentRegistration> musicGroupStu = studentRegistrationDao.getMusicGroupStu(musicGroupId);
        List<Integer> studentIds = new ArrayList<>();
        if(Objects.nonNull(studentId)){
            studentIds.add(studentId);
        }else if(!CollectionUtils.isEmpty(musicGroupStu)){
            studentIds = musicGroupStu.stream().map(StudentRegistration::getUserId).collect(Collectors.toList());
        }

        LocalDate startDate = LocalDate.parse(startDayStr, DateUtil.dateFormatter);
        LocalDate endDate = LocalDate.parse(endDayStr, DateUtil.dateFormatter);
        List<String> mondayDateStrs = new ArrayList<>();
        while (startDate.compareTo(endDate)<0){
            LocalDate monDayDate = startDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
            mondayDateStrs.add(monDayDate.toString());
            startDate = startDate.plusDays(7);
        }

        Map<IndexDataType, List<IndexBaseMonthData>> typeDateMap = new HashMap<>();

        List<IndexBaseMonthData> d1 = new ArrayList<>();
        List<IndexBaseMonthData> d2 = new ArrayList<>();
        List<IndexBaseMonthData> d3 = new ArrayList<>();
        if(StringUtils.isNotBlank(musicGroupId) && !CollectionUtils.isEmpty(studentIds)){
            d1 = studentExtracurricularExercisesSituationDao.getHomeworkData(startDayStr, endDayStr, musicGroupId,null, studentIds);
            d2 = studentExtracurricularExercisesSituationDao.getHomeworkData(startDayStr, endDayStr, musicGroupId, "submit", studentIds);
            d3 = studentExtracurricularExercisesSituationDao.getHomeworkData(startDayStr, endDayStr, musicGroupId, "comment", studentIds);
        }
        musicGroupHomeworkDataDeal(d1, mondayDateStrs, IndexDataType.HOMEWORK_CREATE_RATE, tenantId);
        typeDateMap.put(IndexDataType.HOMEWORK_CREATE_RATE, d1);

        musicGroupHomeworkDataDeal(d2, mondayDateStrs, IndexDataType.HOMEWORK_SUBMIT_RATE, tenantId);
        typeDateMap.put(IndexDataType.HOMEWORK_SUBMIT_RATE, d2);

        musicGroupHomeworkDataDeal(d3, mondayDateStrs, IndexDataType.HOMEWORK_COMMENT_RATE, tenantId);
        typeDateMap.put(IndexDataType.HOMEWORK_COMMENT_RATE, d3);

        for (Map.Entry<IndexDataType, List<IndexBaseMonthData>> typeDateMapEntry : typeDateMap.entrySet()) {
            IndexBaseDto indexBaseData = new IndexBaseDto(typeDateMapEntry.getKey(),typeDateMapEntry.getKey().getMsg());
            indexBaseData.setPercent(typeDateMapEntry.getValue().stream().map(IndexBaseMonthData::getTotalNum).reduce(BigDecimal.ZERO, BigDecimal::add));
            result.add(indexBaseData);
        }
        return result;
    }
}
