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

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.ExtraExercilseQueryInfo;
import com.ym.mec.biz.dal.page.ExtraExercilseReplyQueryInfo;
import com.ym.mec.biz.service.ExtracurricularExercisesReplyService;
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.service.impl.BaseServiceImpl;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
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;

@Service
public class ExtracurricularExercisesReplyServiceImpl extends BaseServiceImpl<Long, ExtracurricularExercisesReply> implements ExtracurricularExercisesReplyService {
	
	@Autowired
	private ExtracurricularExercisesReplyDao extracurricularExercisesReplyDao;
	@Autowired
	private ExtracurricularExercisesDao extracurricularExercisesDao;
	@Autowired
	private ExtracurricularExercisesMessageDao extracurricularExercisesMessageDao;
	@Autowired
	private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;
	@Autowired
	private StudentExtracurricularExercisesSituationDao studentExtracurricularExercisesSituationDao;
	@Autowired
	private SysMessageService sysMessageService;
	@Autowired
	private TeacherDao teacherDao;
	@Autowired
	private StudentDao studentDao;
	@Autowired
	private CourseScheduleDao courseScheduleDao;
	@Autowired
	private StudentServeService studentServeService;

	@Override
	public BaseDAO<Long, ExtracurricularExercisesReply> getDAO() {
		return extracurricularExercisesReplyDao;
	}

	@Override
	public List<StudentCourseHomework> findExtraExerciseStudents(Long extraExerciseId, String studentName) {
		if(Objects.isNull(extraExerciseId)){
			throw new BizException("请选择课外训练");
		}
		List<ExtraExerciseStudentsDto> extraExerciseStudents = extracurricularExercisesReplyDao.findExtraExerciseStudents(extraExerciseId, studentName);
		List<StudentCourseHomework> studentCourseHomeworks=new ArrayList<>();
		for (ExtraExerciseStudentsDto extraExerciseStudent : extraExerciseStudents) {
			StudentCourseHomework studentCourseHomework=new StudentCourseHomework();
			studentCourseHomework.setId(extraExerciseStudent.getId());
			studentCourseHomework.setUserId(extraExerciseStudent.getUserId());
			studentCourseHomework.setUserName(extraExerciseStudent.getStudentName());
			studentCourseHomework.setStatus(extraExerciseStudent.getStatus()==0?YesOrNoEnum.NO:YesOrNoEnum.YES);
			studentCourseHomework.setIsReplied(extraExerciseStudent.getIsReplied()==0?YesOrNoEnum.NO:YesOrNoEnum.YES);
			studentCourseHomework.setIsView(extraExerciseStudent.getIsView()==0?YesOrNoEnum.NO:YesOrNoEnum.YES);
			studentCourseHomeworks.add(studentCourseHomework);
		}
		return studentCourseHomeworks;
	}

	@Override
	public CourseHomeworkStudentDetailDto findStudentExtraExerciseDetail(Long studentExerciseId) {
		ExtraExerciseStudentsDto extraExerciseReply = extracurricularExercisesReplyDao.findExtraExerciseReply(studentExerciseId);
		if(extraExerciseReply == null){
			throw new BizException("找不到学生作业记录");
		}
		CourseHomeworkStudentDetailDto detail=new CourseHomeworkStudentDetailDto();
		detail.setCourseHomeworkId(extraExerciseReply.getId());
		detail.setClassGroupName(extraExerciseReply.getTitle() + "•" + extraExerciseReply.getStudentName());
		detail.setContent(extraExerciseReply.getContent());
		detail.setAttachments(extraExerciseReply.getAttachments());
		detail.setStatus(extraExerciseReply.getStatus()==0?YesOrNoEnum.NO:YesOrNoEnum.YES);
		detail.setIsReplied(extraExerciseReply.getIsReplied()==0?YesOrNoEnum.NO:YesOrNoEnum.YES);
		detail.setTeacherId(extraExerciseReply.getTeacherId());
		Teacher teacher = teacherDao.get(extraExerciseReply.getTeacherId());
		detail.setTeacherName(teacher.getRealName());
		detail.setStudentId(extraExerciseReply.getUserId());
		detail.setStudentName(extraExerciseReply.getStudentName());
		detail.setExpiryDate(extraExerciseReply.getExpireDate());
		detail.setType("EXTRA");
		return detail;
	}

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

