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

import com.baomidou.mybatisplus.core.conditions.Wrapper;
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.entity.SchoolTeacher;
import com.ruoyi.common.core.domain.entity.SysDept;
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 java.text.SimpleDateFormat;
import lombok.Data;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yangtz.cs.liu.campus.domain.schoolAtt.SchoolAtt;
import yangtz.cs.liu.campus.domain.schoolClass.SchoolClass;
import yangtz.cs.liu.campus.domain.schoolgrade.SchoolGrade;
import yangtz.cs.liu.campus.domain.student.SchoolStudent;
import yangtz.cs.liu.campus.domain.workTimes.WorkTime;
import yangtz.cs.liu.campus.mapper.WorkTimes.WorkTimeMapper;
import yangtz.cs.liu.campus.mapper.schoolAtt.SchoolAttMapper;
import yangtz.cs.liu.campus.mapper.schoolgrade.SchoolGradeMapper;
import yangtz.cs.liu.campus.mapper.teacher.SchoolTeacherMapper;
import yangtz.cs.liu.campus.service.schoolAtt.ISchoolAttService;
import yangtz.cs.liu.campus.service.workDay.ISchoolWorkDayService;
import yangtz.cs.liu.campus.vo.schoolAtt.SchoolAttVO;
import yangtz.cs.liu.campus.vo.student.SchoolStudentVO;
import yangtz.cs.liu.campus.vo.teacher.SchoolTeacherDutyVO;
import yangtz.cs.liu.campus.vo.teacher.SchoolTeacherVO;
import yangtz.cs.liu.campus.vo.teacher.TeacherDutyMap;

import java.awt.print.Book;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

import static com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNotNull;
import static com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNull;
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.GradeConstant.NEWTERM;
import static yangtz.cs.liu.campus.constant.SexConstant.MAN;

@Service
public class SchoolAttServiceImpl extends ServiceImpl<SchoolAttMapper, SchoolAtt> implements ISchoolAttService {
    @Autowired
    private SchoolAttMapper schoolAttMapper;
    @Autowired
    private SchoolGradeMapper gradeMapper;
    @Autowired
    private SchoolTeacherMapper teacherMapper;
    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private WorkTimeMapper workTimeMapper;
    @Autowired
    private ISchoolWorkDayService dayService;

    DateFormat df = DateFormat.getTimeInstance();//只显示出时分秒

    @Override
    public List<SchoolAtt> queryList(SchoolAtt schoolAtt) {
        List<SchoolAtt> list = schoolAttMapper.queryList(schoolAtt);
        return list;
    }

    //级部打卡
    @Override
    public List<SchoolAtt> queryGradeList(List<Long> gradeIds, SchoolAtt schoolAtt) {

        List<SchoolAtt> list = schoolAttMapper.queryGradeList(gradeIds,schoolAtt);
        return list;
    }

