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

import com.ym.mec.biz.dal.dao.*;
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.dto.StudentServiceHomeworkDto;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.GroupType;
import com.ym.mec.biz.dal.enums.TeachModeEnum;
import com.ym.mec.biz.dal.enums.YesOrNoEnum;
import com.ym.mec.biz.service.StudentServeService;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.util.date.DateUtil;
import org.apache.commons.lang3.ArrayUtils;
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 java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @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 StudentServeService studentServeService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exercisesSituationStatistics(String monday) {
        LocalDate nowDate = LocalDateTime.now(DateUtil.zoneId).toLocalDate();

        int lastWeekTodayUpdateNum = studentExtracurricularExercisesSituationDao.findLastWeekTodayUpdateNum(nowDate.plusDays(-nowDate.getDayOfWeek().getValue()).toString());
        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();
        List<Integer> serveStudentIds=new ArrayList<>();
        List<StudentServeCourseDto> serveStudentCourseStartTimes = studentDao.getServeStudentCourseStartTimes(monDayDate.toString());
        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));
                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);
        }

        studentExtracurricularExercisesSituationDao.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());
            studentExtracurricularExercisesSituationDao.batchInsert(rows);
            currentPage1=currentPage1.add(BigDecimal.ONE);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exercisesSituationStatistics2(String monday, List<Integer> studentIds) {
        LocalDate nowDate = LocalDateTime.now(DateUtil.zoneId).toLocalDate();

        int lastWeekTodayUpdateNum = studentExtracurricularExercisesSituationDao.findLastWeekTodayUpdateNum(nowDate.plusDays(-nowDate.getDayOfWeek().getValue()).toString());
        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());

