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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.CourseGroupCreateDto;
import com.ym.mec.biz.dal.dto.CourseGroupTeacherCardDto;
import com.ym.mec.biz.dal.dto.CourseTimeDto;
import com.ym.mec.biz.dal.dto.GroupCourseTimesDto;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.service.CourseScheduleService;
import com.ym.mec.biz.service.CoursesGroupService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CoursesGroupServiceImpl extends BaseServiceImpl<Long, CoursesGroup> implements CoursesGroupService {

    @Autowired
    private CoursesGroupDao coursesGroupDao;
    @Autowired
    private CourseScheduleService courseScheduleService;
    @Autowired
    private ClassGroupDao classGroupDao;
    @Autowired
    private ClassGroupTeacherMapperDao classGroupTeacherMapperDao;
    @Autowired
    private CourseScheduleDao courseScheduleDao;
    @Autowired
    private CourseScheduleTeacherSalaryDao courseScheduleTeacherSalaryDao;
    @Autowired
    private TeacherAttendanceDao teacherAttendanceDao;
    @Autowired
    private SubjectDao subjectDao;
    @Autowired
    private ClassGroupStudentMapperDao classGroupStudentMapperDao;

    @Override
    public BaseDAO<Long, CoursesGroup> getDAO() {
        return coursesGroupDao;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void createCourseGroup(CourseGroupCreateDto courseGroupCreateInfo) {
        CoursesGroup courseGroup = courseGroupCreateInfo.getCoursesGroup();
        CourseGenerateDto courseCycleInfo = courseGroupCreateInfo.getCourseCycleInfo();
        if(Objects.isNull(courseGroup.getName())|| StringUtils.isBlank(courseGroup.getName())){
            throw new BizException("请填写课程班名称");
        }
        if(Objects.isNull(courseGroup.getSubjectId())){
            throw new BizException("请选择科目");
        }
        if(Objects.isNull(courseGroup.getMaxStudentNum())){
            throw new BizException("请填写班级人数");
        }
        if(Objects.isNull(courseCycleInfo.getSingleClassMinutes())){
            throw new BizException("请填写课程时长");
        }
        if(Objects.isNull(courseCycleInfo.getCourseCreateStartTime())){
            throw new BizException("请填写课程开始时间");
        }
        if(Objects.isNull(courseCycleInfo.getCourseCount())){
            throw new BizException("请填写课程数量");
        }

        //总课程时长
        Integer totalCourseTime=courseCycleInfo.getCourseCount()*courseCycleInfo.getSingleClassMinutes();

        Date now=new Date();
        courseGroup.setSingleClassMinutes(courseCycleInfo.getSingleClassMinutes());
        courseGroup.setStatus(GroupStatusEnum.APPLYING);
        List<CourseSchedule> newCourses = courseScheduleService.createCourses(courseGroupCreateInfo.getCourseCycleInfo());
        for (CourseSchedule newCourse : newCourses) {
            newCourse.setTeachMode(TeachModeEnum.ONLINE);
            newCourse.setGroupType(GroupType.COMM);
            newCourse.setType(CourseSchedule.CourseScheduleType.COMM);
            newCourse.setTeacherId(courseGroup.getTeacherId());
            newCourse.setActualTeacherId(courseGroup.getTeacherId());
            newCourse.setIsLock(1);
            newCourse.setStatus(CourseStatusEnum.NOT_START);
            newCourse.setName(courseGroup.getName());
        }
        courseScheduleService.checkNewCourseSchedules(newCourses,false);

        CourseSchedule firstCourseSchedule = newCourses.stream().min(Comparator.comparing(CourseSchedule::getStartClassTime)).get();
        CourseSchedule latestCourseSchedule = newCourses.stream().max(Comparator.comparing(CourseSchedule::getEndClassTime)).get();
        courseGroup.setCoursesStartDate(firstCourseSchedule.getStartClassTime());
        courseGroup.setCoursesEndDate(latestCourseSchedule.getEndClassTime());

        JSONArray courseTimesArray=new JSONArray();
        for (CourseTimeDto courseTime : courseCycleInfo.getCourseTimes()) {
            JSONObject courseTimeObject=new JSONObject();
            courseTimeObject.put(String.valueOf(courseTime.getDayOfWeek()),courseTime.getStartClassTime());
            courseTimesArray.add(courseTimeObject);
        }

        coursesGroupDao.insert(courseGroup);
        //创建班级信息
        ClassGroup classGroup = new ClassGroup();
        classGroup.setSubjectIdList(courseGroup.getSubjectId().toString());
        classGroup.setExpectStudentNum(1);
        classGroup.setStudentNum(1);
        classGroup.setName(courseGroup.getName());
        classGroup.setTotalClassTimes(courseCycleInfo.getCourseCount());
        classGroup.setType(ClassGroupTypeEnum.COMM);
        classGroup.setDelFlag(0);
        classGroup.setGroupType(GroupType.COMM);
        classGroup.setMusicGroupId(courseGroup.getId().toString());
        classGroup.setCreateTime(now);
        classGroup.setUpdateTime(now);
        classGroupDao.insert(classGroup);

        //创建班级老师关联记录
        ClassGroupTeacherMapper classGroupTeacherMapper = new ClassGroupTeacherMapper();
        classGroupTeacherMapper.setMusicGroupId(courseGroup.getId().toString());
        classGroupTeacherMapper.setClassGroupId(classGroup.getId());
        classGroupTeacherMapper.setTeacherRole(TeachTypeEnum.BISHOP);
        classGroupTeacherMapper.setUserId(courseGroup.getTeacherId());
        classGroupTeacherMapper.setGroupType(GroupType.COMM);
        classGroupTeacherMapper.setCreateTime(now);
        classGroupTeacherMapper.setUpdateTime(now);
        classGroupTeacherMapperDao.insert(classGroupTeacherMapper);

        List<CourseScheduleTeacherSalary> courseScheduleTeacherSalaries = new ArrayList<>();
        List<TeacherAttendance> teacherAttendances = new ArrayList<>();

        for (CourseSchedule courseSchedule : newCourses) {
            //课表
            courseSchedule.setMusicGroupId(courseGroup.getId().toString());
            courseSchedule.setClassGroupId(classGroup.getId());
            courseSchedule.setCreateTime(now);
            courseSchedule.setUpdateTime(now);
        }
        courseScheduleDao.batchAddCourseSchedules(newCourses);

        for (CourseSchedule courseSchedule : newCourses) {
            //课程与老师薪水表
            CourseScheduleTeacherSalary courseScheduleTeacherSalary = new CourseScheduleTeacherSalary();
            courseScheduleTeacherSalary.setCourseScheduleId(courseSchedule.getId());
            courseScheduleTeacherSalary.setGroupType(GroupType.COMM);
            courseScheduleTeacherSalary.setMusicGroupId(courseGroup.getId().toString());
            courseScheduleTeacherSalary.setTeacherRole(classGroupTeacherMapper.getTeacherRole());
            courseScheduleTeacherSalary.setUserId(courseGroup.getTeacherId());
            courseScheduleTeacherSalary.setExpectSalary(BigDecimal.ZERO);
            courseScheduleTeacherSalary.setCreateTime(now);
            courseScheduleTeacherSalary.setUpdateTime(now);
            courseScheduleTeacherSalary.setClassGroupId(classGroup.getId());
            courseScheduleTeacherSalaries.add(courseScheduleTeacherSalary);

            //教师签到记录
            TeacherAttendance teacherAttendance = new TeacherAttendance();
            teacherAttendance.setMusicGroupId(courseGroup.getId().toString());
            teacherAttendance.setTeacherId(courseGroup.getTeacherId());
            teacherAttendance.setClassGroupId(classGroup.getId());
            teacherAttendance.setGroupType(GroupType.COMM);
            teacherAttendance.setCourseScheduleId(courseSchedule.getId());
            teacherAttendance.setCreateTime(now);
            teacherAttendances.add(teacherAttendance);
        }
        courseScheduleTeacherSalaryDao.batchInsert(courseScheduleTeacherSalaries);
        teacherAttendanceDao.batchInsert(teacherAttendances);
    }

    @Override
    public List<CourseGroupTeacherCardDto> findTeacherCourseGroups(Integer teacherId) {
        if(Objects.isNull(teacherId)){
            throw new BizException("请指定老师");
        }
        List<CoursesGroup> teacherCourseGroups = coursesGroupDao.findTeacherCourseGroups(teacherId);
        if (CollectionUtils.isEmpty(teacherCourseGroups)){
            return new ArrayList<>();
        }

        List<String> groupIds = teacherCourseGroups.stream().map(group -> String.valueOf(group.getId())).collect(Collectors.toList());

        List<Integer> subjectIds = teacherCourseGroups.stream().map(CoursesGroup::getSubjectId).collect(Collectors.toList());
        List<Subject> subjects = subjectDao.findBySubjectIds(subjectIds);
        Map<Integer, Subject> idSubjectMap = subjects.stream().collect(Collectors.toMap(Subject::getId, subject -> subject));

        List<ClassGroupStudentMapper> students = classGroupStudentMapperDao.findByGroups(groupIds, GroupType.COMM);
        Map<String, List<ClassGroupStudentMapper>> groupStudentsMap = students.stream().collect(Collectors.groupingBy(ClassGroupStudentMapper::getMusicGroupId));

        List<GroupCourseTimesDto> groupsCourseTimesInfo = courseScheduleDao.findGroupsCourseTimesInfo(groupIds, GroupType.COMM);
        Map<String, GroupCourseTimesDto> groupCourseTimesInfoMap = groupsCourseTimesInfo.stream().collect(Collectors.toMap(GroupCourseTimesDto::getGroupId, e -> e));

        List<CourseGroupTeacherCardDto> groupCards=new ArrayList<>();
        for (CoursesGroup teacherCourseGroup : teacherCourseGroups) {
            CourseGroupTeacherCardDto groupCard=new CourseGroupTeacherCardDto();
            groupCard.setId(teacherCourseGroup.getId());
            groupCard.setName(teacherCourseGroup.getName());
            groupCard.setSingleClassMinutes(teacherCourseGroup.getSingleClassMinutes());
            groupCard.setCoursesStartDate(teacherCourseGroup.getCoursesStartDate());
            groupCard.setCoursesEndDate(teacherCourseGroup.getCoursesEndDate());
            groupCard.setSubjectId(teacherCourseGroup.getSubjectId());
            groupCard.setSubjectName(idSubjectMap.get(teacherCourseGroup.getSubjectId()).getName());
            GroupCourseTimesDto groupCourseTimesInfo = groupCourseTimesInfoMap.get(String.valueOf(teacherCourseGroup.getId()));
            groupCard.setTotalCourseTimes(groupCourseTimesInfo.getTotalCourseTimes());
            groupCard.setSurplusClassTimes(groupCourseTimesInfo.getSurplusClassTimes());
            List<ClassGroupStudentMapper> groupStudents = groupStudentsMap.get(String.valueOf(teacherCourseGroup.getId()));
            if(!CollectionUtils.isEmpty(groupStudentsMap)){
                List<String> userNames = groupStudents.stream().map(ClassGroupStudentMapper::getUserName).collect(Collectors.toList());
                groupCard.setStudentNames(StringUtils.join(userNames,","));
            }
            groupCards.add(groupCard);
        }
        return groupCards;
    }
}
