package com.mortals.xhx.module.attendance.service.work;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.OrderCol;
import com.mortals.framework.util.ThreadPool;
import com.mortals.xhx.common.code.*;
import com.mortals.xhx.module.attendance.model.*;
import com.mortals.xhx.module.attendance.service.*;
import com.mortals.xhx.module.check.model.CheckAttendRecordEntity;
import com.mortals.xhx.module.check.model.CheckAttendRecordQuery;
import com.mortals.xhx.module.check.service.CheckAttendRecordService;
import com.mortals.xhx.module.holiday.model.HolidayEntity;
import com.mortals.xhx.module.holiday.model.HolidayQuery;
import com.mortals.xhx.module.holiday.service.HolidayService;
import com.mortals.xhx.module.perform.model.PerformAttendRecordEntity;
import com.mortals.xhx.module.perform.model.PerformAttendRecordQuery;
import com.mortals.xhx.module.perform.model.PerformErrorMessageEntity;
import com.mortals.xhx.module.perform.model.PerformErrorMessageQuery;
import com.mortals.xhx.module.perform.service.PerformAttendRecordService;
import com.mortals.xhx.module.perform.service.PerformErrorMessageService;
import com.mortals.xhx.utils.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StopWatch;

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

/**
 * 固定班
 *
 * @author:
 * @date: 2023/7/31 15:15
 */
@Slf4j
public class FixWorkOtherAttendance extends AttendanceWorkAbstract {

    private AttendanceGroupFixedworkService attendanceGroupFixedworkService;

    private AttendanceRecordErrorService errorService;

    private AttendanceLeaveRecordService attendanceLeaveRecordService;

    private Map<Long, AttendanceClassDetailEntity> classDetailEntityMap;

    private CommonData commonData;

    private PerformAttendRecordService performAttendRecordService;

    private CheckAttendRecordService checkAttendRecordService;

    private PerformErrorMessageService performErrorMessageService;

    public FixWorkOtherAttendance(int type) {
        super(type);
        this.attendanceGroupFixedworkService = SpringUtils.getBean(AttendanceGroupFixedworkService.class);
        this.errorService = SpringUtils.getBean(AttendanceRecordErrorService.class);
        this.attendanceLeaveRecordService = SpringUtils.getBean(AttendanceLeaveRecordService.class);
        this.performAttendRecordService = SpringUtils.getBean(PerformAttendRecordService.class);
        this.checkAttendRecordService = SpringUtils.getBean(CheckAttendRecordService.class);
        this.performErrorMessageService = SpringUtils.getBean(PerformErrorMessageService.class);

    }

    @Override
    int getType() {
        return TypeEnum.固定班制.getValue();
    }

    @Override
    void initData() {
    }