//        int weekServiceNum = studentExtracurricularExercisesSituationDao.countWeekServiceNum(monDayDate.toString());
//        if(weekServiceNum>0&&CollectionUtils.isEmpty(studentIds)){
//            return;
//        }

        List<StudentServeCourseDto> studentFutureCourseInfo = studentDao.getStudentFutureCourseInfo(monDayDate.toString(), DateUtil.dateToString(nextMonday, "yyyy-MM-dd"), studentIds);
        if(CollectionUtils.isEmpty(studentFutureCourseInfo)){
            return;
        }
        Map<Integer, List<StudentServeCourseDto>> studentCourseMap = studentFutureCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getStudentId));

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

        for (Map.Entry<Integer, List<StudentServeCourseDto>> studentCourseMapEntry : studentCourseMap.entrySet()) {
            Map<CourseSchedule.CourseScheduleType, List<StudentServeCourseDto>> typeCourseMap = studentCourseMapEntry.getValue().stream().collect(Collectors.groupingBy(StudentServeCourseDto::getType));

            if(typeCourseMap.containsKey(CourseSchedule.CourseScheduleType.SINGLE)){
                List<StudentServeCourseDto> futureCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.SINGLE);
                List<StudentServeCourseDto> weekCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.SINGLE).stream().filter(c -> c.getCourseStartTime().compareTo(nextMonday) < 0).collect(Collectors.toList());
                if(CollectionUtils.isEmpty(weekCourseInfo)){
                    Map<String, List<StudentServeCourseDto>> groupCourseInfo = futureCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getMusicGroupId));

                    Map<Integer, Integer> teacherNumMap = new HashMap<>();
                    for (Map.Entry<String, List<StudentServeCourseDto>> groupCourseInfoEntry : groupCourseInfo.entrySet()) {
                        StudentServeCourseDto courseInfo = groupCourseInfoEntry.getValue().stream().min(Comparator.comparing(StudentServeCourseDto::getCourseStartTime)).get();

                        if(!teacherNumMap.containsKey(courseInfo.getActualTeacherId())){
                            teacherNumMap.put(courseInfo.getActualTeacherId(), 1);
                        }else{
                            teacherNumMap.put(courseInfo.getActualTeacherId(), teacherNumMap.get(courseInfo.getActualTeacherId())+1);
                        }
                    }

                    for (Map.Entry<Integer, Integer> teacherNumMapEntry : teacherNumMap.entrySet()) {
                        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
                                teacherNumMapEntry.getKey(),nowDate.get(DateUtil.weekFields.weekOfYear()),
                                DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
                                "EXERCISE", null);
                        studentExtracurricularExercisesSituation.setExpectExercisesNum(teacherNumMapEntry.getValue());
                        results.add(studentExtracurricularExercisesSituation);
                    }
                }else{
                    Map<String, List<StudentServeCourseDto>> groupCourseInfo = weekCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getMusicGroupId));
                    Map<Integer, Set<Long>> teacherServiceCourseIdMap = new HashMap<>();
                    for (Map.Entry<String, List<StudentServeCourseDto>> groupCourseInfoEntry : groupCourseInfo.entrySet()) {
                        StudentServeCourseDto courseInfo = groupCourseInfoEntry.getValue().stream().min(Comparator.comparing(StudentServeCourseDto::getCourseStartTime)).get();
                        if(!teacherServiceCourseIdMap.containsKey(courseInfo.getActualTeacherId())){
                            teacherServiceCourseIdMap.put(courseInfo.getActualTeacherId(), new HashSet<>());
                        }
                        teacherServiceCourseIdMap.get(courseInfo.getActualTeacherId()).add(courseInfo.getCourseScheduleId());
                    }
                    for (Map.Entry<Integer, Set<Long>> teacherServiceCourseIdMapEntry : teacherServiceCourseIdMap.entrySet()) {
                        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
                                teacherServiceCourseIdMapEntry.getKey(),nowDate.get(DateUtil.weekFields.weekOfYear()),
                                DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
                                "HOMEWORK", StringUtils.join(teacherServiceCourseIdMapEntry.getValue(), ","));
                        studentExtracurricularExercisesSituation.setExpectExercisesNum(teacherServiceCourseIdMapEntry.getValue().size());
                        results.add(studentExtracurricularExercisesSituation);
                    }
                }
            }else if(typeCourseMap.containsKey(CourseSchedule.CourseScheduleType.VIP)){
                List<StudentServeCourseDto> futureCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.VIP);
                List<StudentServeCourseDto> weekCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.VIP).stream().filter(c -> c.getCourseStartTime().compareTo(nextMonday) < 0).collect(Collectors.toList());
                if(CollectionUtils.isEmpty(weekCourseInfo)){
                    Map<Integer, List<StudentServeCourseDto>> teacherCourseMap = futureCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getActualTeacherId));
                    for (Integer teacherId : teacherCourseMap.keySet()) {
                        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
                                teacherId,nowDate.get(DateUtil.weekFields.weekOfYear()),
                                DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
                                "EXERCISE", null);
                        results.add(studentExtracurricularExercisesSituation);
                    }
                }else{
                    Map<Integer, List<StudentServeCourseDto>> teacherCourseMap = weekCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getActualTeacherId));
                    for (Map.Entry<Integer, List<StudentServeCourseDto>> teacherCourseMapEntry : teacherCourseMap.entrySet()) {
                        StudentServeCourseDto courseInfo = teacherCourseMapEntry.getValue().stream().min(Comparator.comparing(StudentServeCourseDto::getCourseStartTime)).get();
                        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation;
                        if(TeachModeEnum.OFFLINE.equals(courseInfo.getTeachMode())){
                            studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
                                    teacherCourseMapEntry.getKey(),nowDate.get(DateUtil.weekFields.weekOfYear()),
                                    DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
                                    "EXERCISE", null);
                        }else{
                            studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
                                    teacherCourseMapEntry.getKey(),nowDate.get(DateUtil.weekFields.weekOfYear()),
                                    DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
                                    "HOMEWORK", String.valueOf(courseInfo.getCourseScheduleId()));
                        }
                        results.add(studentExtracurricularExercisesSituation);
                    }
                }
            }else if(typeCourseMap.containsKey(CourseSchedule.CourseScheduleType.MIX)){
                List<StudentServeCourseDto> futureCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.MIX);
                List<StudentServeCourseDto> weekCourseInfo = futureCourseInfo.stream().filter(c -> c.getCourseStartTime().compareTo(nextMonday) < 0).collect(Collectors.toList());
                List<StudentServeCourseDto> serveCourseInfo;
                if(CollectionUtils.isEmpty(weekCourseInfo)){
                    serveCourseInfo = futureCourseInfo;
                }else{
                    serveCourseInfo = weekCourseInfo;
                }
                Map<String, List<StudentServeCourseDto>> groupCourseInfo = serveCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getMusicGroupId));

                Map<Integer, Integer> teacherNumMap = new HashMap<>();
                for (String groupId : groupCourseInfo.keySet()) {
                    CourseSchedule studentHistoryLastCourse = courseScheduleStudentPaymentDao.getStudentHistoryLastCourse(studentCourseMapEntry.getKey(), monDayDate.toString(), groupId, CourseSchedule.CourseScheduleType.SINGLE);
                    Integer teacherId = Objects.isNull(studentHistoryLastCourse)?studentCourseMapEntry.getValue().get(0).getLeadTeacherId():studentHistoryLastCourse.getActualTeacherId();
                    if(Objects.isNull(teacherId)){
                        continue;
                    }

                    if(!teacherNumMap.containsKey(teacherId)){
                        teacherNumMap.put(teacherId, 1);
                    }else{
                        teacherNumMap.put(teacherId, teacherNumMap.get(teacherId)+1);
                    }

                }

                for (Map.Entry<Integer, Integer> teacherNumMapEntry : teacherNumMap.entrySet()) {
                    StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
                            teacherNumMapEntry.getKey(),
                            nowDate.get(DateUtil.weekFields.weekOfYear()),
                            DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
                            "EXERCISE", null);
                    studentExtracurricularExercisesSituation.setExpectExercisesNum(teacherNumMapEntry.getValue());
                    results.add(studentExtracurricularExercisesSituation);
                }
            }else if(typeCourseMap.containsKey(CourseSchedule.CourseScheduleType.PRACTICE)){
                List<StudentServeCourseDto> futureCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.PRACTICE);
                List<StudentServeCourseDto> weekCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.PRACTICE).stream().filter(c -> c.getCourseStartTime().compareTo(nextMonday) < 0).collect(Collectors.toList());
                if(CollectionUtils.isEmpty(weekCourseInfo)){
                    Set<Integer> teacherIds = futureCourseInfo.stream().map(StudentServeCourseDto::getActualTeacherId).collect(Collectors.toSet());
                    for (Integer teacherId : teacherIds) {
                        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
                                teacherId,nowDate.get(DateUtil.weekFields.weekOfYear()),
                                DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
                                "EXERCISE", null);
                        results.add(studentExtracurricularExercisesSituation);
                    }
                }else{
                    Map<Integer, List<StudentServeCourseDto>> teacherCourseMap = weekCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getActualTeacherId));
                    Map<Integer, Set<Long>> teacherServiceCourseIdMap = new HashMap<>();
                    for (Map.Entry<Integer, List<StudentServeCourseDto>> teacherCourseMapEntry : teacherCourseMap.entrySet()) {
                        StudentServeCourseDto courseInfo = teacherCourseMapEntry.getValue().stream().min(Comparator.comparing(StudentServeCourseDto::getCourseStartTime)).get();
                        teacherServiceCourseIdMap.put(teacherCourseMapEntry.getKey(), new HashSet<>());
                        teacherServiceCourseIdMap.get(teacherCourseMapEntry.getKey()).add(courseInfo.getCourseScheduleId());
                    }
                    for (Map.Entry<Integer, Set<Long>> teacherServiceCourseIdMapEntry : teacherServiceCourseIdMap.entrySet()) {
                        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
                                teacherServiceCourseIdMapEntry.getKey(),nowDate.get(DateUtil.weekFields.weekOfYear()),
                                DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
                                "HOMEWORK", StringUtils.join(teacherServiceCourseIdMapEntry.getValue(), ","));
                        studentExtracurricularExercisesSituation.setExpectExercisesNum(teacherServiceCourseIdMapEntry.getValue().size());
                        results.add(studentExtracurricularExercisesSituation);
                    }
                }
            }else{
                continue;
            }
        }

        if(!CollectionUtils.isEmpty(results)){

            if(CollectionUtils.isEmpty(studentIds)){
                studentIds = 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<>(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));
            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);
                        }
                    }
                }
            }

            studentExtracurricularExercisesSituationDao.deleteByMonday(monDayDate.toString(), studentIds);

            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());
