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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.core.utils.HolidayDateUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import yangtz.cs.liu.campus.domain.schoolAtt.SchoolAttEa;
import yangtz.cs.liu.campus.domain.schoolAtt.SchoolAttOt;
import yangtz.cs.liu.campus.domain.schoolClass.SchoolClassMentor;
import yangtz.cs.liu.campus.domain.time.SchoolTimeTable;
import yangtz.cs.liu.campus.mapper.schoolAtt.SchoolAttOtMapper;
import yangtz.cs.liu.campus.mapper.schoolClass.SchoolClassMentorMapper;
import yangtz.cs.liu.campus.mapper.schoolgrade.SchoolGradeMapper;
import yangtz.cs.liu.campus.mapper.time.SchoolTimeTableMapper;
import yangtz.cs.liu.campus.service.schoolAtt.ISchoolAttOtService;
import yangtz.cs.liu.campus.service.workDay.ISchoolWorkDayService;

//import javax.xml.ws.Action;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import static com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNotNull;
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.WorkTime.*;

@Service
public class SchoolAttOtServiceImpl extends ServiceImpl<SchoolAttOtMapper, SchoolAttOt> implements ISchoolAttOtService {

    @Autowired
    private SchoolAttOtMapper otMapper;

    @Autowired
    private ISchoolWorkDayService dayService;

    @Autowired
    private SchoolClassMentorMapper mentorMapper;

    @Autowired
    private SchoolTimeTableMapper tableMapper;

    @Autowired
    private SchoolGradeMapper gradeMapper;

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

