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

import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.MessageTypeEnum;
import com.ym.mec.biz.dal.enums.YesOrNoEnum;
import com.ym.mec.biz.dal.page.CourseHomeworkQueryInfo;
import com.ym.mec.biz.service.CourseHomeworkService;
import com.ym.mec.biz.service.StudentCourseHomeworkService;
import com.ym.mec.biz.service.StudentServeService;
import com.ym.mec.biz.service.SysMessageService;
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;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
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.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import com.ym.mec.biz.dal.entity.CourseSchedule.CourseScheduleType;

@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 StudentExtracurricularExercisesSituationDao studentExtracurricularExercisesSituationDao;
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private SubjectDao subjectDao;
    @Autowired
    private StudentServeService studentServeService;

    @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)>=14){
            throw new BizException("该作业已超出可提交时间范围，无法提交作业。");
        }

//        boolean push = Objects.isNull(existHomework.getAttachments());
        boolean push = true;
        bean.setSubmitTime(now);
        super.update(bean);
        bean = studentCourseHomeworkDao.get(bean.getId());
        CourseSchedule courseSchedule = courseScheduleDao.get(bean.getCourseScheduleId());

        CourseHomework courseHomework = courseHomeworkDao.get(bean.getCourseHomeworkId());
        courseHomework.setGroupType(courseSchedule.getGroupType());
        courseHomework.setCompletedNum(studentCourseHomeworkDao.countCompletedStudentNum(bean.getCourseHomeworkId()));
        courseHomeworkService.update(courseHomework);

        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(existHomework.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){
//            StudentExtracurricularExercisesSituation studentExercisesSituation = studentExtracurricularExercisesSituationDao.findStudentExercisesSituationsWithMonDay(createMonday.toString(), existHomework.getUserId());
//            if(Objects.nonNull(studentExercisesSituation)){
//                studentExercisesSituation.setExercisesReplyNum(1);
//                studentExercisesSituation.setLastSubmitTime(now);
//                studentExtracurricularExercisesSituationDao.update(studentExercisesSituation);
//            }
//        }

        studentServeService.updateExercisesSituation(courseSchedule.getClassDate(), new ArrayList<>(Arrays.asList(bean.getUserId())), courseSchedule.getTeacherId());

//        CourseHomework temp = courseHomeworkService.get(courseHomework.getId());
//        if (temp.getExpectNum().equals(courseHomework.getCompletedNum())) {
        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.batchSendImMessage(MessageTypeEnum.IM_HOMEWORK_SUBMIT_PUSH,bean.getUserId().toString(),extra,
                    new String[]{courseSchedule.getActualTeacherId().toString()},
                    null,courseDate,courseSchedule.getName());
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.HOMEWORK_SUBMIT_PUSH,
                    userMap, null, 0, notifyUrl, "TEACHER", courseSchedule.getName(), courseDate, user.getUsername());

            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("作业不存在");
        }
        CourseHomeworkStudentDetailDto courseHomeworkStudentDetail = studentCourseHomeworkDao.findCourseHomeworkStudentDetail(courseScheduleID, userId);
        if(Objects.nonNull(courseHomeworkStudentDetail)){
            SysUser student = teacherDao.getUser(userId.intValue());
            courseHomeworkStudentDetail.setStudentId(userId.intValue());
            courseHomeworkStudentDetail.setStudentName(student.getUsername());
            CourseSchedule courseSchedule = courseScheduleDao.get(courseHomeworkStudentDetail.getCourseScheduleId());
            if(Objects.nonNull(courseSchedule)){
                SysUser teacher = teacherDao.getUser(courseSchedule.getActualTeacherId());
                courseHomeworkStudentDetail.setTeacherId(courseSchedule.getActualTeacherId());
                courseHomeworkStudentDetail.setTeacherName(teacher.getRealName());
            }
        }
        courseHomeworkStudentDetail.setType("HOMEWORK");
        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<=12){
            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){
                StudentExtracurricularExercisesSituation studentExercisesSituation = studentExtracurricularExercisesSituationDao.findStudentExercisesSituationsWithMonDay(createMonday.toString(), byStudentAndCourseHomewok.getUserId());
                if(Objects.nonNull(studentExercisesSituation)){
                    if(YesOrNoEnum.YES.equals(byStudentAndCourseHomewok.getIsReplied())){
                        studentExercisesSituation.setExercisesMessageNum(1);
                    }
                    if(new Integer(1).equals(byStudentAndCourseHomewok.getIsRepliedTimely())){
                        studentExercisesSituation.setExercisesMessageTimelyNum(1);
                    }
                    studentExtracurricularExercisesSituationDao.update(studentExercisesSituation);
                }
            }
        }
        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, String userName) {
        if (Objects.isNull(courseSchedule)) {
            throw new BizException("请指定课程");
        }
        return studentCourseHomeworkDao.findByCourseSchedule(courseSchedule, 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);
                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;
    }
}
