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.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.entity.*;
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.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dto.CourseHomeworkDto;
import com.ym.mec.biz.dal.dto.CourseHomeworkStudentDetailDto;
import com.ym.mec.biz.dal.dto.EduHomeworkCardDto;
import com.ym.mec.biz.dal.dto.EduHomeworkStatDto;
import com.ym.mec.biz.dal.dto.SimpleUserDto;
import com.ym.mec.biz.dal.dto.StudentCourseHomeworkDto;
import com.ym.mec.biz.dal.dto.StudentHomeworkRecordDto;
import com.ym.mec.biz.dal.dto.StudentVisitCourseHomeWorkDto;
import com.ym.mec.biz.dal.entity.CourseSchedule.CourseScheduleType;
import com.ym.mec.biz.dal.enums.GroupType;
import com.ym.mec.biz.dal.enums.MessageTypeEnum;
import com.ym.mec.biz.dal.enums.MusicGroupStatusEnum;
import com.ym.mec.biz.dal.enums.StudentMusicGroupStatusEnum;
import com.ym.mec.biz.dal.enums.YesOrNoEnum;
import com.ym.mec.biz.dal.page.CourseHomeworkQueryInfo;
import com.ym.mec.biz.dal.page.StudentCourseHomeWorkQueryInfo;
import com.ym.mec.biz.service.CourseHomeworkService;
import com.ym.mec.biz.service.MusicGroupTrainPlanService;
import com.ym.mec.biz.service.StudentCourseHomeworkService;
import com.ym.mec.biz.service.StudentServeService;
import com.ym.mec.biz.service.SysConfigService;
import com.ym.mec.biz.service.SysMessageService;
import com.ym.mec.common.constant.CommonConstants;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.page.QueryInfo;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext.MessageSender;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;

@Service
public class StudentCourseHomeworkServiceImpl extends BaseServiceImpl<Long, StudentCourseHomework> implements StudentCourseHomeworkService {

    @Autowired
    private StudentCourseHomeworkDao studentCourseHomeworkDao;
    @Autowired
    private CourseHomeworkService courseHomeworkService;
    @Autowired
    private CourseHomeworkDao courseHomeworkDao;
    @Autowired
    private CourseScheduleDao courseScheduleDao;
    @Autowired
    private ClassGroupDao classGroupDao;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private CourseScheduleReviewDao courseScheduleReviewDao;
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private SubjectDao subjectDao;
    @Autowired
    private StudentServeService studentServeService;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private StudentRegistrationDao studentRegistrationDao;
    @Autowired
    private VipGroupDao vipGroupDao;
    @Autowired
    private PracticeGroupDao practiceGroupDao;
    @Autowired
    private ExtracurricularExercisesReplyDao extracurricularExercisesReplyDao;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private SysMusicScoreDao sysMusicScoreDao;
    @Autowired
	private MusicGroupTrainPlanService musicGroupTrainPlanService;
    @Autowired
	private StudentExtracurricularExercisesSituationDao studentExtracurricularExercisesSituationDao;

