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

import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.StudentEduTeacherDto;
import com.ym.mec.biz.dal.dto.StudentExercisesSituationDto;
import com.ym.mec.biz.dal.dto.StudentServiceDetailDto;
import com.ym.mec.biz.dal.dto.UserGroupDto;
import com.ym.mec.biz.dal.entity.StudentExtracurricularExercisesSituation;
import com.ym.mec.biz.dal.enums.GroupType;
import com.ym.mec.biz.dal.page.StudentExercisesSituationQueryInfo;
import com.ym.mec.biz.dal.page.StudentServiceDetailQueryInfo;
import com.ym.mec.biz.service.StudentExtracurricularExercisesSituationService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.service.impl.BaseServiceImpl;
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.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;

@Service
public class StudentExtracurricularExercisesSituationServiceImpl extends BaseServiceImpl<Long, StudentExtracurricularExercisesSituation> implements StudentExtracurricularExercisesSituationService {
	
	@Autowired
	private StudentExtracurricularExercisesSituationDao studentExtracurricularExercisesSituationDao;
	@Autowired
	private ExtracurricularExercisesReplyDao extracurricularExercisesReplyDao;
	@Autowired
	private CourseScheduleDao courseScheduleDao;
	@Autowired
	private TeacherDao teacherDao;
	@Autowired
	private ClassGroupStudentMapperDao classGroupStudentMapperDao;
	@Autowired
	private StudentRegistrationDao studentRegistrationDao;

	@Override
	public BaseDAO<Long, StudentExtracurricularExercisesSituation> getDAO() {
		return studentExtracurricularExercisesSituationDao;
	}

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

