package yangtz.cs.liu.campus.service.impl.schoolAtt;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.core.utils.HolidayDateUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import yangtz.cs.liu.campus.controller.schoolClass.SchoolClassMentorController;
import yangtz.cs.liu.campus.domain.schoolAtt.SchoolAtt;
import yangtz.cs.liu.campus.domain.schoolAtt.SchoolAttEa;
import yangtz.cs.liu.campus.domain.schoolAtt.SchoolAttMon;
import yangtz.cs.liu.campus.domain.schoolAtt.SchoolAttOt;
import yangtz.cs.liu.campus.domain.schoolClass.SchoolClassMentor;
import yangtz.cs.liu.campus.domain.schoolgrade.SchoolGrade;
import yangtz.cs.liu.campus.domain.teacher.SchoolTeacherLeave;
import yangtz.cs.liu.campus.domain.time.SchoolTimeTable;
import yangtz.cs.liu.campus.mapper.schoolAtt.SchoolAttMapper;
import yangtz.cs.liu.campus.mapper.schoolAtt.SchoolAttMonMapper;
import yangtz.cs.liu.campus.mapper.schoolClass.SchoolClassMentorMapper;
import yangtz.cs.liu.campus.mapper.schoolgrade.SchoolGradeMapper;
import yangtz.cs.liu.campus.mapper.teacher.SchoolTeacherLeaveMapper;
import yangtz.cs.liu.campus.mapper.teacher.SchoolTeacherMapper;
import yangtz.cs.liu.campus.mapper.time.SchoolTimeTableMapper;
import yangtz.cs.liu.campus.service.schoolAtt.ISchoolAttEaService;
import yangtz.cs.liu.campus.service.schoolAtt.ISchoolAttMonService;
import yangtz.cs.liu.campus.service.schoolAtt.ISchoolAttOtService;
import yangtz.cs.liu.campus.service.workDay.ISchoolWorkDayService;
import yangtz.cs.liu.campus.vo.schoolAtt.SchoolAttVO;
import yangtz.cs.liu.campus.vo.teacher.SchoolTeacherLeaveVO;
import yangtz.cs.liu.campus.vo.teacher.SchoolTeacherVO;
import yangtz.cs.liu.campus.vo.teacher.TeacherLeaveVO;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNotNull;
import static com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank;
import static yangtz.cs.liu.campus.constant.EmployeeType.EMPLOYEE;
import static yangtz.cs.liu.campus.constant.EmployeeType.TEACH;
import static yangtz.cs.liu.campus.constant.ProcessState.PASS;
import static yangtz.cs.liu.campus.constant.WorkTime.*;

@Service
public class SchoolAttMonServiceImpl extends ServiceImpl<SchoolAttMonMapper, SchoolAttMon> implements ISchoolAttMonService {
    @Autowired
    private SchoolAttMonMapper monMapper;
    @Autowired
    private ISchoolAttEaService eaService;

    @Autowired
    private ISchoolAttOtService otService;

    @Autowired
    private SchoolGradeMapper gradeMapper;

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SchoolTeacherMapper teacherMapper;

    @Autowired
    private SchoolTeacherLeaveMapper leaveMapper;

    @Autowired
    private ISchoolWorkDayService dayService;

    @Autowired
    private SchoolAttMapper attMapper;

    @Autowired
    private SchoolClassMentorMapper mentorMapper;

    @Autowired
    private SchoolTimeTableMapper tableMapper;



    public static final String s = "00:00:00";
    public static final String e = "23:59:59";

    @Override
    public List<SchoolAttMon> queryList(SchoolAttMon attMon) {
        LambdaQueryWrapper<SchoolAttMon> lqw = new LambdaQueryWrapper<>();
        lqw
                .eq(isNotNull(attMon.getUserId()), SchoolAttMon::getUserId, attMon.getUserId())
                .eq(isNotBlank(attMon.getAttMon()), SchoolAttMon::getAttMon, attMon.getAttMon())
                .eq(isNotNull(attMon.getOrgid()), SchoolAttMon::getOrgid, attMon.getOrgid())
                .eq(isNotBlank(attMon.getUserType()), SchoolAttMon::getUserType, attMon.getUserType())
                .like(isNotBlank(attMon.getUserName()), SchoolAttMon::getUserName, attMon.getUserName())
        ;
        List<SchoolAttMon> list = monMapper.selectList(lqw);
        for(SchoolAttMon mon : list){
            SysUser user = userMapper.selectUserById(mon.getUserId());
            if(StringUtils.isNotNull(user)){
                mon.setUserName(user.getUserName());
            }
        }
        return list;
    }

    //级部查看月度考勤
    @Override
    public List<SchoolAttMon> queryGradeList(List<Long> idList, SchoolAttMon attMon) {
        LambdaQueryWrapper<SchoolAttMon> lqw = new LambdaQueryWrapper<>();
        lqw
                .eq(isNotBlank(attMon.getAttMon()), SchoolAttMon::getAttMon, attMon.getAttMon())
                .in(isNotNull(idList), SchoolAttMon::getOrgid, idList)
                .eq(isNotBlank(attMon.getUserType()), SchoolAttMon::getUserType, attMon.getUserType())
                .like(isNotBlank(attMon.getUserName()), SchoolAttMon::getUserName, attMon.getUserName())
        ;
        List<SchoolAttMon> list = monMapper.selectList(lqw);
        for(SchoolAttMon mon : list){
            SysUser user = userMapper.selectUserById(mon.getUserId());
            if(StringUtils.isNotNull(user)){
                mon.setUserName(user.getUserName());
            }
        }
        return list;
    }