//                List<Integer> updateStudentIds = rows.stream().map(StudentExtracurricularExercisesSituation::getStudentId).collect(Collectors.toList());
//
//                List<StudentExtracurricularExercisesSituation> weekServiceWithStudents = studentExtracurricularExercisesSituationDao.findWeekServiceWithStudents(monDayDate.toString(), null, updateStudentIds);
//                Map<String, StudentExtracurricularExercisesSituation> codeServeMap = weekServiceWithStudents.stream().collect(Collectors.toMap(StudentExtracurricularExercisesSituation::getStuAndTeaCode, s -> s, (s1, s2) -> s1));
//
//                Set<String> newCodes = rows.stream().map(StudentExtracurricularExercisesSituation::getStuAndTeaCode).collect(Collectors.toSet());
//                for (StudentExtracurricularExercisesSituation weekServiceWithStudent : weekServiceWithStudents) {
//                    if(weekServiceWithStudent.getActualExercisesNum()>0||newCodes.contains(weekServiceWithStudent.getStuAndTeaCode())){
//                        continue;
//                    }
//                    studentExtracurricularExercisesSituationDao.delete(weekServiceWithStudent.getId());
//                }
//
//                List<StudentExtracurricularExercisesSituation> newService = new ArrayList<>();
//                List<StudentExtracurricularExercisesSituation> updateService = new ArrayList<>();
//                for (StudentExtracurricularExercisesSituation result : rows) {
//                    if(codeServeMap.containsKey(result.getStuAndTeaCode())){
//                        StudentExtracurricularExercisesSituation s = codeServeMap.get(result.getStuAndTeaCode());
//                        Set<Long> courseIds = new HashSet<>();
//                        if(StringUtils.isNotBlank(s.getCourseIds())&&s.getActualExercisesNum()>0){
//                            courseIds = Arrays.stream(s.getCourseIds().split(",")).map(id->Long.valueOf(id)).collect(Collectors.toSet());
//                        }
//                        if(StringUtils.isNotBlank(result.getCourseIds())){
//                            courseIds.addAll(Arrays.stream(result.getCourseIds().split(",")).map(id->Long.valueOf(id)).collect(Collectors.toSet()));
//                        }
//                        s.setServeType(result.getServeType());
//                        if(s.getServeType().equals("HOMEWORK")){
//                            s.setCourseIds(StringUtils.join(courseIds, ","));
//                        }else{
//                            s.setCourseIds("");
//                        }
//                        if(StringUtils.isBlank(s.getCourseIds())){
//                            s.setExpectExercisesNum(1);
//                        }else{
//                            s.setExpectExercisesNum(courseIds.size());
//                        }
//                        updateService.add(s);
//                    }else{
//                        newService.add(result);
//                    }
//                }
//                if(!CollectionUtils.isEmpty(updateService))
//                    studentExtracurricularExercisesSituationDao.batchUpdate(updateService);
//                if(!CollectionUtils.isEmpty(newService))
//                    studentExtracurricularExercisesSituationDao.batchInsert(newService);

                studentExtracurricularExercisesSituationDao.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));
        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) {
        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)){
            CourseSchedule courseSchedule = courseScheduleDao.get(courseScheduleId);
            if(Objects.isNull(courseSchedule)){
                result.put("isAssignHomework", 0);
                return result;
            }
            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());

        Set<Integer> hss = studentCourseHomeworkDao.checkStudentHaveHomeworkInDateRange(monDayDate.toString(), sunDayDate.toString(), studentIds);
        Set<Integer> ess = extracurricularExercisesReplyDao.checkStudentHaveExercisesInDateRange(monDayDate.toString(), sunDayDate.toString(), studentIds);
        for (Integer studentId : studentIds) {
            if(!hss.contains(studentId)&&!ess.contains(studentId)){
                result.put("isAssignHomework", 0);
                return result;
            }
        }
        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<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());
    }
}