    @Override
    public void doHandleWork(CommonData commonData) {
        this.commonData = commonData;
        //todo 从缓存中获取
        AttendanceGroupFixedworkEntity attendanceGroupFixedworkEntity = attendanceGroupFixedworkService.selectOne(new AttendanceGroupFixedworkQuery()
                .groupId(commonData.getAttendanceGroupEntity().getId()));
        Map<Long, AttendanceClassEntity> classEntityMap = commonData.getClassEntityMap();
        Map<Long, List<AttendanceGroupFixedworkSpecialEntity>> fixedSpecialGroupMap = commonData.getFixedSpecialGroupMap();
        this.classDetailEntityMap = commonData.getClassDetailEntityMap();
        if (ObjectUtils.isEmpty(attendanceGroupFixedworkEntity)) {
            log.info("attendanceGroupFixedworkEntity is null ! groupId:{}", commonData.getAttendanceGroupEntity().getId());
            return;
        }
        //判断当前考勤日期为周几
        String week = super.getWeek(DateUtil.parseDate(commonData.getDateStr()));
        //获取当前日期的详细班次
        Long weekClassId = this.getWeekClassId(attendanceGroupFixedworkEntity, week);
        //weekClassId为-1 则不在考勤  todo 优化
        Boolean checkWorkByHoliday = checkWorkByHoliday(commonData.getDateStr());
        Boolean checkHolidayByWorkDay = checkHolidayByWorkDay(commonData.getDateStr());
        if (weekClassId == -1L) {
            //跳过本次循环
            if (!checkWorkByHoliday) {
                // log.info("当前日期不在考勤时间范围内，不做处理！");
                return;
            } else {
                //工作日要上班 获取配置的周六 周日班次 默认周一
                weekClassId = this.getWeekClassId(attendanceGroupFixedworkEntity, "星期一");
            }
        } else {
            if (checkHolidayByWorkDay) {
                //本来当天是需要考勤的，但是是节假日，则不计算考勤
                return;
            }
        }
        //判断当天是否请假 请假分为多个区间段与请假类型。
        AttendanceLeaveRecordQuery leaveRecordQuery = new AttendanceLeaveRecordQuery();
        leaveRecordQuery.setLeavePersonId(commonData.getStaffId());
        leaveRecordQuery.setAuditResultList(Arrays.asList(1, 4));
        boolean isLeave = false;
        //todo 从缓存中获取
        List<AttendanceLeaveRecordEntity> leaveRecordEntities = attendanceLeaveRecordService.find(leaveRecordQuery);
        List<AttendanceLeaveRecordEntity> leaveRecords = null;
        if (!ObjectUtils.isEmpty(leaveRecordEntities)) {
            //判断当日日期中 是否有请假记录
            leaveRecords = leaveRecordEntities.stream().filter(f -> {
                String curDateStr = commonData.getDateStr();
                DateTime dateTime = DateUtil.parseDate(curDateStr);
                DateTime start = DateUtil.parseDate(DateUtil.formatDate(f.getStartTime()));
                DateTime end = DateUtil.parseDate(DateUtil.formatDate(f.getEndTime()));
                boolean in = DateUtil.isIn(dateTime, start, end);
                return in;
            }).collect(Collectors.toList());

            if (!ObjectUtils.isEmpty(leaveRecords)) {
                //当前日期范围内 存在请假。判断请假计入考勤。目前只有事件计入
                isLeave = true;
            }
        }
        //特殊日期考勤配置
        List<AttendanceGroupFixedworkSpecialEntity> specialEntities = fixedSpecialGroupMap.get(attendanceGroupFixedworkEntity.getId());
        if (!ObjectUtils.isEmpty(specialEntities)) {
            //分组 需要考勤与不需要考勤
            Map<Boolean, List<AttendanceGroupFixedworkSpecialEntity>> collect = specialEntities.stream().collect(Collectors.partitioningBy(item -> item.getMust() == MustEnum.是.getValue()));
            List<AttendanceGroupFixedworkSpecialEntity> mustList = collect.get(true);
            if (!ObjectUtils.isEmpty(mustList)) {
                //需要打卡
                for (AttendanceGroupFixedworkSpecialEntity specialEntity : mustList) {
                    //必须考勤时间，单位日
                    Date specialTime = specialEntity.getSpecialTime();
                    //判断当前考勤日期是否需要考勤，如果需要重叠 则更新为特殊日期考勤
                    //判断考勤日期与特殊日期是否一致
                    if (!ObjectUtils.isEmpty(specialTime) && DateUtil.formatDate(commonData.getAttendanceDate()).equals(DateUtil.formatDate(specialTime))) {
                        //更新打卡情况
                        if (!ObjectUtils.isEmpty(specialEntity.getClassId())) {
                            weekClassId = specialEntity.getClassId();
                        }
                    }
                }
            }
            List<AttendanceGroupFixedworkSpecialEntity> mustNotList = collect.get(false);
            if (!ObjectUtils.isEmpty(mustNotList)) {
                //不需要考勤 查看是时间段还是单独时间
                for (AttendanceGroupFixedworkSpecialEntity specialEntity : mustNotList) {
                    if (AddWayEnum.单个日期.getValue() == specialEntity.getAddWay()) {
                        Date specialTime = specialEntity.getSpecialTime();
                        if (!ObjectUtils.isEmpty(specialTime) && DateUtil.parseDate(commonData.getDateStr()).equals(DateUtil.formatDate(specialTime))) {
                            log.info("当天特殊日期，无需考勤！dateStr:{}", commonData.getDateStr());
                            return;
                        }
                    }
                    if (AddWayEnum.时间段.getValue() == specialEntity.getAddWay()) {
                        Date specialStartTime = specialEntity.getSpecialStartTime();
                        Date specialEndTime = specialEntity.getSpecialEndTime();
                        if (!ObjectUtils.isEmpty(specialStartTime) && !ObjectUtils.isEmpty(specialEndTime)) {
                            boolean in = DateUtil.isIn(DateUtil.parseDate(commonData.getDateStr()), specialStartTime, specialEndTime);
                            if (in) {
                                //直接返回 无班次信息
                                log.info("当天特殊日期，无需考勤！dateStr:{}", commonData.getDateStr());
                                return;
                            }
                        }
                    }
                }
            }
        }
        //获取班次信息
        AttendanceClassEntity attendanceClassEntity = classEntityMap.get(weekClassId);
        if (ObjectUtils.isEmpty(attendanceClassEntity)) {
            log.info("attendanceClassEntity is null ,weekClassId:{}", weekClassId);
            return;
        }
        List<AttendanceRecordHikEntity> recordHikEntities = commonData.getRecordHikEntities();
        List<AttendanceClassDetailEntity> attendanceClassDetailEntities = attendanceClassEntity.getAttendanceClassDetailList();
        Integer orderNum = 0;
        for (AttendanceClassDetailEntity classDetailEntity : attendanceClassDetailEntities) {
            orderNum++;
            AttendanceRecordDetailEntity recordDetailEntity = new AttendanceRecordDetailEntity();
            recordDetailEntity.setShiftsId(classDetailEntity.getId());
            recordDetailEntity.setShiftsName(classDetailEntity.getClassName());
            recordDetailEntity.setGoWorkResult(GoWorkResultEnum.缺卡.getValue());
            recordDetailEntity.setOffWorkResult(GoWorkResultEnum.缺卡.getValue());
            recordDetailEntity.setOrderNum(orderNum);
            commonData.getDetailEntityList().add(recordDetailEntity);
        }
        if (!ObjectUtils.isEmpty(recordHikEntities)) {
            //针对当天的考勤记录进行计算与判断
            //获取当前班的多个班次，一个班次为一个上下班时间段
            for (AttendanceRecordHikEntity recordHikEntity : recordHikEntities) {
                Date attendanceDate = recordHikEntity.getAttendanceDate();
                //遍历班次详细记录
                for (AttendanceClassDetailEntity classDetail : attendanceClassDetailEntities) {
                    //计算区间范围
                    //上班打卡前时间
                    Date goWorkDateBefore = DateUtil.offsetMinute(classDetail.getGoWorkDate(), -classDetail.getGoWorkDateBefore() - 1);
                    //上班打卡后时间
                    Date goWorkDateAfter = DateUtil.offsetMinute(classDetail.getGoWorkDate(), classDetail.getGoWorkDateAfter() + 1);
                    // 下班打卡前时间
                    Date offWorkDateBefore = DateUtil.offsetMinute(classDetail.getOffWorkDate(), -classDetail.getOffWorkDateBefore() - 1);
                    //下班打卡后时间,默认偏移多一分钟
                    Date offWorkDateAfter = DateUtil.offsetMinute(classDetail.getOffWorkDate(), classDetail.getOffWorkDateAfter() + 1);
                    //判断考勤时间是否在上班打卡区间内  true 在 false 不在  格式化时间
                    //String currDate = DateUtil.formatTime(attendanceDate);
                    Date curDateTime = DateUtil.parseTime(DateUtil.formatTime(attendanceDate));
                    boolean goInTime = DateUtil.isIn(curDateTime, goWorkDateBefore, goWorkDateAfter);
                    //判断考勤时间是否在下班打卡区间内
                    boolean offInTime = DateUtil.isIn(curDateTime, offWorkDateBefore, offWorkDateAfter);
                    //判断在上班与下班区间访问内   在上班的最后时间 与下班的开始时间
                    boolean goOffBetweenTime = DateUtil.isIn(curDateTime, goWorkDateAfter, offWorkDateBefore);
                    boolean updateCheck = false;
                    if (goInTime) {
                        //如果是上班打卡区间范围,判断是否迟到
                        for (AttendanceRecordDetailEntity attendanceRecordDetailEntity : commonData.getDetailEntityList()) {
                            if (attendanceRecordDetailEntity.getShiftsId() == classDetail.getId()) {
                                attendanceRecordDetailEntity.setGoWorkResult(GoWorkResultEnum.正常.getValue());
                                attendanceRecordDetailEntity.setGoWorkDate(recordHikEntity.getAttendanceDate());
                                updateCheck = true;
                            }
                        }
                    } else {
                        if (goOffBetweenTime) {
                            for (AttendanceRecordDetailEntity attendanceRecordDetailEntity : commonData.getDetailEntityList()) {
                                if (attendanceRecordDetailEntity.getShiftsId() == classDetail.getId() && GoWorkResultEnum.缺卡.getValue() == attendanceRecordDetailEntity.getGoWorkResult()) {
                                    attendanceRecordDetailEntity.setGoWorkResult(GoWorkResultEnum.迟到.getValue());
                                    attendanceRecordDetailEntity.setGoWorkDate(recordHikEntity.getAttendanceDate());
                                    updateCheck = true;
                                }
                            }
                        }
                    }
                    if (offInTime) {
                        for (AttendanceRecordDetailEntity attendanceRecordDetailEntity : commonData.getDetailEntityList()) {
                            if (attendanceRecordDetailEntity.getShiftsId() == classDetail.getId()) {
                                attendanceRecordDetailEntity.setOffWorkResult(OffWorkResultEnum.正常.getValue());
                                attendanceRecordDetailEntity.setOffWorkDate(recordHikEntity.getAttendanceDate());
                            }
                        }
                    } else {
                        if (goOffBetweenTime) {
                            for (AttendanceRecordDetailEntity attendanceRecordDetailEntity : commonData.getDetailEntityList()) {
                                if (attendanceRecordDetailEntity.getShiftsId() == classDetail.getId() && !updateCheck) {
                                    attendanceRecordDetailEntity.setOffWorkResult(OffWorkResultEnum.早退.getValue());
                                    attendanceRecordDetailEntity.setOffWorkDate(recordHikEntity.getAttendanceDate());
                                }
                            }
                        }
                    }
                }
            }
        }
        if (!ObjectUtils.isEmpty(commonData.getDetailEntityList())) {
            //判断当前计算的时间，如果小于缺卡打卡时间 则删除详细考勤记录
            Iterator<AttendanceRecordDetailEntity> iterator = commonData.getDetailEntityList().iterator();
            while (iterator.hasNext()) {
                AttendanceRecordDetailEntity next = iterator.next();
                if (next.getGoWorkResult() == GoWorkResultEnum.缺卡.getValue()) {
                    if (DateUtil.compare(new Date(), next.getGoWorkDate()) < 0) {
                        iterator.remove();
                    }
                }
                if (next.getOffWorkResult() == OffWorkResultEnum.缺卡.getValue()) {
                    if (DateUtil.compare(new Date(), next.getOffWorkDate()) < 0) {
                        next.setOffWorkDate(null);
                        next.setOffWorkResult(null);
                    }
                }
            }
            AttendanceClassDetailEntity attendanceClassDetailEntity = classDetailEntityMap.get(commonData.getDetailEntityList().get(0).getShiftsId());
            commonData.getAttendanceRecordEntity().setClassId(attendanceClassDetailEntity == null ? 0L : attendanceClassDetailEntity.getClassId());
            commonData.getAttendanceRecordEntity().setClassName(attendanceClassDetailEntity == null ? "" : attendanceClassDetailEntity.getClassName());
        }
        //todo 判断当日当前人员是否存在请假，有请假则重新计算考勤  并根据时间段 更新详细记录中的请假状态
        if (isLeave) {
            //查看请假时间段，是否为跨天记录
            for (AttendanceLeaveRecordEntity leaveRecord : leaveRecords) {
                long between = DateUtil.between(leaveRecord.getStartTime(), leaveRecord.getEndTime(), DateUnit.DAY);
                if (between > 0) {
                    //跨天 判断当前日期是否在全天，没在 就
                    //判断日期是否在最后一天 不是的话 为全天
                    long betweened = DateUtil.between(DateUtil.parseDate(commonData.getDateStr()), leaveRecord.getEndTime(), DateUnit.DAY);
                    if (betweened > 0) {
                        //全天
                        calLeaveDate(commonData, DateUtil.parseDateTime(commonData.getDateStr() + " 00:00:00"), DateUtil.parseDateTime(commonData.getDateStr() + " 23:59:59"));
                    } else if (betweened == 0) {
                        //最后一天
                        calLeaveDate(commonData, DateUtil.parseDateTime(commonData.getDateStr() + " 00:00:00"), leaveRecord.getEndTime());
                    }
                } else if (between == 0) {
                    calLeaveDate(commonData, leaveRecord.getStartTime(), leaveRecord.getEndTime());
                } else {
                    //错误
                }
            }
        }
        //生成异常记录
        // StopWatch stopWatch = new StopWatch();
        //  stopWatch.start("生成异常记录耗时");
        genErrorAttendRecord(commonData.getContext(), commonData.getDateStr(), commonData.getAttendanceRecordEntity(), commonData.getDetailEntityList());
        // stopWatch.stop();
        // log.info("生成异常记录耗时：{}ms", stopWatch.getLastTaskTimeMillis());
    }