    //修改请假时长，加班时长
    @Override
    public int editById(Long id) {
        Double attEa = 0.000;
        Double attOt = 0.0;
        SchoolAttMon mon = monMapper.selectById(id);
        //获取考勤明细-请假
        List<SchoolAttEa> eaList = eaService.getListByAttMonId(id);
        //List<Double> eaTime = eaList.stream().map(SchoolAttEa::getTotalTime).collect(Collectors.toList());
        if(StringUtils.isNotNull(eaList) || eaList.size() > 0){
            attEa = eaList.stream().mapToDouble(SchoolAttEa::getTotalTime).sum();
        }

        //获取考勤明细-加班
        List<SchoolAttOt> otList = otService.getListByAttMonId(id);
        if(StringUtils.isNotNull(eaList) || eaList.size() > 0){
            attOt = otList.stream().mapToDouble(SchoolAttOt::getTotalTime).sum();
        }

        mon.setAttEa(attEa);
        mon.setAttOt(attOt);
        return monMapper.updateById(mon);
    }

    /**
     * 按月批量提交
     */
    @Override
    public int monthSubmit(SchoolAttMon attMon) {
        //查看未提交数
        LambdaQueryWrapper<SchoolAttMon> lqw = new LambdaQueryWrapper<>();
        lqw
                .eq(SchoolAttMon::getAttMon, attMon.getAttMon())
                .eq(SchoolAttMon::getOrgid, attMon.getOrgid())
                .eq(SchoolAttMon::getUserType, attMon.getUserType())
                .eq(SchoolAttMon::getState,"0")
        ;
        List<SchoolAttMon> list = monMapper.selectList(lqw);
        if(StringUtils.isNull(list) || list.size() == 0){
            throw new ServiceException("所在部门暂无考勤数据可提交，或考勤数据已全部提交");
        }
        LambdaUpdateWrapper<SchoolAttMon> luw = new LambdaUpdateWrapper<>();
        luw
                .eq(SchoolAttMon::getAttMon, attMon.getAttMon())
                .eq(SchoolAttMon::getOrgid, attMon.getOrgid())
                .eq(SchoolAttMon::getUserType, attMon.getUserType())
                .set(SchoolAttMon::getState,"1")
        ;
        return monMapper.update(null, luw);
    }

    /**
     * 级部按月批量提交
     */
    @Override
    public int monthGradeSubmit(List<Long> idList, SchoolAttMon attMon) {
        //查看未提交数
        LambdaQueryWrapper<SchoolAttMon> lqw = new LambdaQueryWrapper<>();
        lqw
                .eq(SchoolAttMon::getAttMon, attMon.getAttMon())
                .in(SchoolAttMon::getOrgid, idList)
                .eq(SchoolAttMon::getUserType, attMon.getUserType())
                .eq(SchoolAttMon::getState,"0")
                ;
        List<SchoolAttMon> list = monMapper.selectList(lqw);
        if(StringUtils.isNull(list) || list.size() == 0){
            throw new ServiceException("所在级部暂无考勤数据可提交，或考勤数据已全部提交");
        }
        LambdaUpdateWrapper<SchoolAttMon> luw = new LambdaUpdateWrapper<>();
        luw
                .eq(SchoolAttMon::getAttMon, attMon.getAttMon())
                .in(SchoolAttMon::getOrgid, idList)
                .eq(SchoolAttMon::getUserType, attMon.getUserType())
                .set(SchoolAttMon::getState,"1")
        ;
        return monMapper.update(null,luw);
    }