    //获取包括att在内所有与之在同一天，打卡时间不同的对象,获取打卡时间字符串数组
    public List<String> getSame(SchoolAtt att){
        LambdaQueryWrapper<SchoolAtt> lqw = new LambdaQueryWrapper<>();
        lqw
                .eq(SchoolAtt::getDeviceNum,att.getDeviceNum())
                .eq(SchoolAtt::getTeacherCode,att.getTeacherCode())
                .eq(SchoolAtt::getClockDate,att.getClockDate());
        List<SchoolAtt> sameList = schoolAttMapper.selectList(lqw);
        //按打卡时间从前往后排 这个好像不管用
        //sameList.sort((a,b)->a.getClockTime().compareTo(b.getClockTime()));

        //取出所有打卡时间排序
        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);
                }
            }
        });
        return timeList;
    }

    //打卡记录导出，数据处理
    @Override
    public List<SchoolAttVO> export(SchoolAtt schoolAtt) {
        List<SchoolAtt> list = schoolAttMapper.queryList(schoolAtt);
        if(null == list && list.size() <= 0){
            return new ArrayList<>();
        }

        //最后返回的结果集
        List<SchoolAttVO> voList = new ArrayList<>();

        for(SchoolAtt att : list){
            SchoolAttVO vo = new SchoolAttVO();
            BeanUtils.copyProperties(att,vo);

            //获取该用户同一天内的所有打卡时间
//            List<String> strings = getSame(att);
            String[] strings = att.getClockTime().split(",");
            //给打卡时间1-20赋值
            for(int i = 0; i < strings.length; i++){
                int j = i + 1;
                switch (j){
                    case 1: vo.setTime1(strings[i]); continue;
                    case 2: vo.setTime2(strings[i]); continue;
                    case 3: vo.setTime3(strings[i]); continue;
                    case 4: vo.setTime4(strings[i]); continue;
                    case 5: vo.setTime5(strings[i]); continue;
                    case 6: vo.setTime6(strings[i]); continue;
                    case 7: vo.setTime7(strings[i]); continue;
                    case 8: vo.setTime8(strings[i]); continue;
                    case 9: vo.setTime9(strings[i]); continue;
                    case 10: vo.setTime10(strings[i]); continue;
                    case 11: vo.setTime11(strings[i]); continue;
                    case 12: vo.setTime12(strings[i]); continue;
                    case 13: vo.setTime13(strings[i]); continue;
                    case 14: vo.setTime14(strings[i]); continue;
                    case 15: vo.setTime15(strings[i]); continue;
                    case 16: vo.setTime16(strings[i]); continue;
                    case 17: vo.setTime17(strings[i]); continue;
                    case 18: vo.setTime18(strings[i]); continue;
                    case 19: vo.setTime19(strings[i]); continue;
                    case 20: vo.setTime20(strings[i]);
                }
            }

            vo.setClockTime(null);
            vo.setId(null);
            voList.add(vo);
        }
        //结果集List中含有重复值，去除重复值
//        List<SchoolAttVO> unique = voList.stream().distinct().collect(Collectors.toList());
        return voList;
    }

    @Override
    public List<SchoolAttVO> exportGrade(List<Long> gradeIds, SchoolAtt schoolAtt) {
        List<SchoolAtt> list = schoolAttMapper.queryGradeList(gradeIds,schoolAtt);
        if(null == list && list.size() <= 0){
            return new ArrayList<>();
        }

        //最后返回的结果集
        List<SchoolAttVO> voList = new ArrayList<>();

        for(SchoolAtt att : list){
            SchoolAttVO vo = new SchoolAttVO();
            BeanUtils.copyProperties(att,vo);

            //获取该用户同一天内的所有打卡时间
//            List<String> strings = getSame(att);
            String[] strings = att.getClockTime().split(",");
            //给打卡时间1-20赋值
            for(int i = 0; i < strings.length; i++){
                int j = i + 1;
                switch (j){
                    case 1: vo.setTime1(strings[i]); continue;
                    case 2: vo.setTime2(strings[i]); continue;
                    case 3: vo.setTime3(strings[i]); continue;
                    case 4: vo.setTime4(strings[i]); continue;
                    case 5: vo.setTime5(strings[i]); continue;
                    case 6: vo.setTime6(strings[i]); continue;
                    case 7: vo.setTime7(strings[i]); continue;
                    case 8: vo.setTime8(strings[i]); continue;
                    case 9: vo.setTime9(strings[i]); continue;
                    case 10: vo.setTime10(strings[i]); continue;
                    case 11: vo.setTime11(strings[i]); continue;
                    case 12: vo.setTime12(strings[i]); continue;
                    case 13: vo.setTime13(strings[i]); continue;
                    case 14: vo.setTime14(strings[i]); continue;
                    case 15: vo.setTime15(strings[i]); continue;
                    case 16: vo.setTime16(strings[i]); continue;
                    case 17: vo.setTime17(strings[i]); continue;
                    case 18: vo.setTime18(strings[i]); continue;
                    case 19: vo.setTime19(strings[i]); continue;
                    case 20: vo.setTime20(strings[i]);
                }
            }

            vo.setClockTime(null);
            vo.setId(null);
            voList.add(vo);
        }
        //结果集List中含有重复值，去除重复值
//        List<SchoolAttVO> unique = voList.stream().distinct().collect(Collectors.toList());
        return voList;
    }

    /**
     * 导入数据校验
     * @param list
     */
    @Override
    public void checkImport(List<SchoolAttVO> list) {
        //检验是否为空
        if (StringUtils.isNull(list) || list.size() == 0) {
            throw new ServiceException("导入数据不能为空");
        }

        // 准备记录日志数据
        int failureNum = 0;
        StringBuilder failureMsg = new StringBuilder();
        for (SchoolAttVO schoolAttVO : list) {
            if (StringUtils.isEmpty(schoolAttVO.getDeviceNum())) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、设备工号为空,请您重新输入! ");
            } else if (StringUtils.isEmpty(schoolAttVO.getUserName())) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、姓名为空,请您重新输入! ");
            }  else if (StringUtils.isEmpty(schoolAttVO.getOrgname())) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、部门为空,请您重新输入! ");
            } else if (StringUtils.isNull(schoolAttVO.getClockDate())) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、考勤日期为空,请您重新输入! ");
            } else {
                //根据设备工号，查询该教职工
                SchoolTeacherVO teacherVO = teacherMapper.judge(schoolAttVO.getDeviceNum());
                if(isNull(teacherVO)){
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + schoolAttVO.getUserName() + "、不存在,请您重新输入! ");
                }else{
                    //获取是教工还是职工
                    if(teacherVO.getEmployeeType().equals(EMPLOYEE)){
                        schoolAttVO.setOrgid(teacherVO.getDeptId());
                        SysDept dept = deptMapper.selectDeptById(teacherVO.getDeptId());
                        schoolAttVO.setOrgname(dept.getDeptName());
                        schoolAttVO.setUserId(teacherVO.getId());
                        schoolAttVO.setTeacherCode(teacherVO.getTeacherCode());
                        schoolAttVO.setUserType(teacherVO.getEmployeeType());
                    }else{
                        //教工
                        schoolAttVO.setUserId(teacherVO.getId());
                        schoolAttVO.setTeacherCode(teacherVO.getTeacherCode());
                        schoolAttVO.setUserType(teacherVO.getEmployeeType());
                        // TODO 修改最新学年
                        int newSchoolYear = gradeMapper.isNewSchoolYear();
                        //根据年级名称和最新学年获取级部id
                        LambdaQueryWrapper<SchoolGrade> lqw = new LambdaQueryWrapper<>();
                        lqw
                                .eq(SchoolGrade::getGradeName,schoolAttVO.getOrgname())
                                .eq(SchoolGrade::getSchoolYear,newSchoolYear);
                        SchoolGrade grade = gradeMapper.selectOne(lqw);
                        if(StringUtils.isNotNull(grade)){
                            schoolAttVO.setOrgid(grade.getId());
                            schoolAttVO.setOrgname(grade.getGradeName());
                        }else{
                            throw new ServiceException("当前学年为"+newSchoolYear+"学年，"+schoolAttVO.getUserName()+"所在级部名称为"+schoolAttVO.getOrgname()+"的级部不存在，请检查");
                        }
                    }

                    //判断当前数据是否在数据库中已存在，如果存在则删除
                    LambdaQueryWrapper<SchoolAtt> lqw = new LambdaQueryWrapper<>();
                    lqw
                            .eq(SchoolAtt::getDeviceNum, schoolAttVO.getDeviceNum())
                            .eq(SchoolAtt::getUserName, schoolAttVO.getUserName())
                            .eq(SchoolAtt::getClockDate, schoolAttVO.getClockDate());
                    List<SchoolAtt> existList = schoolAttMapper.selectList(lqw);
                    if(0 == existList.size()){
                        continue;
                    }
                    List<Long> idList = existList.stream().map(SchoolAtt -> SchoolAtt.getId()).collect(Collectors.toList());
                    schoolAttMapper.deleteBatchIds(idList);
                }
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        }
    }

    @Override
    public List<SchoolAtt> dealData(List<SchoolAttVO> list) {
        //处理好的结果集
        List<SchoolAtt> attList = new ArrayList<>();
        for (SchoolAttVO attVO : list){
            List<String> times = new ArrayList<>();
            if(StringUtils.isNotNull(attVO.getTime1()) && attVO.getTime1() != ""){
                times.add(attVO.getTime1());
            }
            if(StringUtils.isNotNull(attVO.getTime2()) && attVO.getTime2() != ""){
                times.add(attVO.getTime2());
            }
            if(StringUtils.isNotNull(attVO.getTime3()) && attVO.getTime3() != ""){
                times.add(attVO.getTime3());
            }
            if(StringUtils.isNotNull(attVO.getTime4()) && attVO.getTime4() != ""){
                times.add(attVO.getTime4());
            }
            if(StringUtils.isNotNull(attVO.getTime5()) && attVO.getTime5() != ""){
                times.add(attVO.getTime5());
            }
            if(StringUtils.isNotNull(attVO.getTime6()) && attVO.getTime6() != ""){
                times.add(attVO.getTime6());
            }
            if(StringUtils.isNotNull(attVO.getTime7()) && attVO.getTime7() != ""){
                times.add(attVO.getTime7());
            }
            if(StringUtils.isNotNull(attVO.getTime8()) && attVO.getTime8() != ""){
                times.add(attVO.getTime8());
            }
            if(StringUtils.isNotNull(attVO.getTime9()) && attVO.getTime9() != ""){
                times.add(attVO.getTime9());
            }
            if(StringUtils.isNotNull(attVO.getTime10()) && attVO.getTime10() != ""){
                times.add(attVO.getTime10());
            }
            if(StringUtils.isNotNull(attVO.getTime11()) && attVO.getTime11() != ""){
                times.add(attVO.getTime11());
            }
            if(StringUtils.isNotNull(attVO.getTime12()) && attVO.getTime12() != ""){
                times.add(attVO.getTime12());
            }
            if(StringUtils.isNotNull(attVO.getTime13()) && attVO.getTime13() != ""){
                times.add(attVO.getTime13());
            }
            if(StringUtils.isNotNull(attVO.getTime14()) && attVO.getTime14() != ""){
                times.add(attVO.getTime14());
            }
            if(StringUtils.isNotNull(attVO.getTime15()) && attVO.getTime15() != ""){
                times.add(attVO.getTime15());
            }
            if(StringUtils.isNotNull(attVO.getTime16()) && attVO.getTime16() != ""){
                times.add(attVO.getTime16());
            }
            if(StringUtils.isNotNull(attVO.getTime17()) && attVO.getTime17() != ""){
                times.add(attVO.getTime17());
            }
            if(StringUtils.isNotNull(attVO.getTime18()) && attVO.getTime18() != ""){
                times.add(attVO.getTime18());
            }
            if(StringUtils.isNotNull(attVO.getTime19()) && attVO.getTime19() != ""){
                times.add(attVO.getTime19());
            }
            if(StringUtils.isNotNull(attVO.getTime20()) && attVO.getTime20() != ""){
                times.add(attVO.getTime20());
            }

            if(StringUtils.isNull(times) || times.size() == 0){
                SchoolAtt att = new SchoolAtt();
                BeanUtils.copyProperties(attVO,att);
                attList.add(att);
                continue;
            }else {
                for(String time : times){
                    SchoolAtt att = new SchoolAtt();
                    BeanUtils.copyProperties(attVO,att);
                    try {
                        String t = HolidayDateUtil.getTime(time);
                        att.setClockTime(t);
                        attList.add(att);
                    }catch (Exception e){
                        throw new ServiceException("格式转换出错");
                    }

                }
            }
        }
        return attList;
    }

    /**
     * 验证是否迟到、早退
     * @param list
     * @return
     */
    @Override
    public List<SchoolAtt> verifyLateness(List<SchoolAtt> list) throws Exception {
        List<SchoolAtt> handUserAttList = new ArrayList<>();
        String codeUser = null;
        //当前年月份内获取周末、节假日日期
        for (SchoolAtt data :list) {
            List<SchoolAtt> attUserList = new ArrayList<>();
            //将对每个人信息信息处理
            if (codeUser!=null && data.getTeacherCode().equals(codeUser)){
                continue;
            }
                for (SchoolAtt times :list) {
                    if (data.getTeacherCode().equals(times.getTeacherCode()) && (0 == data.getClockDate().compareTo(times.getClockDate()))){
                        codeUser =times.getTeacherCode();
                        attUserList.add(times);
                    }
                }
            //处理个人时间信息
            this.handleAttList(attUserList);
            //存储到新得List中
            handUserAttList.addAll(attUserList);
        }
        return handUserAttList;
    }

    private void handleAttList(List<SchoolAtt> list) throws Exception {
        //迟到
        Boolean beLateFlag = false;
        //早上是否有过第一次打卡
        Boolean amFlag = false;
        //下午第一次打卡
        Boolean pmFlag = false;

        //获取时间段
        List<WorkTime> workTimes = workTimeMapper.selectList(new LambdaQueryWrapper<WorkTime>());
        WorkTime workTime = workTimes.get(0);
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        Date parse = sdf.parse("5:00");
        //上午打卡起始世界
        Calendar parseCal = Calendar.getInstance();
        parseCal.setTime(parse);

        //上午开始时间
       Calendar amStartIime = Calendar.getInstance();
        amStartIime.setTime(workTime.getAmStartTime());
        //上午结束时间
        Calendar amEndTime = Calendar.getInstance();
        amEndTime.setTime(workTime.getAmEndTime());
        //上午工作迟到时间点
        Calendar amLateTime = Calendar.getInstance();
        amLateTime.setTime(workTime.getAmLateTime());
        //下午开始时间
        Calendar pmStartTime = Calendar.getInstance();
        pmStartTime.setTime(workTime.getPmStartTime());
        //下午结束时间
        Calendar pmEndtTime = Calendar.getInstance();
        pmEndtTime.setTime(workTime.getPmEndTime());
        //下午打卡时间开始点
        Calendar pmMiddleTime = Calendar.getInstance();
        pmMiddleTime.setTime(workTime.getPmMiddleTime());
        //下午工作迟到时间点
        Calendar pmLateTime = Calendar.getInstance();
        pmLateTime.setTime(workTime.getPmLateTime());
        //当前打卡世界
        Calendar clockTime = Calendar.getInstance();

        List<String> restList = dayService.getHolidayList("1");

        //判断每个人的打卡时间

        for (SchoolAtt data: list){
            clockTime.setTime(sdf.parse(data.getClockTime()));
            //0判断当前是否是工作日
            if ("0".equals(HolidayDateUtil.isLawHoliday(data.getClockDate().toString(),restList))){
                //判断时间端在早上5到 早上第一个打卡时间内
                if (clockTime.after(parseCal) && clockTime.before(amStartIime)){
                    amFlag = true;
                }else if (clockTime.after(amStartIime) && clockTime.before(amLateTime)){
                    //打卡时间在7.30到9.0之前判断是否有过第一次打卡，没有则迟到，有无效
                    if (!amFlag){
                        data.setWorkStatus("迟到");
                        continue;
                    }
                } else if (clockTime.after(amLateTime) && clockTime.before(amEndTime) ) {
                    //打卡时间在迟到时间到到下班时间点打卡 就是早退
                    data.setWorkStatus("早退");
                    continue;
                } else if (clockTime.after(pmMiddleTime) && clockTime.before(pmStartTime)) {
                    //1点到 下午打卡开始时间
                    pmFlag = true;
                } else if (clockTime.after(pmStartTime) && clockTime.before(pmLateTime)) {
                    //下午开始时间到迟到时间
                    if (!pmFlag){
                        data.setWorkStatus("迟到");
                       continue;
                    }
                } else if (clockTime.after(pmLateTime) && clockTime.before(pmEndtTime)) {
                    //下午卡点时间 到下班时间
                    data.setWorkStatus("早退");
                    continue;
                }
            }

        }




    }
    /**
     * 导入数据
     * */
    @Override
    @Transactional
    public String importData(List<SchoolAtt> list) {
        // 准备记录日志数据
        int successNum = 0;
        StringBuilder successMsg = new StringBuilder();

        // TODO 修改导入
        try{
            schoolAttMapper.insertAttList(list);
        }catch (Exception e){
            throw new ServiceException("导入失败");
        }
//        // 遍历并逐个导入
//        for (SchoolAtt schoolAtt : list) {
//            try {
//                schoolAttMapper.insert(schoolAtt);
//                successNum++;
//                //successMsg.append("<br/>" + successNum + "数据" + " 导入成功");
//            } catch (Exception e) {
//                throw new ServiceException("导入失败");
//            }
//        }
        successMsg.insert(0, "恭喜您，数据已导入成功！");
        return successMsg.toString();
    }

    @Override
    public List<SchoolAtt> getDetailsList(Long userId, String date) {
        LambdaQueryWrapper<SchoolAtt> lqw = new LambdaQueryWrapper<>();
        lqw
                .eq(StringUtils.isNotNull(date), SchoolAtt::getClockDate, date)
                .eq(SchoolAtt::getUserId, userId)
                .orderByAsc(SchoolAtt::getClockTime)
        ;
       return schoolAttMapper.selectList(lqw);
    }
    /**
     * 个人工作-编辑备注
     * 因为没有对应id，所以根据设备工号+考勤日期进行编辑
     * */
    @Override
    public int editRemark(SchoolAttVO vo) {
        if(StringUtils.isNull(vo.getRemark())){
            throw new ServiceException("备注不能为空");
        }
        LambdaUpdateWrapper<SchoolAtt> luw = new LambdaUpdateWrapper<>();
        luw
                .eq(SchoolAtt::getDeviceNum,vo.getDeviceNum())
                .eq(SchoolAtt::getClockDate,vo.getClockDate())
                .set(SchoolAtt::getRemark,vo.getRemark())
                ;
        return schoolAttMapper.update(null,luw);
    }


}