    /**
     * 计算异常
     *
     * @param commonData
     * @param startLeaveTime
     * @param endLeaveTime
     */
    private void calLeaveDate(CommonData commonData, Date startLeaveTime, Date endLeaveTime) {
        //当日 请假开始时间
        //修改当日记录集
        List<AttendanceRecordDetailEntity> detailEntityList = commonData.getDetailEntityList();
        for (AttendanceRecordDetailEntity detail : detailEntityList) {
            Integer goWorkResult = detail.getGoWorkResult();
            Integer offWorkResult = detail.getOffWorkResult();
            Date goWorkDate = detail.getGoWorkDate();
            Date offWorkDate = detail.getOffWorkDate();
            AttendanceClassDetailEntity attendanceClassDetailEntity = classDetailEntityMap.get(detail.getShiftsId());
            if (GoWorkResultEnum.请假.getValue() < goWorkResult) {
                //判断 异常记录是否在请假时间段内 如果缺卡是没有goWorkDate的
                if (ObjectUtils.isEmpty(goWorkDate)) {
                    //goWorkDate为空 缺卡状态
                    Date goWorkDate1 = attendanceClassDetailEntity.getGoWorkDate();
                    if (attendanceClassDetailEntity.getGoWorkDateAfter() > 0) {
                        goWorkDate1 = DateUtil.offsetMinute(goWorkDate1, attendanceClassDetailEntity.getGoWorkDateAfter());
                    }
                    //判断请假区间是否在上班区间内 如果在 则设置为请假 格式化时间范围
                    boolean in = DateUtil.isIn(goWorkDate1, DateUtil.parse(DateUtil.format(startLeaveTime, "HH:mm:ss"), "HH:mm:ss"),
                            DateUtil.parse(DateUtil.format(endLeaveTime, "HH:mm:ss"), "HH:mm:ss"));
                    if (in) {
                        detail.setGoWorkResult(GoWorkResultEnum.请假.getValue());
                    }
                } else {
                    boolean in = DateUtil.isIn(goWorkDate, startLeaveTime, endLeaveTime);
                    if (in) {
                        detail.setGoWorkResult(GoWorkResultEnum.请假.getValue());
                    }
                }
            }
            if (GoWorkResultEnum.请假.getValue() < offWorkResult) {
                //判断 异常记录是否在请假时间段内
                if (ObjectUtils.isEmpty(offWorkDate)) {
                    Date offWorkDate1 = attendanceClassDetailEntity.getOffWorkDate();
                    if (attendanceClassDetailEntity.getOffWorkDateBefore() > 0) {
                        offWorkDate1 = DateUtil.offsetMinute(offWorkDate1, -attendanceClassDetailEntity.getOffWorkDateBefore());
                    }
                    boolean in = DateUtil.isIn(offWorkDate1, DateUtil.parse(DateUtil.format(startLeaveTime, "HH:mm:ss"), "HH:mm:ss"),
                            DateUtil.parse(DateUtil.format(endLeaveTime, "HH:mm:ss"), "HH:mm:ss"));
                    if (in) {
                        detail.setOffWorkResult(GoWorkResultEnum.请假.getValue());
                    }
                } else {
                    boolean in = DateUtil.isIn(offWorkDate, startLeaveTime, endLeaveTime);
                    if (in) {
                        detail.setOffWorkResult(GoWorkResultEnum.请假.getValue());
                    }
                }
            }
        }
    }