    @Override
    public BaseDAO<Long, StudentCourseHomework> getDAO() {
        return studentCourseHomeworkDao;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public long insert(StudentCourseHomework bean) {
        SysUser user = sysUserFeignService.queryUserInfo();
        bean.setUserId(user.getId());
        bean.setStatus(YesOrNoEnum.YES);
        long insert = super.insert(bean);

        CourseSchedule courseSchedule = courseScheduleDao.get(bean.getCourseScheduleId());

        CourseHomework courseHomework = new CourseHomework();
        courseHomework.setId(bean.getCourseHomeworkId());
        courseHomework.setGroupType(courseSchedule.getGroupType());
        courseHomework.setCompletedNum(studentCourseHomeworkDao.countCompletedStudentNum(bean.getCourseHomeworkId()));

        courseHomeworkService.update(courseHomework);
        return insert;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitHomework(StudentCourseHomework bean) {
        if (Objects.isNull(bean.getAttachments()) || StringUtils.isBlank(bean.getAttachments())) {
            throw new BizException("请选择作业");
        }
        StudentCourseHomework existHomework = studentCourseHomeworkDao.get(bean.getId());
        if (Objects.isNull(bean) || Objects.isNull(bean.getId()) || Objects.isNull(existHomework)) {
            throw new BizException("作业不存在");
        }
        Date now = new Date();

        if (DateUtil.daysBetween(existHomework.getCreateTime(), now) > 7) {
            throw new BizException("该作业已超出可提交时间范围，无法提交作业。");
        }
        CourseSchedule courseSchedule = courseScheduleDao.get(existHomework.getCourseScheduleId());
        //若本周有当前课程所在乐团的服务指标，那么在课程开始当天之后不能再提交作业
        Date classDate = studentExtracurricularExercisesSituationDao.getHomeworkSituations(courseSchedule.getId(),courseSchedule.getMusicGroupId(),"HOMEWORK",
                        DateUtil.getWeekMondayWithDate(now),existHomework.getUserId());
        if(Objects.nonNull(classDate)){
            int i = classDate.compareTo(DateUtil.stringToDate(DateUtil.format(now, DateUtil.ISO_EXPANDED_DATE_FORMAT), DateUtil.ISO_EXPANDED_DATE_FORMAT));
            if(i <= 0){
                throw new BizException("已超过提交作业期限。");
            }
        }
        boolean push = true;
        bean.setSubmitTime(now);
        super.update(bean);
        bean = studentCourseHomeworkDao.get(bean.getId());

        CourseHomework courseHomework = courseHomeworkDao.get(bean.getCourseHomeworkId());
        courseHomework.setGroupType(courseSchedule.getGroupType());
        courseHomework.setCompletedNum(studentCourseHomeworkDao.countCompletedStudentNum(bean.getCourseHomeworkId()));
        courseHomeworkService.update(courseHomework);
        studentServeService.updateExercisesSituation(courseSchedule.getClassDate(), new ArrayList<>(Arrays.asList(bean.getUserId())), courseSchedule.getTeacherId());

        Integer userId = bean.getUserId();
        if (courseSchedule.getType().equals(CourseScheduleType.VIP)) {
            userId = null;
        }

        CourseScheduleReview review = courseScheduleReviewDao.findByCourseScheduleAndStudent(bean.getCourseScheduleId(), userId);
        if (Objects.nonNull(review)) {
            review.setHandHomework(YesOrNoEnum.YES.getCode());
            courseScheduleReviewDao.update(review);
        }

        if (push) {
            Map<Integer, String> userMap = new HashMap<>();
            userMap.put(courseSchedule.getActualTeacherId(), courseSchedule.getActualTeacherId().toString());
            SysUser user = teacherDao.getUser(bean.getUserId());
            String notifyUrl = "9?courseScheduleID=" + bean.getId() + "&userId=" + bean.getUserId() + "&studentCourseHomeworkId=" + bean.getId() + "&extra=0";
            String extra = "dayaedu?courseScheduleID=" + courseSchedule.getId() + "&userId=" + bean.getUserId() + "&studentCourseHomeworkId=" + bean.getId() + "&extra=0";
            String courseDate = DateUtil.dateToString(courseSchedule.getClassDate(), "yyyy年MM月dd日");
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.TEACHER_PUSH_HOMEWORK_SUBMIT,
                    userMap, null, 0, notifyUrl, "TEACHER", courseSchedule.getName(), courseDate, user.getUsername());
            MusicGroup musicGroup = musicGroupDao.get(courseSchedule.getMusicGroupId());

            sysMessageService.batchSendImMessage(MessageTypeEnum.IM_HOMEWORK_SUBMIT_PUSH, bean.getUserId().toString(), extra,
                    new String[]{courseSchedule.getActualTeacherId().toString()},
                    null, courseDate, courseSchedule.getName());
            if(musicGroup != null && musicGroup.getHomeworkPushFlag() == 1){
                Date date = new Date();
                if (date.before(courseHomework.getExpiryDate())) {
                    ClassGroup classGroup = classGroupDao.findByCourseSchedule(existHomework.getCourseScheduleId().intValue(), 0);
                    if (classGroup != null) {
                        SysUser sysUser = sysUserFeignService.queryUserById(existHomework.getUserId());
                        sysMessageService.batchSendImGroupMessage(MessageTypeEnum.IM_HOMEWORK_SUBMIT_PUSH_GROUP, existHomework.getUserId().toString(), null,
                                new String[]{classGroup.getId().toString()},
                                null, sysUser.getUsername());
                    }
                }
            }
        }
    }

    @Override
    public CourseHomeworkStudentDetailDto findCourseHomeworkStudentDetail(Long courseScheduleID, Long userId) {
        if (Objects.isNull(courseScheduleID)) {
            throw new BizException("作业不存在");
        }
        CourseSchedule courseSchedule = courseScheduleDao.get(courseScheduleID);
        
        if(courseSchedule == null){
        	throw new BizException("课程不存在");
        }

        MusicGroupTrainPlan musicGroupTrainPlan = null;
		//获取课程规划
		MusicGroupTrainPlanSaveDto schoolTerm = musicGroupTrainPlanService.getSchoolTerm(courseSchedule);
		int courseNumNo = courseScheduleDao.getCourseNumNo(schoolTerm);
		List<MusicGroupTrainPlan> planList = musicGroupTrainPlanService.queryPlan(schoolTerm);
		if(planList.size() >= courseNumNo){
			musicGroupTrainPlan = planList.get(courseNumNo - 1);
		}
		
        CourseHomeworkStudentDetailDto courseHomeworkStudentDetail = studentCourseHomeworkDao.findCourseHomeworkStudentDetail(courseScheduleID, userId);
        if(courseHomeworkStudentDetail == null){
        	courseHomeworkStudentDetail = new CourseHomeworkStudentDetailDto();
			courseHomeworkStudentDetail.setMusicGroupTrainPlan(musicGroupTrainPlan);
        	return courseHomeworkStudentDetail;
        }
        courseHomeworkStudentDetail.setExpire(DateUtil.isOverdue(courseHomeworkStudentDetail.getSubmitTime(),
                sysConfigDao.findConfigValue("file_expiration_time")));
		courseHomeworkStudentDetail.setMusicGroupTrainPlan(musicGroupTrainPlan);
        
        SysUser sysUser = teacherDao.getUser(userId.intValue());
        courseHomeworkStudentDetail.setStudentId(userId.intValue());
        courseHomeworkStudentDetail.setStudentName(sysUser.getUsername());
        if (Objects.nonNull(courseSchedule)) {
            SysUser teacher = teacherDao.getUser(courseSchedule.getActualTeacherId());
            courseHomeworkStudentDetail.setTeacherId(courseSchedule.getActualTeacherId());
            courseHomeworkStudentDetail.setTeacherName(teacher.getRealName());
        }
        courseHomeworkStudentDetail.setType("HOMEWORK");
        String configValue = sysConfigDao.findConfigValue(SysConfigService.HOMEWORK_OPEN_FLAG);
        if(StringUtils.isEmpty(configValue)){
            configValue = "0";
        }
        courseHomeworkStudentDetail.setHomeworkOpenFlag(Integer.parseInt(configValue));
        if(StringUtils.isNotEmpty(courseHomeworkStudentDetail.getMusicScoreId())){
            List<SysMusicScore> sysMusicScoreList = sysMusicScoreDao.findByIds(courseHomeworkStudentDetail.getMusicScoreId());
            courseHomeworkStudentDetail.setSysMusicScoreList(sysMusicScoreList);
            SysMusicScore sysMusicScore = sysMusicScoreList.get(0);
            courseHomeworkStudentDetail.setSysMusicScore(sysMusicScore);
            courseHomeworkStudentDetail.setMusicScoreId(sysMusicScore.getId().toString());
            courseHomeworkStudentDetail.setMusicScoreName(sysMusicScore.getName());
        }
        Student student = studentDao.get(userId.intValue());
        courseHomeworkStudentDetail.setHasMember(student.getMemberRankSettingId()==null?0:1);

        Date now = new Date();

        if (DateUtil.daysBetween(courseHomeworkStudentDetail.getCreateTime(), now) > 7) {
            courseHomeworkStudentDetail.setSubmitFlag(false);
        }
        if(courseHomeworkStudentDetail.getSubmitFlag()){
            //若本周有当前课程所在乐团的服务指标，那么在课程开始当天之后不能再提交作业
            Date classDate = studentExtracurricularExercisesSituationDao.getHomeworkSituations(courseSchedule.getId(),courseSchedule.getMusicGroupId(),"HOMEWORK",
                    DateUtil.getWeekMondayWithDate(now),userId.intValue());
            if(Objects.nonNull(classDate)){
                int i = classDate.compareTo(DateUtil.stringToDate(DateUtil.format(now, DateUtil.ISO_EXPANDED_DATE_FORMAT), DateUtil.ISO_EXPANDED_DATE_FORMAT));
                if(i <= 0){
                    courseHomeworkStudentDetail.setSubmitFlag(false);
                }
            }
        }
        return courseHomeworkStudentDetail;
    }

    @Override
    public boolean updateReplyStatus(Integer teacherId, Long courseHomeworkId, Integer studentId) {
        StudentCourseHomework byStudentAndCourseHomewok = studentCourseHomeworkDao.findByStudentAndCourseHomewok(courseHomeworkId, studentId);
        if (Objects.isNull(byStudentAndCourseHomewok)) {
            throw new BizException("作业记录不存在");
        }

        int hours = -1;
        if (Objects.nonNull(byStudentAndCourseHomewok.getSubmitTime())) {
            hours = DateUtil.hoursBetween(byStudentAndCourseHomewok.getSubmitTime(), new Date());
        }
        if (byStudentAndCourseHomewok.getIsReplied() == YesOrNoEnum.YES && Integer.valueOf(1).equals(byStudentAndCourseHomewok.getIsRepliedTimely())) {
            return true;
        }
        if (hours >= 0 && hours <= 24) {
            byStudentAndCourseHomewok.setIsRepliedTimely(1);
        }
        CourseHomework byTeacherAndCourseHomewok = courseHomeworkDao.findByTeacherAndCourseHomewok(courseHomeworkId, teacherId);
        if (Objects.nonNull(byTeacherAndCourseHomewok)) {
            byStudentAndCourseHomewok.setIsReplied(YesOrNoEnum.YES);
            studentCourseHomeworkDao.update(byStudentAndCourseHomewok);

            CourseSchedule courseSchedule = courseScheduleDao.get(byStudentAndCourseHomewok.getCourseScheduleId());

            LocalDate nowDate = LocalDateTime.now(DateUtil.zoneId).toLocalDate();
            LocalDate monDayDate = nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
            LocalDate createDateTime = LocalDateTime.ofInstant(courseSchedule.getClassDate().toInstant(), DateUtil.zoneId).toLocalDate();
            LocalDate createMonday = createDateTime.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());

            LocalDate homeworkCreateDateTime = LocalDateTime.ofInstant(byStudentAndCourseHomewok.getCreateTime().toInstant(), DateUtil.zoneId).toLocalDate();
            boolean isOk = false;
            switch (createDateTime.getDayOfWeek()) {
                case SATURDAY:
                    if (createDateTime.until(homeworkCreateDateTime, ChronoUnit.DAYS) < 4) {
                        isOk = true;
                    }
                    break;
                case SUNDAY:
                    if (createDateTime.until(homeworkCreateDateTime, ChronoUnit.DAYS) < 3) {
                        isOk = true;
                    }
                    break;
                default:
                    if (createDateTime.get(DateUtil.weekFields.weekOfYear()) == homeworkCreateDateTime.get(DateUtil.weekFields.weekOfYear())) {
                        isOk = true;
                    }
                    break;
            }
            if (createDateTime.isBefore(monDayDate) && isOk) {
                studentServeService.updateExercisesSituation(new Date(), new ArrayList<>(Arrays.asList(byStudentAndCourseHomewok.getUserId())), teacherId);
            }
        }
        return true;
    }