    //根据主表id获取加班详情
    @Override
    public List<SchoolAttOt> getListByAttMonId(Long attMonId) {
        LambdaQueryWrapper<SchoolAttOt> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SchoolAttOt::getAttMonId,attMonId);
        return otMapper.selectList(lqw);
    }

    //计算加班时长
    @Override
    public double count(SchoolAttOt schoolAttOt) throws Exception {
        Double hours = 0.0;
        if(StringUtils.isNull(schoolAttOt.getUserType())){
            throw new ServiceException("加班人类型为空");
        }
        if(StringUtils.isNull(schoolAttOt.getStartTime())){
            throw new ServiceException("加班开始时间为空");
        }
        if(StringUtils.isNull(schoolAttOt.getEndTime())){
            throw new ServiceException("加班结束时间为空");
        }
        if(StringUtils.isNull(schoolAttOt.getUserId())){
            throw new ServiceException("加班人id为空");
        }
        /**
         * 判断传入日期是否是同一天
         * 是同一天的话，结束时间是否在开始时间之后
         * 如果指定的数与参数相等返回 0。
         *
         * 如果指定的数小于参数返回 -1。
         *
         * 如果指定的数大于参数返回 1。
         * */
        //格式化为yyyy-MM-dd
        String sDate = HolidayDateUtil.format1.format(schoolAttOt.getStartTime());
        String eDate = HolidayDateUtil.format1.format(schoolAttOt.getEndTime());
        if(0 != sDate.compareTo(eDate)){
            throw new ServiceException("加班日期应选择同一天哦");
        }

        //判断同一天开始时间、结束时间是否合法yyyy-MM-dd HH:mm:ss
        String stTime = HolidayDateUtil.format.format(schoolAttOt.getStartTime());
        String enTime = HolidayDateUtil.format.format(schoolAttOt.getEndTime());
        if(stTime.compareTo(enTime) >= 0){
            throw new ServiceException("加班时间应选择不合法哦");
        }

        //验证通过，准备所需参数
        //获取年月
        Calendar c = Calendar.getInstance();
        c.setTime(schoolAttOt.getStartTime());
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        //该年该月有都多少天
        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");

        //获取开始时间，结束时间HH:mm:ss
        String startTime = HolidayDateUtil.format4.format(schoolAttOt.getStartTime());
        String endTime = HolidayDateUtil.format4.format(schoolAttOt.getEndTime());

        //判断是教工还是职工
        if(EMPLOYEE.equals(schoolAttOt.getUserType())){
            //职工
            //判断是工作日还是非工作日
            //工作日
            if("0".equals(HolidayDateUtil.isLawHoliday(sDate,restList))){
                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 morEnd = HolidayDateUtil.format.parse(sDate + " " + MOREND);
                Date eveStart = HolidayDateUtil.format.parse(sDate + " " + EVESTART);
                if(morEnd.compareTo(schoolAttOt.getEndTime()) <= 0){
                    //在7点15前
                    if(schoolAttOt.getStartTime().compareTo(morEnd) <= 0){
                        //获取第一次打卡时间到在7点15前
                        String sTime = sDate + " " + startTime;
                        String eTime = sDate + " " + MOREND;
                        String h = HolidayDateUtil.dateToStamp(sTime,eTime);
                        hours1 = Double.parseDouble(h);
                    }
                    //晚加班,取最后一次打卡，看是否在18点30之后
                    /**
                     * 二、晚加班：最后一次打开在 6点半之后的。18点30之后算加班 加班时间不能低于半个小时。打卡次数N。
                     * 最后一次打卡时时间-18点30。
                     * */
                    if(schoolAttOt.getEndTime().compareTo(eveStart) > 0){
                        String sTime = sDate + " " + EVESTART;
                        String eTime = sDate + " " + endTime;
                        String h = HolidayDateUtil.dateToStamp(sTime,eTime);
                        hours2 = Double.parseDouble(h);
                    }
                }

                hours = hours1 + hours2;
            }else {
                //非工作日
                /**
                 * 只一次打卡的不统计。  只取第一次和最后一次打开时间。
                 * 取两次打卡内有效时间。（7点15到7点45、  11点30到14点、17点30到18点30 这里边的时间算无效时间）
                 * */
                    String h = HolidayDateUtil.calculateOverHour(startTime,endTime,sDate,MORSTART,MOREND,
                            AMSTARTTIME,AMENDTIME,PMSTARTTIME,PMENDTIME,EVESTART);
                    hours = Double.parseDouble(h);
            }
        }else{
            //教工
            //工作日
            if("0".equals(HolidayDateUtil.isLawHoliday(sDate,restList))){
                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(sDate + " " + attVO.getTime1());
                Date morEnd = HolidayDateUtil.format.parse(sDate + " " + MOREND);
                Date eveStart = HolidayDateUtil.format.parse(sDate + " " + EVESTART);
                Date mid = HolidayDateUtil.format.parse(sDate + " " + "12:00:00");
                if(morEnd.compareTo(schoolAttOt.getEndTime()) <= 0){
                    //在7点15前
                    if(schoolAttOt.getStartTime().compareTo(morEnd) <= 0){
                        //获取第一次打卡时间到在7点15前
                        String sTime = sDate + " " + startTime;
                        String eTime = sDate + " " + MOREND;
                        String h = HolidayDateUtil.dateToStamp(sTime,eTime);
                        hours1 = Double.parseDouble(h);
                    }
                    //晚加班,取最后一次打卡，看是否在18点30之后
                    /**
                     * 二、晚加班：最后一次打开在 6点半之后的。18点30之后算加班 加班时间不能低于半个小时。打卡次数N。
                     * 最后一次打卡时时间-18点30。
                     * */
                    //Date time2 = HolidayDateUtil.format.parse(sDate + " " + timeList.get(timeList.size() - 1));
                    if(schoolAttOt.getEndTime().compareTo(eveStart) > 0){
                        String sTime = sDate + " " + EVESTART;
                        String eTime = sDate + " " + enTime;
                        String h = HolidayDateUtil.dateToStamp(sTime,eTime);
                        hours2 = Double.parseDouble(h);
                    }

                    /**
                     * 三,排上午第四节课的老师，算半节课加班。在生成时 时间就携程 11：30 -12：00就可以。
                     * */
                    if(mid.compareTo(schoolAttOt.getEndTime()) <= 0){
                        //获取当前学年，教师所在班级
//                        int schoolYear = getNewYear();
                        // TODO 修改最新学年
                        int schoolYear = gradeMapper.isNewSchoolYear();
                        List<SchoolClassMentor> mentors = mentorMapper.getMentors(schoolAttOt.getUserId(),schoolYear);
                        //确保该教师在本学年有 所教班级
                        if(isNotNull(mentors) && mentors.size() > 0){
                            //获取当前处于什么学期
                            int termId = isNewTerm();
                            //获取当前日期属于周几
                            int weekValue = HolidayDateUtil.dateToWeekValue(sDate);
                            //判断教师所在班级，当前学年，当前学期当天的第四节课是不是教师所教授的课
                            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;
            }else {
                //非工作日
                /**
                 * 只一次打卡的不统计。  只取第一次和最后一次打开时间。
                 * 取两次打卡内有效时间。（7点15到7点45、  11点30到14点、17点30到18点30 这里边的时间算无效时间）
                 * */
                    String h = HolidayDateUtil.calculateOverHour(startTime,endTime,sDate,MORSTART,MOREND,
                            AMSTARTTIME,AMENDTIME,PMSTARTTIME,PMENDTIME,EVESTART);
                     hours = Double.parseDouble(h);
            }
        }
        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);
            }
        }else {
            hours = 0.0;
        }
        return hours;
    }

    //获取当前学年
    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;
    }

}