    public void genErrorAttendRecord(Context context, String dateStr, AttendanceRecordEntity attendanceRecordEntity, List<AttendanceRecordDetailEntity> detailEntityList) {
        //处理异常打卡，所以异常打卡的 都新增一条记录
        List<AttendanceRecordErrorEntity> errorEntityList = new ArrayList<>();
        for (AttendanceRecordDetailEntity recordDetailEntity : detailEntityList) {
            Integer goWorkResult = recordDetailEntity.getGoWorkResult();
            Integer offWorkResult = recordDetailEntity.getOffWorkResult();
            //判断是否是离职员工 如果是 则不添加
            //判断上班
            AttendanceClassDetailEntity attendanceClassDetailEntity = classDetailEntityMap.get(recordDetailEntity.getShiftsId());
            if (ObjectUtils.isEmpty(attendanceClassDetailEntity)) continue;
            //判断上班
            if (GoWorkResultEnum.请假.getValue() < goWorkResult) {
                AttendanceRecordErrorEntity errorEntity = new AttendanceRecordErrorEntity();
                errorEntity.initAttrValue();
                BeanUtils.copyProperties(attendanceRecordEntity, errorEntity, new String[]{"id"});
                errorEntity.setShiftsId(recordDetailEntity.getShiftsId());
                errorEntity.setShiftsName(recordDetailEntity.getShiftsName());
                errorEntity.setProcessStatus(YesNoEnum.NO.getValue());
                errorEntity.setCreateTime(new Date());
                errorEntity.setCreateUserId(1L);
                Date goWorkDate = attendanceClassDetailEntity.getGoWorkDate();
                errorEntity.setGoOffDateTime(DateUtil.parseDateTime(dateStr + " " + DateUtil.formatTime(goWorkDate)).toJdkDate());
                if (!ObjectUtils.isEmpty(recordDetailEntity.getGoWorkDate())) {
                    errorEntity.setErrorDateTime(recordDetailEntity.getGoWorkDate());
                    errorEntity.setActualAttendanceDateTime(recordDetailEntity.getGoWorkDate());
                } else {
                    errorEntity.setErrorDateTime(DateUtil.parseDateTime(dateStr + " " + DateUtil.formatTime(goWorkDate)).toJdkDate());
                }
                if (GoWorkResultEnum.早退.getValue() == recordDetailEntity.getGoWorkResult()) {
                    errorEntity.setErrorStatus(ErrorStatusEnum.早退.getValue());
                }
                if (GoWorkResultEnum.迟到.getValue() == recordDetailEntity.getGoWorkResult()) {
                    errorEntity.setErrorStatus(ErrorStatusEnum.迟到.getValue());
                }
                if (GoWorkResultEnum.缺卡.getValue() == recordDetailEntity.getGoWorkResult()) {
                    errorEntity.setErrorStatus(ErrorStatusEnum.缺卡.getValue());
                    errorEntity.setActualAttendanceDateTime(null);
                }
                errorEntity.setProcessResult(errorEntity.getErrorStatus().toString());
                errorEntityList.add(errorEntity);
            }
            //判断下班
            if (OffWorkResultEnum.请假.getValue() < offWorkResult) {
                AttendanceRecordErrorEntity errorEntity = new AttendanceRecordErrorEntity();
                errorEntity.initAttrValue();
                BeanUtils.copyProperties(attendanceRecordEntity, errorEntity, new String[]{"id"});
                errorEntity.setShiftsId(recordDetailEntity.getShiftsId());
                errorEntity.setShiftsName(recordDetailEntity.getShiftsName());
                errorEntity.setProcessStatus(YesNoEnum.NO.getValue());
                errorEntity.setCreateTime(new Date());
                errorEntity.setCreateUserId(1L);
                Date offWorkDate = attendanceClassDetailEntity.getOffWorkDate();
                errorEntity.setGoOffDateTime(DateUtil.parseDateTime(dateStr + " " + DateUtil.formatTime(offWorkDate)).toJdkDate());
                if (!ObjectUtils.isEmpty(recordDetailEntity.getOffWorkDate())) {
                    errorEntity.setErrorDateTime(recordDetailEntity.getOffWorkDate());
                    errorEntity.setActualAttendanceDateTime(recordDetailEntity.getOffWorkDate());
                } else {
                    errorEntity.setErrorDateTime(DateUtil.parseDateTime(dateStr + " " + DateUtil.formatTime(offWorkDate)).toJdkDate());
                }
                if (OffWorkResultEnum.缺卡.getValue() == recordDetailEntity.getOffWorkResult()) {
                    errorEntity.setErrorStatus(ErrorStatusEnum.缺卡.getValue());
                    errorEntity.setActualAttendanceDateTime(null);
                }
                if (OffWorkResultEnum.早退.getValue() == recordDetailEntity.getOffWorkResult()) {
                    errorEntity.setErrorStatus(ErrorStatusEnum.早退.getValue());
                }
                if (OffWorkResultEnum.迟到.getValue() == recordDetailEntity.getOffWorkResult()) {
                    errorEntity.setErrorStatus(ErrorStatusEnum.迟到.getValue());
                }
                errorEntity.setProcessResult(errorEntity.getErrorStatus().toString());
                errorEntityList.add(errorEntity);
            }
        }
        //删除当前员工当日未处理的异常后，重新添加 处理的 不做删除
        deleteErrorRecord(dateStr, attendanceRecordEntity.getStaffId(), context);
        //todo 级联删除优化 耗时50秒
        //deleteErrorRecordCache(attendanceRecordEntity.getStaffId(), context);
        if (!ObjectUtils.isEmpty(errorEntityList)) {
            //过滤异常列表中存在相同的记录
            errorEntityList = errorEntityList.stream().distinct().collect(Collectors.toList());
            for (AttendanceRecordErrorEntity errorEntity : errorEntityList) {
                //查看是否存在相同的异常记录，如果存在 则不添加  todo 非数据库查询方式判断优化
                // List<AttendanceRecordErrorEntity> attendanceRecordErrorEntities = commonData.getErrorGroupStaffMap().getOrDefault(attendanceRecordEntity.getStaffId(), new ArrayList<>(0));
                // checkAndSaveCache(context, attendanceRecordErrorEntities, errorEntity);
                checkAndSave(context, errorEntity);
            }
        }
    }