    /**
     * 科室按月初始化
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int monthInit(SchoolAttMon attMon) throws Exception {
        int num = 0;
        int size = 0;
        //时间正常，可以初始化
        if (judgeDate(attMon.getAttMon())) {
            //判断当前时间是否已经初始化
            LambdaQueryWrapper<SchoolAttMon> lqw = new LambdaQueryWrapper<>();
            lqw
                    .eq(SchoolAttMon::getAttMon, attMon.getAttMon())
                    .eq(SchoolAttMon::getUserType, attMon.getUserType())
                    .eq(SchoolAttMon::getOrgid,attMon.getOrgid());
            List<SchoolAttMon> schoolAttMon = monMapper.selectList(lqw);
            if (schoolAttMon.size() > 0) {
                throw new ServiceException("所在科室该月份已完成初始化，请不要重复");
            }
                //科室
                SysDept dept = deptMapper.selectDeptById(attMon.getOrgid());
                //查询本科室下的职工
                List<SchoolTeacherVO> voList = teacherMapper.getTeacherByDeptId(attMon.getOrgid(), EMPLOYEE);
                size = voList.size();
                for (SchoolTeacherVO teacherVO : voList) {
                    //先插主表
                    SchoolAttMon mon = new SchoolAttMon();
                    mon.setUserId(teacherVO.getId());
                    mon.setUserName(teacherVO.getTeacherName());
                    mon.setUserType(attMon.getUserType());
                    mon.setOrgid(attMon.getOrgid());
                    mon.setOrgname(dept.getDeptName());
                    mon.setAttMon(attMon.getAttMon());
                    mon.setState("0");
                    if (monMapper.insert(mon) <= 0) {
                        throw new ServiceException("初始化失败");
                    }

                    //获取选择年月的起始年月日
                    String attMonDate = attMon.getAttMon();
                    //获取传入的年月
                    int year = Integer.parseInt(attMonDate.substring(0, attMonDate.lastIndexOf("-")));
                    int month = Integer.parseInt(attMonDate.substring(attMonDate.lastIndexOf("-") + 1, attMonDate.length()));
                    //该年该月有都多少天
                    int day = HolidayDateUtil.daysMonth(year, month - 1);

                    //该年月的开始日期

                        Date startDate = HolidayDateUtil.format.parse(year + "-" + (month >= 10 ? month : "0" + month) + "-" + "01" + " " + s);
                        Date endDate = HolidayDateUtil.format.parse(year + "-" + (month >= 10 ? month : "0" + month) + "-" + day + " " + e);
                        //获取周末，节假日日期
                        List<String> restList = dayService.getHolidayList(startDate,endDate,"1");

                        //遍历教师请假表
                        //当月已通过的请假，0，请假开始时间在本时间段内的
                        String state = PASS;
                        List<TeacherLeaveVO> leaveVOList = leaveMapper.getLeaveByTeacherId(state, teacherVO.getId(), null, null);
                        if(StringUtils.isNotNull(leaveVOList) && leaveVOList.size() > 0){
                            for (TeacherLeaveVO leaveVO : leaveVOList) {
                                /**
                                 * 判断集中情况（假设当前月份为2022-12）
                                 * 1.请假开始时间和结束时间都在本月份的（开始结束时间 2022-12-03到2022-12-06）
                                 * 2.开始时间在本月份，结束时间不在本月份（2022-12-06到 2023-01-01）
                                 * 3.开始时间不在本月份，结束时间在本月份（2022-11-06到 2022-12-02）
                                 * 4.开始时间和结束时间都不在本月份（这种情况会在算法中先排除第5中情况，2022-11-06到 2023-02-02）
                                 * 5.开始月份和结束月份都在本月之前或之后的（也就是这种请假和本月份无关的，2022-11-06到 2022-11-07，2023-01-06到 2023-01-07）
                                 */
                                int flag = HolidayDateUtil.judgeLeaveTime(startDate,endDate,leaveVO.getStartTime(),leaveVO.getEndTime());
                                SchoolAttEa ea = new SchoolAttEa();
                                if(1 == flag){
                                    //1.请假开始时间和结束时间都在本月份的
                                    ea.setAttMonId(mon.getId());
                                    ea.setUserId(leaveVO.getTeacherId());
                                    ea.setUserName(leaveVO.getTeacherName());
                                    ea.setUserType(EMPLOYEE);
                                    ea.setStartTime(leaveVO.getStartTime());
                                    ea.setEndTime(leaveVO.getEndTime());
                                    ea.setTotalTime(leaveVO.getTotalTime());
                                    eaService.save(ea);
                                } else if (2 == flag) {
                                    //2.开始时间在本月份，结束时间不在本月份
                                    ea.setAttMonId(mon.getId());
                                    ea.setUserId(leaveVO.getTeacherId());
                                    ea.setUserName(leaveVO.getTeacherName());
                                    ea.setUserType(EMPLOYEE);
                                    ea.setStartTime(leaveVO.getStartTime());
                                    ea.setEndTime(endDate);
                                    //获取请假时长
                                    String startTime = HolidayDateUtil.format.format(leaveVO.getStartTime());
                                    String endTime = HolidayDateUtil.format.format(endDate);
                                    double hours = HolidayDateUtil.calculateTimeHour(startTime,endTime,AMSTARTTIME,AMENDTIME,PMSTARTTIME,PMENDTIME,restList);
                                    double d = hours / 7.25;
                                    ea.setTotalTime(d);
                                    eaService.save(ea);
                                } else if (3 == flag) {
                                    //3.开始时间不在本月份，结束时间在本月份
                                    ea.setAttMonId(mon.getId());
                                    ea.setUserId(leaveVO.getTeacherId());
                                    ea.setUserName(leaveVO.getTeacherName());
                                    ea.setUserType(EMPLOYEE);
                                    ea.setStartTime(startDate);
                                    ea.setEndTime(leaveVO.getEndTime());
                                    //获取请假时长
                                    String startTime = HolidayDateUtil.format.format(startDate);
                                    String endTime = HolidayDateUtil.format.format(leaveVO.getEndTime());
                                    double hours = HolidayDateUtil.calculateTimeHour(startTime,endTime,AMSTARTTIME,AMENDTIME,PMSTARTTIME,PMENDTIME,restList);
                                    double d = hours / 7.25;
                                    ea.setTotalTime(d);
                                    eaService.save(ea);
                                } else if (4 == flag) {
                                    //4.开始时间和结束时间都不在本月份
                                    ea.setAttMonId(mon.getId());
                                    ea.setUserId(leaveVO.getTeacherId());
                                    ea.setUserName(leaveVO.getTeacherName());
                                    ea.setUserType(EMPLOYEE);
                                    ea.setStartTime(startDate);
                                    ea.setEndTime(endDate);
                                    //获取请假时长
                                    String startTime = HolidayDateUtil.format.format(startDate);
                                    String endTime = HolidayDateUtil.format.format(endDate);
                                    double hours = HolidayDateUtil.calculateTimeHour(startTime,endTime,AMSTARTTIME,AMENDTIME,PMSTARTTIME,PMENDTIME,restList);
                                    double d = hours / 7.25;
                                    ea.setTotalTime(d);
                                    eaService.save(ea);
                                } else if (5 == flag) {
                                    continue;
                                }
                            }
                        }

                        //遍历教师打卡表
                        List<SchoolAtt> teacherAtt = attMapper.teacherAtt(teacherVO.getId(),EMPLOYEE,startDate,endDate);
                        if(StringUtils.isNotNull(teacherAtt) && teacherAtt.size() > 0){
                            //变换成一天N个打卡记录格式
                            List<SchoolAttVO> attVOList = new ArrayList<>();

                            for(SchoolAtt att : teacherAtt){
                                SchoolAttVO vo = getSame(att);
                                attVOList.add(vo);
                            }
                            //结果集List中含有重复值，去除重复值
                            List<SchoolAttVO> unique = attVOList.stream().distinct().collect(Collectors.toList());

                            for(SchoolAttVO attVO : unique){
                                //获取打卡日期
                                String d = HolidayDateUtil.format1.format(attVO.getClockDate());
                                //获取本日期时间点打卡记录
                                List<String> timeList = Arrays.asList(attVO.getTimes().split("、"));
                                //判断是工作日还是非工作日
                                //工作日
                                if("0".equals(HolidayDateUtil.isLawHoliday(d,restList))){
                                    Double hours = 0.0;
                                    Double hours1 = 0.0;
                                    Double hours2 = 0.0;
                                    /**
                                     *职工加班初始化规则  基础单位0.5h，不满0.5的直接舍去。如（1.8小时，就算1.5h. 0.3H的就没加班）
                                     *
                                     *  一、7点15前有打卡算加班。加班时间不能低于半个小时。打卡次数N。
                                     *   计算：  7：15 -第一次打开时间。
                                     *
                                     * */
                                    //判断第一次打卡时间是否在7点15前
                                    //在7点15前
                                    Date time1 = HolidayDateUtil.format.parse(d + " " + attVO.getTime1());
                                    Date morEnd = HolidayDateUtil.format.parse(d + " " + MOREND);
                                    Date time2 = HolidayDateUtil.format.parse(d + " " + timeList.get(timeList.size() - 1));
                                    Date eveStart = HolidayDateUtil.format.parse(d + " " + EVESTART);
                                    if(morEnd.compareTo(time2) <= 0){
                                        //在7点15前
                                        if(time1.compareTo(morEnd) <= 0){
                                            //获取第一次打卡时间到在7点15前
                                            String sTime = HolidayDateUtil.format1.format(attVO.getClockDate()) + " " + attVO.getTime1();
                                            String eTime = HolidayDateUtil.format1.format(attVO.getClockDate()) + " " + MOREND;
                                            String h = HolidayDateUtil.dateToStamp(sTime,eTime);
                                            hours1 = Double.parseDouble(h);
                                        }
                                        //晚加班,取最后一次打卡，看是否在18点30之后
                                        /**
                                         * 二、晚加班：最后一次打开在 6点半之后的。18点30之后算加班 加班时间不能低于半个小时。打卡次数N。
                                         * 最后一次打卡时时间-18点30。
                                         * */

                                        if(time2.compareTo(eveStart) > 0){
                                            String sTime = HolidayDateUtil.format1.format(attVO.getClockDate()) + " " + EVESTART;
                                            String eTime = HolidayDateUtil.format1.format(attVO.getClockDate()) + " " + timeList.get(timeList.size() - 1);
                                            String h = HolidayDateUtil.dateToStamp(sTime,eTime);
                                            hours2 = Double.parseDouble(h);
                                        }
                                    }

                                    hours = hours1 + hours2;
                                    if(hours >= 0.5){
                                        double lastNum = HolidayDateUtil.getLast(hours.toString());
                                        if(lastNum < 0.5){
                                            hours = hours - lastNum;
                                        } else if (lastNum > 0.5) {
                                            hours = hours - (lastNum - 0.5);
                                        }
                                        SchoolAttOt ot = new SchoolAttOt();
                                        ot.setAttMonId(mon.getId());
                                        ot.setUserId(teacherVO.getId());
                                        ot.setUserName(teacherVO.getTeacherName());
                                        ot.setUserType(EMPLOYEE);
                                        ot.setStartTime(time1);
                                        ot.setEndTime(time2);
                                        ot.setTotalTime(hours);
                                        ot.setRemarks("工作日加班");
                                        ot.insert();
                                        otService.save(ot);
                                    }
                                }else {
                                    //非工作日
                                    /**
                                     * 只一次打卡的不统计。  只取第一次和最后一次打开时间。
                                     * 取两次打卡内有效时间。（7点15到7点45、  11点30到14点、17点30到18点30 这里边的时间算无效时间）
                                     * */
                                    if(timeList.size() > 1){
                                        //取第一次打卡时间和最后一打卡时间
                                        String firstTime = timeList.get(0);
                                        String lastTime = timeList.get(timeList.size() - 1);
                                        String sTime = d + " " + firstTime;
                                        String eTime = d + " " + lastTime;

                                        String h = HolidayDateUtil.calculateOverHour(firstTime,lastTime,d,MORSTART,MOREND,
                                                AMSTARTTIME,AMENDTIME,PMSTARTTIME,PMENDTIME,EVESTART);
                                        Double hours = Double.parseDouble(h);
                                        if(hours >= 0.5){
                                            double lastNum = HolidayDateUtil.getLast(h);
                                            if(lastNum < 0.5){
                                                hours = hours - lastNum;
                                            } else if (lastNum > 0.5) {
                                                hours = hours - (lastNum - 0.5);
                                            }
                                            SchoolAttOt ot = new SchoolAttOt();
                                            ot.setAttMonId(mon.getId());
                                            ot.setUserId(teacherVO.getId());
                                            ot.setUserName(teacherVO.getTeacherName());
                                            ot.setUserType(EMPLOYEE);
                                            ot.setStartTime(HolidayDateUtil.format.parse(sTime));
                                            ot.setEndTime(HolidayDateUtil.format.parse(eTime));
                                            ot.setTotalTime(hours);
                                            ot.setRemarks("非工作日加班");
                                            ot.insert();
                                            otService.save(ot);
                                        }
                                    }

                                }
                            }
                        }

                    //更新主表请假、加班时长
                    num += editById(mon.getId());
                }
            return num == size ? 1 : 0;
        }else{
            throw new ServiceException("时间选择错误");
        }
    }

    //获取包括att在内所有与之在同一天，打卡时间不同的对象,获取打卡时间字符串数组
    public SchoolAttVO getSame(SchoolAtt att){
        SchoolAttVO vo = new SchoolAttVO();
        BeanUtils.copyProperties(att,vo);
        LambdaQueryWrapper<SchoolAtt> lqw = new LambdaQueryWrapper<>();
        lqw
                .eq(SchoolAtt::getDeviceNum,att.getDeviceNum())
                .eq(SchoolAtt::getTeacherCode,att.getTeacherCode())
                .eq(SchoolAtt::getClockDate,att.getClockDate());
        List<SchoolAtt> sameList = attMapper.selectList(lqw);

        //取出所有打卡时间
        List<String> timeList = sameList.stream().map(SchoolAtt::getClockTime).collect(Collectors.toList());
        Collections.sort(timeList, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                try {
                    return HolidayDateUtil.format4.parse(o1).compareTo(HolidayDateUtil.format4.parse(o2));
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        vo.setClockTime(null);
        vo.setId(null);
        //给打卡时间1-20赋值
        for(int i = 0; i < timeList.size(); i++){
            int j = i + 1;
            switch (j){
                case 1: vo.setTime1(timeList.get(i)); continue;
                case 2: vo.setTime2(timeList.get(i)); continue;
                case 3: vo.setTime3(timeList.get(i)); continue;
                case 4: vo.setTime4(timeList.get(i)); continue;
                case 5: vo.setTime5(timeList.get(i)); continue;
                case 6: vo.setTime6(timeList.get(i)); continue;
                case 7: vo.setTime7(timeList.get(i)); continue;
                case 8: vo.setTime8(timeList.get(i)); continue;
                case 9: vo.setTime9(timeList.get(i)); continue;
                case 10: vo.setTime10(timeList.get(i)); continue;
                case 11: vo.setTime11(timeList.get(i)); continue;
                case 12: vo.setTime12(timeList.get(i)); continue;
                case 13: vo.setTime13(timeList.get(i)); continue;
                case 14: vo.setTime14(timeList.get(i)); continue;
                case 15: vo.setTime15(timeList.get(i)); continue;
                case 16: vo.setTime16(timeList.get(i)); continue;
                case 17: vo.setTime17(timeList.get(i)); continue;
                case 18: vo.setTime18(timeList.get(i)); continue;
                case 19: vo.setTime19(timeList.get(i)); continue;
                case 20: vo.setTime20(timeList.get(i));
            }
        }
        String times = StringUtils.join(timeList.toArray(),"、");
        vo.setTimes(times);
        return vo;
    }

    //级部初始化
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int monthGradeInit(List<Long> idList, SchoolAttMon attMon) throws Exception {
        int num = 0;
        int size = 0;
        //时间正常，可以初始化
        if (judgeDate(attMon.getAttMon())) {
            //判断当前时间是否已经初始化,排除已初始化的级部（当前人可能在多个级部工作）
            Iterator it=idList.iterator();
            while(it.hasNext()){
                Long gradeId = (Long)it.next();
                LambdaQueryWrapper<SchoolAttMon> lqw = new LambdaQueryWrapper<>();
                lqw
                        .eq(SchoolAttMon::getAttMon, attMon.getAttMon())
                        .eq(SchoolAttMon::getUserType, attMon.getUserType())
                        .eq(SchoolAttMon::getOrgid,gradeId)
                ;
                List<SchoolAttMon> schoolAttMon = monMapper.selectList(lqw);
                if (StringUtils.isNotNull(schoolAttMon) && schoolAttMon.size() > 0) {
                    it.remove();
                }
            }

            if(StringUtils.isNull(idList) || idList.size() == 0){
                throw new ServiceException("所在级部该月份已完成初始化，请不要重复");
            }

            //级部
            List<SchoolGrade> grades = gradeMapper.selectBatchIds(idList);
            for(SchoolGrade grade : grades){
                //查询本级部下的老师
                List<SchoolTeacherVO> voList = teacherMapper.getTeacherByGradeId(grade.getId());
                size += voList.size();
                for (SchoolTeacherVO teacherVO : voList) {
                    //先插主表
                    SchoolAttMon mon = new SchoolAttMon();
                    mon.setUserId(teacherVO.getId());
                    mon.setUserName(teacherVO.getTeacherName());
                    mon.setUserType(attMon.getUserType());
                    mon.setOrgid(grade.getId());
                    mon.setOrgname(grade.getGradeName());
                    mon.setAttMon(attMon.getAttMon());
                    mon.setState("0");
                    if (monMapper.insert(mon) <= 0) {
                        throw new ServiceException("初始化失败");
                    }

                    //获取选择年月的起始年月日
                    String attMonDate = attMon.getAttMon();
                    //获取传入的年月
                    int year = Integer.parseInt(attMonDate.substring(0, attMonDate.lastIndexOf("-")));
                    int month = Integer.parseInt(attMonDate.substring(attMonDate.lastIndexOf("-") + 1, attMonDate.length()));
                    //该年该月有都多少天
                    int day = HolidayDateUtil.daysMonth(year, month - 1);

                    //该年月的开始日期
                        Date startDate = HolidayDateUtil.format1.parse(year + "-" + (month >= 10 ? month : "0" + month) + "-" + "01");
                        Date endDate = HolidayDateUtil.format1.parse(year + "-" + (month >= 10 ? month : "0" + month) + "-" + day);
                        Date start = HolidayDateUtil.format.parse(year + "-" + (month >= 10 ? month : "0" + month) + "-" + "01" + " " + s);
                        Date end = HolidayDateUtil.format.parse(year + "-" + (month >= 10 ? month : "0" + month) + "-" + day + " " + e);
                        //获取周末，节假日日期
                        List<String> restList = dayService.getHolidayList(startDate,endDate,"1");

                        //遍历教师请假表
                        //当月已通过的请假，0
                        String state = PASS;
                        List<TeacherLeaveVO> leaveVOList = leaveMapper.getLeaveByTeacherId(state, teacherVO.getId(), null, null);
                        if(StringUtils.isNotNull(leaveVOList) && leaveVOList.size() > 0){
                            for (TeacherLeaveVO leaveVO : leaveVOList) {
                                /**
                                 * 判断集中情况（假设当前月份为2022-12）
                                 * 1.请假开始时间和结束时间都在本月份的（开始结束时间 2022-12-03到2022-12-06）
                                 * 2.开始时间在本月份，结束时间不在本月份（2022-12-06到 2023-01-01）
                                 * 3.开始时间不在本月份，结束时间在本月份（2022-11-06到 2022-12-02）
                                 * 4.开始时间和结束时间都不在本月份（这种情况会在算法中先排除第5中情况，2022-11-06到 2023-02-02）
                                 * 5.开始月份和结束月份都在本月之前或之后的（也就是这种请假和本月份无关的，2022-11-06到 2022-11-07，2023-01-06到 2023-01-07）
                                 */
                                int flag = HolidayDateUtil.judgeLeaveTime(start,end,leaveVO.getStartTime(),leaveVO.getEndTime());
                                SchoolAttEa ea = new SchoolAttEa();
                                if(1 == flag){
                                    ea.setAttMonId(mon.getId());
                                    ea.setUserId(leaveVO.getTeacherId());
                                    ea.setUserName(leaveVO.getTeacherName());
                                    ea.setUserType(TEACH);
                                    ea.setStartTime(leaveVO.getStartTime());
                                    ea.setStartSort(leaveVO.getStartSort());
                                    ea.setEndTime(leaveVO.getEndTime());
                                    ea.setEndSort(leaveVO.getEndSort());
                                    ea.setTotalTime(leaveVO.getTotalTime());
                                    eaService.save(ea);
                                } else if (2 == flag) {
                                    ea.setAttMonId(mon.getId());
                                    ea.setUserId(leaveVO.getTeacherId());
                                    ea.setUserName(leaveVO.getTeacherName());
                                    ea.setUserType(TEACH);
                                    ea.setStartTime(leaveVO.getStartTime());
                                    ea.setStartSort(leaveVO.getStartSort());
                                    //结束时间设置为本月最后一天最后一节课
                                    ea.setEndTime(endDate);
                                    ea.setEndSort("8");
                                    String startTime = HolidayDateUtil.format1.format(leaveVO.getStartTime());
                                    String endTime = HolidayDateUtil.format1.format(endDate);
                                    int startSort = Integer.valueOf(leaveVO.getStartSort());
                                    int courseNum = HolidayDateUtil.courseNum(startTime,endTime,startSort,8,restList);
                                    double d = courseNum / 8.0;
                                    ea.setTotalTime(d);
                                    eaService.save(ea);
                                } else if (3 == flag) {
                                    ea.setAttMonId(mon.getId());
                                    ea.setUserId(leaveVO.getTeacherId());
                                    ea.setUserName(leaveVO.getTeacherName());
                                    ea.setUserType(TEACH);
                                    ea.setStartTime(startDate);
                                    ea.setStartSort("1");
                                    ea.setEndTime(leaveVO.getEndTime());
                                    ea.setEndSort(leaveVO.getEndSort());
                                    String startTime = HolidayDateUtil.format1.format(startDate);
                                    String endTime = HolidayDateUtil.format1.format(leaveVO.getEndTime());
                                    int endSort = Integer.valueOf(leaveVO.getEndSort());
                                    int courseNum = HolidayDateUtil.courseNum(startTime,endTime,1,endSort,restList);
                                    double d = courseNum / 8.0;
                                    ea.setTotalTime(d);
                                    eaService.save(ea);
                                } else if (4 == flag) {
                                    ea.setAttMonId(mon.getId());
                                    ea.setUserId(leaveVO.getTeacherId());
                                    ea.setUserName(leaveVO.getTeacherName());
                                    ea.setUserType(TEACH);
                                    ea.setStartTime(startDate);
                                    ea.setStartSort("1");
                                    ea.setEndTime(endDate);
                                    ea.setEndSort("8");
                                    String startTime = HolidayDateUtil.format1.format(startDate);
                                    String endTime = HolidayDateUtil.format1.format(endDate);
                                    int courseNum = HolidayDateUtil.courseNum(startTime,endTime,1,8,restList);
                                    double d = courseNum / 8.0;
                                    ea.setTotalTime(d);
                                    eaService.save(ea);
                                } else if (5 == flag) {
                                    continue;
                                }
                            }
                        }


                        //遍历教师打卡表
                        List<SchoolAtt> teacherAtt = attMapper.teacherAtt(teacherVO.getId(),TEACH,startDate,endDate);
                        if(isNotNull(teacherAtt) && teacherAtt.size() > 0){
                            //变换成一天N个打卡记录格式
                            List<SchoolAttVO> attVOList = new ArrayList<>();

                            for(SchoolAtt att : teacherAtt){
                                SchoolAttVO vo = getSame(att);
                                attVOList.add(vo);
                            }
                            //结果集List中含有重复值，去除重复值
                            List<SchoolAttVO> unique = attVOList.stream().distinct().collect(Collectors.toList());

                            for(SchoolAttVO attVO : unique){
                                //获取打卡日期
                                String d = HolidayDateUtil.format1.format(attVO.getClockDate());
                                //获取本日期时间点打卡记录
                                List<String> timeList = Arrays.asList(attVO.getTimes().split("、"));
                                //判断是工作日还是非工作日
                                //工作日
                                if("0".equals(HolidayDateUtil.isLawHoliday(d,restList))){
                                    Double hours = 0.0;
                                    Double hours1 = 0.0;
                                    Double hours2 = 0.0;
                                    Double hours3 = 0.0;
                                    /**
                                     *教工加班初始化规则
                                     * 算出加班时长后 1个小时算1节课。 基础单位0.5节，不满0.5的直接舍去。如（1.8小时，就算1.5节）
                                     *工作日
                                     *  一、7点15前有打卡算加班。加班时间不能低于半个小时。打卡次数N。
                                     *   计算：  7：15 -第一次打开时间。
                                     *    二、晚加班：18点30 之后有打卡的。18点30之后算加班 加班时间不能低于半个小时。打卡次数N。
                                     *                  最后一次打卡时时间-18点30。
                                     *    三,排上午第四节课的老师，算半节课加班。在生成时 时间就携程 11：30 -12：00就可以。
                                     *
                                     * */
                                    //判断第一次打卡时间是否在7点15前
                                    //在7点15前
                                    Date time1 = HolidayDateUtil.format.parse(d + " " + attVO.getTime1());
                                    Date morEnd = HolidayDateUtil.format.parse(d + " " + MOREND);
                                    Date time2 = HolidayDateUtil.format.parse(d + " " + timeList.get(timeList.size() - 1));
                                    Date eveStart = HolidayDateUtil.format.parse(d + " " + EVESTART);
                                    Date mid = HolidayDateUtil.format.parse(d + " " + "12:00:00");
                                    //判断最后一次打卡时间是否在7.15hou
                                    if(morEnd.compareTo(time2) <= 0){
                                        //在7点15前
                                        if(time1.compareTo(morEnd) <= 0){
                                            //获取第一次打卡时间到在7点15前
                                            String sTime = HolidayDateUtil.format1.format(attVO.getClockDate()) + " " + attVO.getTime1();
                                            String eTime = HolidayDateUtil.format1.format(attVO.getClockDate()) + " " + MOREND;
                                            String h = HolidayDateUtil.dateToStamp(sTime,eTime);
                                            hours1 = Double.parseDouble(h);
                                        }
                                        //晚加班,取最后一次打卡，看是否在18点30之后
                                        /**
                                         * 二、晚加班：最后一次打开在 6点半之后的。18点30之后算加班 加班时间不能低于半个小时。打卡次数N。
                                         * 最后一次打卡时时间-18点30。
                                         * */

                                        if(time2.compareTo(eveStart) > 0){
                                            String sTime = HolidayDateUtil.format1.format(attVO.getClockDate()) + " " + EVESTART;
                                            String eTime = HolidayDateUtil.format1.format(attVO.getClockDate()) + " " + timeList.get(timeList.size() - 1);
                                            String h = HolidayDateUtil.dateToStamp(sTime,eTime);
                                            hours2 = Double.parseDouble(h);
                                        }

                                        /**
                                         * 三,排上午第四节课的老师，算半节课加班。在生成时 时间就携程 11：30 -12：00就可以。
                                         * 最后一次打卡在12点之后才算
                                         * */
                                        if(mid.compareTo(time2) <= 0){
                                            //获取当前学年，教师所在班级
                                            int schoolYear = getNewYear();
                                            List<SchoolClassMentor> mentors = mentorMapper.getMentors(teacherVO.getId(),schoolYear);
                                            //确保该教师在本学年有 所教班级
                                            if(isNotNull(mentors) && mentors.size() > 0){
                                                //获取当前处于什么学期
                                                int termId = isNewTerm();
                                                //获取当前日期属于周几
                                                int weekValue = HolidayDateUtil.dateToWeekValue(d);
                                                //判断教师所在班级，当前学年，当前学期当天的第四节课是不是教师所教授的课
                                                boolean flag = false;
                                                for(SchoolClassMentor mentor : mentors){
                                                    //查当前学年，所在班级，所处学期，该日期所在星期的第4节课是否有课
                                                    LambdaQueryWrapper<SchoolTimeTable> lqw = new LambdaQueryWrapper<>();
                                                    lqw
                                                            .eq(SchoolTimeTable::getYearValue,schoolYear)
                                                            .eq(SchoolTimeTable::getClassId,mentor.getClassId())
                                                            .eq(SchoolTimeTable::getTermId,termId)
                                                            .eq(SchoolTimeTable::getWeekValue,weekValue)
                                                            .eq(SchoolTimeTable::getSortName,"第四节课")
                                                            .eq(SchoolTimeTable::getCourseId,mentor.getCourseId())
                                                    ;
                                                    List<SchoolTimeTable> tableList = tableMapper.selectList(lqw);
                                                    if(StringUtils.isNotNull(tableList) && tableList.size() > 0){
                                                        flag = true;
                                                        break;
                                                    }
                                                }
                                                //有课
                                                if(flag){
                                                    hours3 = 0.5;
                                                }
                                            }
                                        }

                                    }

                                    hours = hours1 + hours2 + hours3;
                                    if(hours >= 0.5){
                                        double lastNum = HolidayDateUtil.getLast(hours.toString());
                                        if(lastNum < 0.5){
                                            hours = hours - lastNum;
                                        } else if (lastNum > 0.5) {
                                            hours = hours - (lastNum - 0.5);
                                        }
                                        SchoolAttOt ot = new SchoolAttOt();
                                        ot.setAttMonId(mon.getId());
                                        ot.setUserId(teacherVO.getId());
                                        ot.setUserName(teacherVO.getTeacherName());
                                        ot.setUserType(TEACH);
                                        ot.setStartTime(time1);
                                        ot.setEndTime(time2);
                                        ot.setTotalTime(hours);
                                        ot.setRemarks("工作日加班");
                                        ot.insert();
                                        otService.save(ot);
                                    }
                                }else {
                                    //非工作日
                                    /**
                                     * 只一次打卡的不统计。  只取第一次和最后一次打开时间。
                                     * 取两次打卡内有效时间。（7点15到7点45、  11点30到14点、17点30到18点30 这里边的时间算无效时间）
                                     * */
                                    if(timeList.size() > 1){
                                        //取第一次打卡时间和最后一打卡时间
                                        String firstTime = timeList.get(0);
                                        String lastTime = timeList.get(timeList.size() - 1);
                                        String sTime = d + " " + firstTime;
                                        String eTime = d + " " + lastTime;

                                        String h = HolidayDateUtil.calculateOverHour(firstTime,lastTime,d,MORSTART,MOREND,
                                                AMSTARTTIME,AMENDTIME,PMSTARTTIME,PMENDTIME,EVESTART);
                                        Double hours = Double.parseDouble(h);
                                        if(hours >= 0.5){
                                            double lastNum = HolidayDateUtil.getLast(h);
                                            if(lastNum < 0.5){
                                                hours = hours - lastNum;
                                            } else if (lastNum > 0.5) {
                                                hours = hours - (lastNum - 0.5);
                                            }
                                            SchoolAttOt ot = new SchoolAttOt();
                                            ot.setAttMonId(mon.getId());
                                            ot.setUserId(teacherVO.getId());
                                            ot.setUserName(teacherVO.getTeacherName());
                                            ot.setUserType(TEACH);
                                            ot.setStartTime(HolidayDateUtil.format.parse(sTime));
                                            ot.setEndTime(HolidayDateUtil.format.parse(eTime));
                                            ot.setTotalTime(hours);
                                            ot.setRemarks("非工作日加班");
                                            ot.insert();
                                            otService.save(ot);
                                        }
                                    }
                                }
                            }
                        }

                    //更新主表请假、加班时长
                    num += editById(mon.getId());
                }
            }
            return num == size ? 1 : 0;
        }else{
           throw new ServiceException("时间选择错误");
        }
    }

    //获取当前学年
    public Integer getNewYear(){
        Calendar cal = Calendar.getInstance();
        //获取当前年月
        int nowYear = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        //设置当前学期
        int term = 1;
        //2-7为第二学期，8-1为第一学期
        //如果当前月份小于8月，则该学年应为当前年-1 到 当前年,例如当前年月为2023年7月，则该学年为2022-2023年的第二学期
        if (month < 8) {
            nowYear = nowYear - 1;
        }
        if (month >= 2 && month < 8) {
            term = 2;
        }
        return nowYear;
    }

    //判断所处学期是上还是下学期
    private Integer isNewTerm() {
        Calendar cal = Calendar.getInstance();
        //获取当前年月
        int nowYear = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        //设置当前学期为上学期
        int term = 0;
        //2-7为下学期，8-1为上学期
        if (month >= 2 && month < 8) {
            term = 1;
        }
        return term;
    }

    //判断当前传入月份是否已过完
    public boolean judgeDate(String date) {
        boolean flag = false;
        //获取传入的年月
        int year = Integer.parseInt(date.substring(0, date.lastIndexOf("-")));
        int month = Integer.parseInt(date.substring(date.lastIndexOf("-") + 1, date.length()));

        //获取此时的年月
        Calendar now = Calendar.getInstance();
        int nowYear = now.get(Calendar.YEAR);
        int nowMonth = (now.get(Calendar.MONTH) + 1);

        //当前年
        if (year == nowYear) {
            //是本月之前的月份
            if (month < nowMonth) {
                flag = true;
            } else if (month == nowMonth) {
                throw new ServiceException("抱歉，本月还没有过完，无法初始化数据");
            } else {
                throw new ServiceException("抱歉，该月份还没有开始，无法初始化数据");
            }
        } else if (year < nowYear) {
            flag = true;
        } else {
            //flag = false;
            throw new ServiceException("抱歉，该月份还没有开始，无法初始化数据");
        }
        return flag;
    }
}