		List<StudentExercisesSituationDto> dataList = null;
		int count = studentExtracurricularExercisesSituationDao.countExercisesSituations(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = studentExtracurricularExercisesSituationDao.findExercisesSituations(params);
			List<Integer> studentIds = dataList.stream().map(StudentExtracurricularExercisesSituation::getStudentId).collect(Collectors.toList());
			List<Map<Integer, Long>> studentVipCoursesMaps = courseScheduleDao.countStudentVipCoursesWithDate(studentIds, queryInfo.getMonday(), queryInfo.getSunday(), GroupType.VIP);
			Map<Integer, Long> studentVipCourseMap = MapUtil.convertIntegerMap(studentVipCoursesMaps);

			List<Map<Integer, Long>> studentPracticeCoursesMaps = courseScheduleDao.countStudentPayPracticeCoursesWithDate(studentIds, queryInfo.getMonday(), queryInfo.getSunday());
			Map<Integer, Long> studentPracticeCourseMap = MapUtil.convertIntegerMap(studentPracticeCoursesMaps);

			List<StudentEduTeacherDto> studentEducationalTeachers = classGroupStudentMapperDao.getStudentEducationalTeachers(studentIds);
			Map<Integer, List<StudentEduTeacherDto>> studentEduTeachersMap = studentEducationalTeachers.stream().collect(Collectors.groupingBy(StudentEduTeacherDto::getStudentId));

			List<UserGroupDto> allUserGroups = studentRegistrationDao.getUserGroups(studentIds);
			Map<Integer, List<UserGroupDto>> userGroupsMap = new HashMap<>();
			if(!CollectionUtils.isEmpty(allUserGroups)){
				userGroupsMap = allUserGroups.stream().collect(Collectors.groupingBy(UserGroupDto::getUserId));
			}

			for (StudentExercisesSituationDto exercisesSituationDto : dataList) {
				Long vipCourses=studentVipCourseMap.get(exercisesSituationDto.getStudentId());
				exercisesSituationDto.setExistVipCourse(Objects.isNull(vipCourses)?0:vipCourses.intValue());
				Long practiceCourses=studentPracticeCourseMap.get(exercisesSituationDto.getStudentId());
				exercisesSituationDto.setExistPracticeCourse(Objects.isNull(practiceCourses)?0:practiceCourses.intValue());
//				exercisesSituationDto.setExpectExercisesNum((int) until+1);
				List<UserGroupDto> userGroupDtos = userGroupsMap.get(exercisesSituationDto.getStudentId());
				if(!CollectionUtils.isEmpty(userGroupDtos)){
					exercisesSituationDto.setGroupNames(userGroupDtos.stream().map(UserGroupDto::getGroupName).sorted().collect(Collectors.joining(",")));
				}
				List<StudentEduTeacherDto> studentEduTeachers = studentEduTeachersMap.get(exercisesSituationDto.getStudentId());
				if(!CollectionUtils.isEmpty(studentEduTeachers)){
					List<StudentEduTeacherDto> t1 = studentEduTeachers.stream().filter(set -> set.getGroupType().equals(GroupType.VIP.getCode())||set.getGroupType().equals(GroupType.PRACTICE.getCode())).collect(Collectors.toList());
					if(!CollectionUtils.isEmpty(t1)){
						for (StudentEduTeacherDto studentEduTeacherDto : t1) {
							if(StringUtils.isNotBlank(studentEduTeacherDto.getEducationalTeacherName())){
								exercisesSituationDto.setEducationalTeacherId(studentEduTeacherDto.getEducationalTeacherId());
								exercisesSituationDto.setEducationalTeacherName(studentEduTeacherDto.getEducationalTeacherName());
								break;
							}
						}
					}
					if(StringUtils.isNoneBlank(exercisesSituationDto.getEducationalTeacherName())){
						continue;
					}
					List<StudentEduTeacherDto> t2 = studentEduTeachers.stream().filter(set -> set.getGroupType().equals(GroupType.MUSIC.getCode())).collect(Collectors.toList());
					if(!CollectionUtils.isEmpty(t2)){
						for (StudentEduTeacherDto studentEduTeacherDto : t2) {
							if(StringUtils.isNotBlank(studentEduTeacherDto.getEducationalTeacherName())){
								exercisesSituationDto.setEducationalTeacherId(studentEduTeacherDto.getEducationalTeacherId());
								exercisesSituationDto.setEducationalTeacherName(studentEduTeacherDto.getEducationalTeacherName());
								break;
							}
						}
					}
				}
			}
		}
		if (count == 0) {
			dataList = new ArrayList<>();
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

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

		List<StudentExercisesSituationDto> dataList = null;
		int count = studentExtracurricularExercisesSituationDao.countExercisesSituations(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = studentExtracurricularExercisesSituationDao.findExercisesSituations(params);
			Map<Integer, Long> studentVipCourseMap=new HashMap<>();
			if(Objects.isNull(queryInfo.getExistVipCourse())){
				List<Integer> studentIds = dataList.stream().map(StudentExtracurricularExercisesSituation::getStudentId).collect(Collectors.toList());
				List<Map<Integer, Long>> studentVipCoursesMaps = courseScheduleDao.countStudentVipCoursesWithDate(studentIds, queryInfo.getMonday(), queryInfo.getSunday(),GroupType.VIP);
				studentVipCourseMap = MapUtil.convertIntegerMap(studentVipCoursesMaps);
			}
			for (StudentExercisesSituationDto exercisesSituationDto : dataList) {
				if(Objects.isNull(queryInfo.getExistVipCourse())){
					Long vipCourses=studentVipCourseMap.get(exercisesSituationDto.getStudentId());
					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
	public List<Map<String, Object>> findServiceStudentDetail(StudentServiceDetailQueryInfo queryInfo) {
		PageInfo<StudentServiceDetailDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
		Map<String, Object> params = new HashMap<>();
		MapUtil.populateMap(params, queryInfo);

		List<StudentServiceDetailDto> dataList = null;
		int count = extracurricularExercisesReplyDao.countStudentHomeworkDetailsInTimeZone(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = extracurricularExercisesReplyDao.findStudentHomeworkDetailsInTimeZone(params);
			Map<String, List<StudentServiceDetailDto>> weekHomeworks=new HashMap<>();
			for (StudentServiceDetailDto studentServiceDetailDto : dataList) {
				if(Objects.isNull(studentServiceDetailDto.getCourseStartTime())){
					continue;
				}
				LocalDate homeworkCreateTime = LocalDateTime.ofInstant(studentServiceDetailDto.getCourseStartTime().toInstant(), DateUtil.zoneId).toLocalDate();
				String mondayStr = homeworkCreateTime.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue()).toString();
				if(!weekHomeworks.containsKey(mondayStr)){
					weekHomeworks.put(mondayStr, new ArrayList<>());
				}
				weekHomeworks.get(mondayStr).add(studentServiceDetailDto);
			}
			List<Map<String, Object>> results=new ArrayList<>();
			for (Map.Entry<String, List<StudentServiceDetailDto>> stringListEntry : weekHomeworks.entrySet()) {
				Map<String, Object> result=new HashMap<>();
				result.put("monday", stringListEntry.getKey());
				result.put("data", stringListEntry.getValue());
				results.add(result);
			}
			return results;
		}else{
			return null;
		}
	}
}