    @Override
    public PageInfo<StudentCourseHomework> queryPage(QueryInfo queryInfo) {
        SysUser user = sysUserFeignService.queryUserInfo();
        CourseHomeworkQueryInfo courseHomeworkQueryInfo = (CourseHomeworkQueryInfo) queryInfo;
        courseHomeworkQueryInfo.setUserId(Long.valueOf(user.getId()));
        return super.queryPage(queryInfo);
    }

    @Override
    public List<StudentCourseHomework> findStudentCourseHomeworkByCourse(Long courseSchedule, Long homeworkId, String userName) {
        return studentCourseHomeworkDao.findByCourseSchedule(courseSchedule, homeworkId, userName);
    }

    @Override
    public void homeworkRemind() {
        List<StudentCourseHomework> list = studentCourseHomeworkDao.queryNotDoneHomeworkList();
        StringBuffer sb;
        for (StudentCourseHomework sch : list) {
            sb = new StringBuffer("courseScheduleID=").append(sch.getCourseScheduleId()).append("&studentCourseHomeworkId=").append(sch.getId());
            Map<Integer, String> receivers = new HashMap<Integer, String>(1);
            receivers.put(sch.getUserId(), sch.getUserId() + "");
            sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_JOB_MESSAGE, receivers, null, 0, "3?" + sb, "STUDENT", sch.getCourseHomework()
                    .getMusicGroup().getName(), sch.getCourseHomework().getClassGroup().getName());
        }
    }

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

        List<StudentCourseHomeworkDto> dataList = null;
        int count = studentCourseHomeworkDao.countStudentCourseHomeworks(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentCourseHomeworkDao.findStudentCourseHomeworks(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

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

        List<StudentHomeworkRecordDto> dataList = null;
        int count = studentCourseHomeworkDao.countStudentHomeworkRecord(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentCourseHomeworkDao.findStudentHomeworkRecord(params);
            if (!CollectionUtils.isEmpty(dataList)) {
                List<Integer> teacherIds = dataList.stream().map(StudentHomeworkRecordDto::getTeacherId).collect(Collectors.toList());
                List<SimpleUserDto> teachers = teacherDao.findSimpleTeachers(teacherIds, queryInfo.getTenantId());
                Map<Integer, String> idNameMap = teachers.stream().collect(Collectors.toMap(SimpleUserDto::getUserId, u -> u.getUserName()));
                for (StudentHomeworkRecordDto studentHomeworkRecordDto : dataList) {
                    studentHomeworkRecordDto.setTeacherName(idNameMap.get(studentHomeworkRecordDto.getTeacherId()));
                }
            }
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public void add(StudentCourseHomework studentCourseHomework) {
        studentCourseHomework.setStatus(YesOrNoEnum.YES);
        studentCourseHomeworkDao.insert(studentCourseHomework);
        CourseHomework courseHomework = courseHomeworkDao.get(studentCourseHomework.getCourseHomeworkId());
        Date date = new Date();
        if (date.before(courseHomework.getExpiryDate())) {
            ClassGroup classGroup = classGroupDao.findByCourseSchedule(studentCourseHomework.getCourseScheduleId().intValue(), 0);
            if (classGroup != null) {
                SysUser sysUser = sysUserFeignService.queryUserById(studentCourseHomework.getUserId());
                sysMessageService.batchSendImGroupMessage(MessageTypeEnum.IM_HOMEWORK_SUBMIT_PUSH_GROUP, studentCourseHomework.getUserId().toString(), null,
                        new String[]{classGroup.getId().toString()},
                        null, sysUser.getUsername());
            }
        }
    }

    @Override
    public Map<String, Object> getCourseHomeworkDetail(CourseHomeworkQueryInfo queryInfo) {
        Map<String, Object> result = new HashMap<>();
        CourseHomework courseHomework = courseHomeworkDao.findByCourseSchedule(queryInfo.getCourseScheduleId());

        if (Objects.isNull(courseHomework)) {
            result.put("countInfo", null);
            return result;
        }

        PageInfo<StudentCourseHomeworkDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List<StudentCourseHomework> dataList = new ArrayList<>();
        List<StudentCourseHomeworkDto> studentCourseHomeworkDtos = new ArrayList<>();
        int count = studentCourseHomeworkDao.countAll(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentCourseHomeworkDao.queryAll(params);
            Set<Integer> studentIds = dataList.stream().map(StudentCourseHomework::getUserId).collect(Collectors.toSet());
            List<SimpleUserDto> usersSimpleInfo = teacherDao.getUsersSimpleInfo(new ArrayList<>(studentIds));
            List<Student> students = studentDao.findByStudentIds(new ArrayList<>(studentIds));
            Set<Integer> subjectIds = new HashSet<>();
            for (Student student : students) {
                if (StringUtils.isBlank(student.getSubjectIdList())) {
                    continue;
                }
                Set<Integer> studentSubjectIds = Arrays.stream(student.getSubjectIdList().split(",")).mapToInt(Integer::valueOf).boxed().collect(Collectors.toSet());
                subjectIds.addAll(studentSubjectIds);
            }
            List<Subject> subjects = new ArrayList<>();
            if (!CollectionUtils.isEmpty(subjectIds)) {
                subjects = subjectDao.findBySubjectIds(new ArrayList<>(subjectIds));
            }
            Map<Integer, SimpleUserDto> studentInfoMap = usersSimpleInfo.stream().collect(Collectors.toMap(SimpleUserDto::getUserId, s -> s, (s1, s2) -> s1));
            Map<Integer, Student> studentMap = students.stream().collect(Collectors.toMap(Student::getUserId, s -> s, (s1, s2) -> s1));
            for (StudentCourseHomework studentCourseHomework : dataList) {
                StudentCourseHomeworkDto s = new StudentCourseHomeworkDto();
                s.setStudentId(studentCourseHomework.getUserId());
                s.setStudentName(studentInfoMap.containsKey(s.getStudentId()) ? studentInfoMap.get(s.getStudentId()).getNickName() : "");
                s.setPhone(studentInfoMap.containsKey(s.getStudentId()) ? studentInfoMap.get(s.getStudentId()).getPhone() : "");
                s.setSubjectIds(studentMap.containsKey(s.getStudentId()) ? studentMap.get(s.getStudentId()).getSubjectIdList() : "");
                if (StringUtils.isNotBlank(s.getSubjectIds())) {
                    Set<Integer> studentSubjectIds = Arrays.stream(s.getSubjectIds().split(",")).mapToInt(Integer::valueOf).boxed().collect(Collectors.toSet());
                    List<String> subjectNames = subjects.stream().filter(sj -> studentSubjectIds.contains(sj.getId())).map(Subject::getName).collect(Collectors.toList());
                    s.setSubjectNames(StringUtils.join(subjectNames, ","));
                }
                s.setSubmitTime(studentCourseHomework.getSubmitTime());
                s.setIsView(studentCourseHomework.getIsView().getCode());
                s.setIsReplied(studentCourseHomework.getIsReplied().getCode());
                s.setAttachments(studentCourseHomework.getAttachments());
                studentCourseHomeworkDtos.add(s);
            }
        }
        pageInfo.setRows(studentCourseHomeworkDtos);

        if (queryInfo.getPage() == 1) {
            params.put("isReplied", 1);
            int repliedNum = studentCourseHomeworkDao.countAll(params);
            CourseHomeworkDto courseHomeworkDto = new CourseHomeworkDto();
            courseHomeworkDto.setExpectNum(courseHomework.getExpectNum());
            courseHomeworkDto.setCompletedNum(courseHomework.getCompletedNum());
            courseHomeworkDto.setRepliedNum(repliedNum);
            courseHomeworkDto.setRepliedNum(repliedNum);
            result.put("countInfo", courseHomeworkDto);
        }

        result.put("pageInfo", pageInfo);

        return result;
    }

    @Override
    public PageInfo<StudentVisitCourseHomeWorkDto> getStudentHomeWorks(StudentCourseHomeWorkQueryInfo queryInfo) {
        PageInfo<StudentVisitCourseHomeWorkDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);
        List<StudentVisitCourseHomeWorkDto> dataList = new ArrayList<>();
        int count = studentCourseHomeworkDao.getStudentCourseHomeWorksCount(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentCourseHomeworkDao.getStudentCourseHomeWorks(params);

            List<String> musicGroupIds = dataList.stream().filter(e -> e.getGroupType()!=null).filter(e -> e.getGroupType().equals(GroupType.MUSIC)).map(StudentVisitCourseHomeWorkDto::getGroupId).distinct().collect(Collectors.toList());
            List<Long> vipGroupIds = dataList.stream().filter(e -> e.getGroupType()!=null).filter(e -> e.getGroupType().equals(GroupType.VIP)).map(e -> Long.parseLong(e.getGroupId())).distinct().collect(Collectors.toList());
            List<Long> practiceGroupIds = dataList.stream().filter(e -> e.getGroupType()!=null).filter(e -> e.getGroupType().equals(GroupType.PRACTICE)).map(e -> Long.parseLong(e.getGroupId())).distinct().collect(Collectors.toList());

            Map<String, List<MusicGroup>> musicGroupMap = new HashMap<>();
            Map<Long, List<VipGroup>> vipGroupMap = new HashMap<>();
            Map<Long, List<PracticeGroup>> practiceGroupMap = new HashMap<>();
            if (musicGroupIds.size() > 0) {
                musicGroupMap = musicGroupDao.getMusicGroupByIds(musicGroupIds).stream().collect(Collectors.groupingBy(MusicGroup::getId));
            }
            if (vipGroupIds.size() > 0) {
                vipGroupMap = vipGroupDao.getVipGroupByIds(vipGroupIds).stream().collect(Collectors.groupingBy(VipGroup::getId));
            }
            if (practiceGroupIds.size() > 0) {
                practiceGroupMap = practiceGroupDao.getWithIds(practiceGroupIds).stream().collect(Collectors.groupingBy(PracticeGroup::getId));
            }
            for (StudentVisitCourseHomeWorkDto homeWork : dataList) {
                if (GroupType.MUSIC.equals(homeWork.getGroupType()) && musicGroupMap.containsKey(homeWork.getGroupId())) {
                    homeWork.setGroupName(musicGroupMap.get(homeWork.getGroupId()).get(0).getName());
                }
                if (GroupType.VIP.equals(homeWork.getGroupType()) && vipGroupMap.containsKey(Long.parseLong(homeWork.getGroupId()))) {
                    homeWork.setGroupName(vipGroupMap.get(Long.parseLong(homeWork.getGroupId())).get(0).getName());
                }
                if (GroupType.PRACTICE.equals(homeWork.getGroupType()) && practiceGroupMap.containsKey(Long.parseLong(homeWork.getGroupId()))) {
                    homeWork.setGroupName(practiceGroupMap.get(Long.parseLong(homeWork.getGroupId())).get(0).getName());
                }
            }
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

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

        int count = studentCourseHomeworkDao.countEduCourseHomeworkList(params);
        pageInfo.setTotal(count);
        params.put("offset", pageInfo.getOffset());
        List<EduHomeworkCardDto> dataList = studentCourseHomeworkDao.getEduCourseHomeworkList(params);

        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public PageInfo<EduHomeworkStatDto> queryEduHomeworkStatList(StudentCourseHomeWorkQueryInfo queryInfo) {
        PageInfo<EduHomeworkStatDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);
        params.put("musicGroupStatus", MusicGroupStatusEnum.PROGRESS.getCode());

        int count = musicGroupDao.queryCount(params);
        pageInfo.setTotal(count);
        params.put("offset", pageInfo.getOffset());
//        StudentService
        List<MusicGroup> musicGroups = musicGroupDao.queryPage(params);

        List<EduHomeworkStatDto> dataList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(musicGroups)){
            List<String> groupIds = musicGroups.stream().map(MusicGroup::getId).collect(Collectors.toList());
            List<StudentRegistration> studentRegistrations = studentRegistrationDao.findByMusicGroupIds(groupIds, StudentMusicGroupStatusEnum.NORMAL);
            Map<String, Long> groupStudentNumMap = studentRegistrations.stream().collect(Collectors.groupingBy(StudentRegistration::getMusicGroupId, Collectors.counting()));

            BigDecimal oneHundred = new BigDecimal(100);
            BigDecimal zero = new BigDecimal("0.00");

            List<EduHomeworkCardDto> courseHomeworkStudentNumList = studentCourseHomeworkDao.countHomeworkStudentInfoWithMusicGroup(groupIds, queryInfo.getStartTime(), queryInfo.getEndTime());
            List<EduHomeworkCardDto> homeworkStudentNumList = extracurricularExercisesReplyDao.countEduHomeworkStudentNumWithMusicGroup(groupIds, queryInfo.getStartTime(), queryInfo.getEndTime(), queryInfo.getTenantId());
            homeworkStudentNumList.addAll(courseHomeworkStudentNumList);
            Map<String, List<EduHomeworkCardDto>> groupStudentListMap = homeworkStudentNumList.stream().collect(Collectors.groupingBy(EduHomeworkCardDto::getGroupId));
            for (MusicGroup mg : musicGroups) {
                EduHomeworkStatDto ehs = new EduHomeworkStatDto();
                ehs.setGroupId(mg.getId());
                ehs.setGroupName(mg.getName());
                if(groupStudentNumMap.containsKey(mg.getId())){
                    ehs.setGroupStudentNum(Math.toIntExact(groupStudentNumMap.get(mg.getId())));
                }else{
                    ehs.setGroupStudentNum(0);
                }
                int exceptStudentNum = 0;
                int submitStudentNum = 0;
                if(groupStudentListMap.containsKey(mg.getId())){
                    List<EduHomeworkCardDto> eduHomeworkCardDtos = groupStudentListMap.get(mg.getId());
                    for (EduHomeworkCardDto eduHomeworkCardDto : eduHomeworkCardDtos) {
                        exceptStudentNum += eduHomeworkCardDto.getExceptStudentNum();
                        submitStudentNum += eduHomeworkCardDto.getSubmitStudentNum();
                    }
                }
                ehs.setExceptStudentNum(exceptStudentNum);
                ehs.setSubmitStudentNum(submitStudentNum);
                if(exceptStudentNum<=0){
                    ehs.setSubmitRate(zero);
                }else{
                    ehs.setSubmitRate(new BigDecimal(submitStudentNum).divide(new BigDecimal(exceptStudentNum), CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP).multiply(oneHundred));
                }
                dataList.add(ehs);
            }
        }

        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public List<EduHomeworkStatDto> queryEduHomeworkStatDetail(StudentCourseHomeWorkQueryInfo queryInfo) {
        List<EduHomeworkStatDto> dataList = new ArrayList<>();
        MusicGroup musicGroup = musicGroupDao.get(queryInfo.getGroupId());
        if(Objects.isNull(musicGroup)){
            return dataList;
        }
        List<StudentRegistration> studentRegistrations = studentRegistrationDao.findByMusicGroupIds(Arrays.asList(queryInfo.getGroupId()), StudentMusicGroupStatusEnum.NORMAL);
        Map<Integer, Long> subjectStudentNumMap = studentRegistrations.stream().collect(Collectors.groupingBy(StudentRegistration::getActualSubjectId, Collectors.counting()));

        Map<Integer, Subject> idSubjectMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(subjectStudentNumMap)){
            List<Subject> subjects = subjectDao.findBySubjectIds(new ArrayList<>(subjectStudentNumMap.keySet()));
            idSubjectMap = subjects.stream().collect(Collectors.toMap(Subject::getId, s -> s, (s1, s2) -> s1));
        }

        BigDecimal oneHundred = new BigDecimal(100);
        BigDecimal zero = new BigDecimal("0.00");

        List<EduHomeworkCardDto> courseHomeworkStudentNumList = studentCourseHomeworkDao.countHomeworkSubjectStudentInfoWithMusicGroup(queryInfo.getGroupId(), queryInfo.getStartTime(), queryInfo.getEndTime());
        List<EduHomeworkCardDto> homeworkStudentNumList = extracurricularExercisesReplyDao.countEduHomeworkSubjectStudentNumWithMusicGroup(queryInfo.getGroupId(), queryInfo.getStartTime(), queryInfo.getEndTime());
        homeworkStudentNumList.addAll(courseHomeworkStudentNumList);
        Map<Integer, List<EduHomeworkCardDto>> subjectStudentListMap = homeworkStudentNumList.stream().collect(Collectors.groupingBy(EduHomeworkCardDto::getSubjectId));
        for (Map.Entry<Integer, Long> subjectStudentNumEntry : subjectStudentNumMap.entrySet()) {
            EduHomeworkStatDto ehs = new EduHomeworkStatDto();
            if(idSubjectMap.containsKey(subjectStudentNumEntry.getKey())){
                ehs.setSubjectName(idSubjectMap.get(subjectStudentNumEntry.getKey()).getName());
            }
            ehs.setGroupId(queryInfo.getGroupId());
            ehs.setGroupName(musicGroup.getName());
            if(subjectStudentNumMap.containsKey(subjectStudentNumEntry.getKey())){
                ehs.setGroupStudentNum(Math.toIntExact(subjectStudentNumMap.get(subjectStudentNumEntry.getKey())));
            }else{
                ehs.setGroupStudentNum(0);
            }
            int exceptStudentNum = 0;
            int submitStudentNum = 0;
            if(subjectStudentListMap.containsKey(subjectStudentNumEntry.getKey())){
                List<EduHomeworkCardDto> eduHomeworkCardDtos = subjectStudentListMap.get(subjectStudentNumEntry.getKey());
                for (EduHomeworkCardDto eduHomeworkCardDto : eduHomeworkCardDtos) {
                    exceptStudentNum += eduHomeworkCardDto.getExceptStudentNum();
                    submitStudentNum += eduHomeworkCardDto.getSubmitStudentNum();
                }
            }
            ehs.setExceptStudentNum(exceptStudentNum);
            ehs.setSubmitStudentNum(submitStudentNum);
            if(exceptStudentNum<=0){
                ehs.setSubmitRate(zero);
            }else{
                ehs.setSubmitRate(new BigDecimal(submitStudentNum).divide(new BigDecimal(exceptStudentNum), CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP).multiply(oneHundred));
            }
            dataList.add(ehs);
        }
        return dataList;
    }
}