    private void deleteErrorRecord(String dateStr, Long staffId, Context context) {
        //删除当前员工当日未处理的异常后，重新添加
        AttendanceRecordErrorQuery errorQuery = new AttendanceRecordErrorQuery();
        errorQuery.setErrorDateTimeStart(dateStr);
        errorQuery.setErrorDateTimeEnd(dateStr);
        errorQuery.setStaffId(staffId);
        errorQuery.setProcessStatus(YesNoEnum.NO.getValue());
        List<AttendanceRecordErrorEntity> attendanceRecordErrorEntities = errorService.find(errorQuery);
        Long[] errorIds = attendanceRecordErrorEntities.stream().map(i -> i.getId()).toArray(Long[]::new);
        if (!ObjectUtils.isEmpty(errorIds)) {
            //log.info("删除 {} 人员:{} 异常记录:{}",dateStr,staffId, JSON.toJSONString(attendanceRecordErrorEntities));
            errorService.remove(errorIds, context);
        }
    }

    private void deleteErrorRecordCache(Long staffId, Context context) {
        //删除当前员工当日未处理的异常后，重新添加
        List<AttendanceRecordErrorEntity> attendanceRecordErrorEntities = commonData.getErrorGroupStaffMap().getOrDefault(staffId, new ArrayList<>(0));

        List<AttendanceRecordErrorEntity> delErrorList = attendanceRecordErrorEntities.stream()
                .filter(f -> YesNoEnum.NO.getValue() == f.getProcessStatus())
                .collect(Collectors.toList());
        Long[] errorIds = delErrorList.stream().map(i -> i.getId()).toArray(Long[]::new);
        if (!ObjectUtils.isEmpty(errorIds)) {
            //log.info("删除 {} 人员:{} 异常记录:{}",dateStr,staffId, JSON.toJSONString(attendanceRecordErrorEntities));
            // StopWatch stopWatch = new StopWatch();
            //  stopWatch.start("删除异常记录耗时");
            //todo 耗时长，删除优化
            errorService.getDao().delete(errorIds);
/*
            //线程池去删除异常记录
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    errorService.remove(errorIds, context);
                }
            };
            ThreadPool.getInstance().execute(runnable);*/

            PerformAttendRecordQuery query = new PerformAttendRecordQuery();
            query.setStaffId(staffId);
            query.setErrorTimeStart(DateUtil.formatDate(delErrorList.get(0).getErrorDateTime()));
            query.setErrorTimeEnd(DateUtil.formatDate(delErrorList.get(0).getErrorDateTime()));
            query.setRuleIdNotList(Arrays.asList(9L));
            List<PerformAttendRecordEntity> attendRecords = performAttendRecordService.find(query, context);

            List<PerformAttendRecordEntity> delAttendRecords = attendRecords.stream().map(item -> {
                Date errorTime = item.getErrorTime();
                for (AttendanceRecordErrorEntity attendRecord : delErrorList) {
                    if (errorTime.getTime() == attendRecord.getErrorDateTime().getTime()) {
                        return item;
                    }
                }
                return null;
            }).filter(f -> f != null).collect(Collectors.toList());

            if (!ObjectUtils.isEmpty(delAttendRecords)) {
                Long[] delIds = delAttendRecords.stream().map(i -> i.getId()).toArray(Long[]::new);
                performAttendRecordService.getDao().delete(delIds);

                CheckAttendRecordQuery checkAttendRecordQuery = new CheckAttendRecordQuery();
                checkAttendRecordQuery.setRecordIdList(Arrays.asList(delIds));
                List<CheckAttendRecordEntity> checkAttendRecordEntities = checkAttendRecordService.find(checkAttendRecordQuery, context);
                if (!ObjectUtils.isEmpty(checkAttendRecordEntities)) {
                    Long[] checkIds = checkAttendRecordEntities.stream().map(i -> i.getId()).toArray(Long[]::new);
                    checkAttendRecordService.getDao().delete(checkIds);
                    //  checkAttendRecordService.remove(checkIds, context);
                    //  log.info("删除考勤核查记录成功,size:{}",checkIds.length);

                    PerformErrorMessageQuery performErrorMessageQuery = new PerformErrorMessageQuery();
                    performErrorMessageQuery.setPerformType(PerformTypeEnum.考勤绩效.getValue());
                    performErrorMessageQuery.setCheckRecordIdList(Arrays.asList(checkIds));
                    List<PerformErrorMessageEntity> errorList = performErrorMessageService.find(performErrorMessageQuery);
                    if (CollectionUtils.isNotEmpty(errorList)) {
                        Long[] deleteIds = errorList.stream().map(i -> i.getId()).toArray(Long[]::new);
                        performErrorMessageService.remove(deleteIds, context);
                    }
                }
            }
            // stopWatch.stop();
            //   log.info("删除异常记录耗时：{}ms", stopWatch.getLastTaskTimeMillis());
        }

    }