		List<ExtraExerciseStudentsDto> dataList = null;
		int count = extracurricularExercisesReplyDao.countStudentExtraExercises(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = extracurricularExercisesReplyDao.findStudentExtraExercises(params);
		}
		if (count == 0) {
			dataList = new ArrayList<>();
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void submitExtraExercise(ExtracurricularExercisesReply extracurricularExercisesReply) {
		if(Objects.isNull(extracurricularExercisesReply.getId())){
			throw new BizException("请选择课外训练");
		}
		if(StringUtils.isBlank(extracurricularExercisesReply.getAttachments())){
			throw new BizException("请先提交作业文件");
		}
		ExtracurricularExercisesReply existExtra = extracurricularExercisesReplyDao.get(extracurricularExercisesReply.getId());
		if(Objects.isNull(existExtra)){
			throw new BizException("作业不存在");
		}
//		boolean push=Objects.isNull(existExtra.getAttachments());
		boolean push=true;
		ExtracurricularExercises extracurricularExercises = extracurricularExercisesDao.get(existExtra.getExtracurricularExercisesId());
		if(Objects.isNull(extracurricularExercises)){
			throw new BizException("作业不存在");
		}
		Date now=new Date();
		if (DateUtil.daysBetween(extracurricularExercises.getCreateTime(), now)>=14){
			throw new BizException("该作业已超出可提交时间范围，无法提交作业。");
		}
		existExtra.setAttachments(extracurricularExercisesReply.getAttachments());
		existExtra.setStatus(1);
		existExtra.setSubmitTime(new Date());
		extracurricularExercisesReplyDao.update(existExtra);

		LocalDate nowDate = LocalDateTime.now(DateUtil.zoneId).toLocalDate();
		LocalDate monDayDate = nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
		LocalDate createDateTime = LocalDateTime.ofInstant(existExtra.getCreateTime().toInstant(), DateUtil.zoneId).toLocalDate();
		LocalDate createMonday = createDateTime.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
//		if(createDateTime.isBefore(monDayDate)){
//			StudentExtracurricularExercisesSituation studentExercisesSituation = studentExtracurricularExercisesSituationDao.findStudentExercisesSituationsWithMonDay(createMonday.toString(), existExtra.getUserId());
//			if(Objects.nonNull(studentExercisesSituation)){
//				studentExercisesSituation.setExercisesReplyNum(1);
//				studentExercisesSituation.setLastSubmitTime(now);
//				studentExtracurricularExercisesSituationDao.update(studentExercisesSituation);
//			}
//		}

		int submitStudentNum=extracurricularExercisesReplyDao.countIsSubmitStudents(existExtra.getExtracurricularExercisesId());
		extracurricularExercises.setCompletedNum(submitStudentNum);
		extracurricularExercisesDao.update(extracurricularExercises);

		studentServeService.updateExercisesSituation(extracurricularExercises.getCreateTime(), Arrays.asList(existExtra.getUserId()), extracurricularExercises.getTeacherId());

		if(push){
			Map<Integer, String> userMap = new HashMap<>();
			userMap.put(extracurricularExercises.getTeacherId(), extracurricularExercises.getTeacherId().toString());
			SysUser user = teacherDao.getUser(existExtra.getUserId());
			String notifyUrl = "?courseScheduleID=" + existExtra.getId() + "&userId=" + existExtra.getUserId() + "&studentCourseHomeworkId=" + existExtra.getId()+ "&extra=1";
			sysMessageService.batchSendImMessage(MessageTypeEnum.EXTRA_SUBMIT_IM,existExtra.getUserId().toString(),"dayaedu"+notifyUrl,
					new String[]{extracurricularExercises.getTeacherId().toString()},
					null,extracurricularExercises.getTitle());
			sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.EXTRA_SUBMIT_PUSH,
					userMap, null, 0, 9+notifyUrl, "TEACHER",
					extracurricularExercises.getTitle(), user.getUsername());
		}
	}

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