    private void checkAndSaveCache(Context context, List<AttendanceRecordErrorEntity> attendanceRecordErrorEntities, AttendanceRecordErrorEntity errorEntity) {
        AttendanceRecordErrorEntity attendanceRecordErrorEntity = attendanceRecordErrorEntities.stream()
                .filter(f -> errorEntity.getErrorDateTime().getTime() == f.getErrorDateTime().getTime())
                .filter(f -> errorEntity.getShiftsId().equals(f.getShiftsId()))
                .filter(f -> YesNoEnum.YES.getValue() == f.getProcessStatus()).findAny().orElseGet(() -> null);
        if (ObjectUtils.isEmpty(attendanceRecordErrorEntity)) {
            errorService.save(errorEntity, context);
        }
    }

    private void checkAndSave(Context context, AttendanceRecordErrorEntity errorEntity) {
        AttendanceRecordErrorQuery errorQuery;
        errorQuery = new AttendanceRecordErrorQuery();
        errorQuery.setErrorDateTime(errorEntity.getErrorDateTime());
        errorQuery.setStaffId(errorEntity.getStaffId());
        errorQuery.setShiftsId(errorEntity.getShiftsId());
        errorQuery.setProcessStatus(YesNoEnum.YES.getValue());
        AttendanceRecordErrorEntity attendanceRecordErrorEntity = errorService.selectOne(errorQuery, context);
        if (ObjectUtils.isEmpty(attendanceRecordErrorEntity)) {
            errorService.save(errorEntity, context);
        }
    }


    public static void main(String[] args) {
    /*    String date = "2021-05-01 09:00:00";
        String endDate = "2021-05-02 18:00:00";
        long between = DateUtil.between(DateUtil.parseDate(date), DateUtil.parseDate(endDate), DateUnit.DAY);
        System.out.println(between);
        String curDateStr = "2024-01-05";
        DateTime dateTime = DateUtil.parseDate(curDateStr);
        DateTime start = DateUtil.parseDate("2024-01-05 18:45:15");
        DateTime end = DateUtil.parseDate("2024-01-05 08:45:15");
        boolean in = DateUtil.isIn(dateTime, start, end);
        System.out.println(in);*/
        System.out.println(GoWorkResultEnum.getEnumMap().keySet());


    }
}