		List<ExtraExerciseStudentsDto> dataList = null;
		int count = extracurricularExercisesReplyDao.countExtraExercises(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = extracurricularExercisesReplyDao.findExtraExercises(params);
			List<Long> replyIds = dataList.stream().map(ExtraExerciseStudentsDto::getId).collect(Collectors.toList());
			List<Integer> teacherIds = dataList.stream().map(ExtraExerciseStudentsDto::getTeacherId).collect(Collectors.toList());
			List<SimpleUserDto> teachers = teacherDao.findSimpleTeachers(teacherIds);
			Map<Integer, String> idNameMap = teachers.stream().collect(Collectors.toMap(SimpleUserDto::getUserId, SimpleUserDto::getUserName));
			for (ExtraExerciseStudentsDto extraExerciseStudentsDto : dataList) {
				extraExerciseStudentsDto.setTeacherName(idNameMap.get(extraExerciseStudentsDto.getTeacherId()));
				if(Objects.nonNull(queryInfo.getExistVipCourse())){
					extraExerciseStudentsDto.setExistVipCourse(queryInfo.getExistVipCourse());
				}
			}
			if(Objects.isNull(queryInfo.getExistVipCourse())){
				List<Integer> studentIds = dataList.stream().map(ExtraExerciseStudentsDto::getUserId).collect(Collectors.toList());
				List<Map<Integer, Long>> studentVipCoursesMaps = courseScheduleDao.countStudentVipCoursesInFuture(studentIds);
				Map<Integer, Long> studentVipCourseMap = MapUtil.convertIntegerMap(studentVipCoursesMaps);
				for (ExtraExerciseStudentsDto exercisesSituationDto : dataList) {
					Long vipCourses=studentVipCourseMap.get(exercisesSituationDto.getUserId());
					if(Objects.isNull(vipCourses)||vipCourses<=0){
						exercisesSituationDto.setExistVipCourse(0);
					}else{
						exercisesSituationDto.setExistVipCourse(1);
					}
				}
			}
		}
		if (count == 0) {
			dataList = new ArrayList<>();
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void exercisesSituationStatistics() {
		LocalDate nowDate = LocalDateTime.now(DateUtil.zoneId).toLocalDate();
		if(nowDate.getDayOfWeek()==DayOfWeek.MONDAY){
			nowDate = nowDate.plusDays(-1);
			int lastWeekTodayUpdateNum = studentExtracurricularExercisesSituationDao.findLastWeekTodayUpdateNum(nowDate.toString());
			if(lastWeekTodayUpdateNum>0){
				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());
		List<Practice4ExercisesSituationDto> noPracticeStudents = courseScheduleStudentPaymentDao.findNoPracticeStudentIdsOnWeek(monDayDate.toString(),sunDayDate.toString());
		if(CollectionUtils.isEmpty(noPracticeStudents)){
			return;
		}
		Map<Integer, List<Practice4ExercisesSituationDto>> studentCourseMap = noPracticeStudents.stream().filter(e->Objects.nonNull(e.getCourseStartTime())).collect(Collectors.groupingBy(Practice4ExercisesSituationDto::getUserId));

		List<ExtracurricularExercisesReply> noPracticeStudentExercisesInWeek = extracurricularExercisesReplyDao.findNoPracticeStudentExercisesInWeek(monDayDate.toString(), sunDayDate.toString());
		Map<Integer, List<ExtracurricularExercisesReply>> studentExercisesMap = noPracticeStudentExercisesInWeek.stream().collect(Collectors.groupingBy(ExtracurricularExercisesReply::getUserId));

		List<StudentExtracurricularExercisesSituation> results=new ArrayList<>();
		for (Map.Entry<Integer, List<Practice4ExercisesSituationDto>> studentCourseEntry : studentCourseMap.entrySet()) {
			StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation();
			studentExtracurricularExercisesSituation.setStudentId(studentCourseEntry.getKey());
			studentCourseEntry.getValue().sort(Comparator.comparing(Practice4ExercisesSituationDto::getCourseStartTime).reversed());
			studentExtracurricularExercisesSituation.setTeacherId(studentCourseEntry.getValue().get(0).getActualTeacherId());
			studentExtracurricularExercisesSituation.setExpectExercisesNum(1);
			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"));
			List<ExtracurricularExercisesReply> studentExercises = studentExercisesMap.get(studentCourseEntry.getKey());
			if(CollectionUtils.isEmpty(studentExercises)){
				studentExtracurricularExercisesSituation.setActualExercisesNum(0);
				studentExtracurricularExercisesSituation.setExercisesReplyNum(0);
				studentExtracurricularExercisesSituation.setExercisesMessageNum(0);
				studentExtracurricularExercisesSituation.setExercisesMessageTimelyNum(0);
				results.add(studentExtracurricularExercisesSituation);
				continue;
			}
			studentExtracurricularExercisesSituation.setActualExercisesNum(1);
			long replyNum = studentExercises.stream().filter(e -> e.getStatus()==1).count();
			studentExtracurricularExercisesSituation.setExercisesReplyNum(replyNum>0?1:0);
			int exercisesMessageNum=0;
			int exercisesMessageTimelyNum=0;
			for (ExtracurricularExercisesReply studentExercise : studentExercises) {
				if(!new Integer(1).equals(studentExercise.getStatus())){
					continue;
				}
				if(!new Integer(1).equals(studentExercise.getIsReplied())){
					continue;
				}
				exercisesMessageNum+=1;
				if(new Integer(1).equals(studentExercise.getIsRepliedTimely())){
					exercisesMessageTimelyNum+=1;
				}
			}
			studentExtracurricularExercisesSituation.setExercisesMessageNum(exercisesMessageNum>0?1:0);
			studentExtracurricularExercisesSituation.setExercisesMessageTimelyNum(exercisesMessageTimelyNum>0?1:0);
			results.add(studentExtracurricularExercisesSituation);
		}
		studentExtracurricularExercisesSituationDao.deleteByMonday(monDayDate.toString(),null);
		studentExtracurricularExercisesSituationDao.batchInsert(results);
	}

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

		if(nowDate.getDayOfWeek()==DayOfWeek.MONDAY){
			int lastWeekTodayUpdateNum = studentExtracurricularExercisesSituationDao.findLastWeekTodayUpdateNum(nowDate.plusDays(-1).toString());
			if(lastWeekTodayUpdateNum<=0){
				nowDate = nowDate.plusDays(-1);
			}
		}

		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());

		List<Student> serviceStudents = studentDao.getServiceStudents();
		if(CollectionUtils.isEmpty(serviceStudents)){
			return;
		}

		List<StudentServiceHomeworkDto> studentHomeworksInWeek = extracurricularExercisesReplyDao.findStudentHomewarksInWeek(monDayDate.toString(), sunDayDate.toString());
		Map<Integer, List<StudentServiceHomeworkDto>> studentExercisesMap = studentHomeworksInWeek.stream().collect(Collectors.groupingBy(StudentServiceHomeworkDto::getUserId));

		List<StudentExtracurricularExercisesSituation> results=new ArrayList<>();
		for (Student serviceStudent : serviceStudents) {
			StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation();
			studentExtracurricularExercisesSituation.setStudentId(serviceStudent.getUserId());
			studentExtracurricularExercisesSituation.setTeacherId(serviceStudent.getTeacherId());
			studentExtracurricularExercisesSituation.setExpectExercisesNum(1);
			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"));
			List<StudentServiceHomeworkDto> studentHomeworks = studentExercisesMap.get(serviceStudent.getUserId());
			if(CollectionUtils.isEmpty(studentHomeworks)){
				studentExtracurricularExercisesSituation.setActualExercisesNum(0);
				studentExtracurricularExercisesSituation.setExercisesReplyNum(0);
				studentExtracurricularExercisesSituation.setExercisesMessageNum(0);
				studentExtracurricularExercisesSituation.setExercisesMessageTimelyNum(0);
				results.add(studentExtracurricularExercisesSituation);
				continue;
			}
			studentExtracurricularExercisesSituation.setActualExercisesNum(1);
			long replyNum = studentHomeworks.stream().filter(e -> e.getStatus()==1).count();
			studentExtracurricularExercisesSituation.setExercisesReplyNum(replyNum>0?1:0);
			int exercisesMessageNum=0;
			int exercisesMessageTimelyNum=0;
			for (StudentServiceHomeworkDto studentHomework : studentHomeworks) {
				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;
				}
			}
			studentExtracurricularExercisesSituation.setExercisesMessageNum(exercisesMessageNum>0?1:0);
			studentExtracurricularExercisesSituation.setExercisesMessageTimelyNum(exercisesMessageTimelyNum>0?1:0);
			results.add(studentExtracurricularExercisesSituation);
		}

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

		BigDecimal currentPage=BigDecimal.ONE,
                pageSize=new BigDecimal(10000),
                total=new BigDecimal(results.size()),
                totalPage=total.divide(pageSize, BigDecimal.ROUND_UP);
        while (currentPage.compareTo(totalPage)<=0){
            List<StudentExtracurricularExercisesSituation> rows=results.stream().skip(pageSize.multiply(currentPage.subtract(BigDecimal.ONE)).longValue()).limit(pageSize.longValue()).collect(Collectors.toList());
            studentExtracurricularExercisesSituationDao.batchInsert(rows);
            currentPage=currentPage.add(BigDecimal.ONE);
        }
	}
}
