package com.yida.data.attendance.service.impl;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.attendance.dto.DealRecordDTO;
import com.yida.data.attendance.dto.InOutPageDTO;
import com.yida.data.attendance.dto.ListRecordDTO;
import com.yida.data.attendance.mapper.EduAttendanceDeviceMapper;
import com.yida.data.attendance.mapper.EduAttendanceRecordMapper;
import com.yida.data.attendance.mapper.EduAttendanceStaffRecordMapper;
import com.yida.data.attendance.service.*;
import com.yida.data.attendance.vo.*;
import com.yida.data.common.core.entity.attendance.*;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.school.EduDormitoryRoom;
import com.yida.data.common.core.entity.user.EduStaff;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.enums.AttendanceResult;
import com.yida.data.common.core.utils.ExcelUtil;
import com.yida.data.common.service.CommonService;
import com.yida.data.school.dto.index.ListDormRoomDTO;
import com.yida.data.school.feign.facility.RemoteDormitoryService;
import com.yida.data.user.dto.ListStudentDTO;
import com.yida.data.user.feign.RemoteStaffService;
import com.yida.data.user.feign.RemoteStudentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class EduAttendanceRecordServiceImpl extends
    ServiceImpl<EduAttendanceRecordMapper, EduAttendanceRecord> implements EduAttendanceRecordService {

    // 修改学生在校，离校，在寝，离寝状态线程池
    private static final ExecutorService UPDATE_STUDENT_POOL = new ThreadPoolExecutor(5, 10, 1,
        TimeUnit.MINUTES, new LinkedBlockingQueue<>());
    private final EduAttendanceRuleService eduAttendanceRuleService;
    private final EduAttendanceConfigService eduAttendanceConfigService;
    private final NoticeService noticeService;
    private final EduAttendanceDeviceMapper eduAttendanceDeviceMapper;

    private final EduAttendanceResultService eduAttendanceResultService;
    private final EduAttendanceStaffRecordMapper eduAttendanceStaffRecordMapper;
    private final RemoteStudentService remoteStudentService;
    private final RemoteStaffService remoteStaffService;
    private final RemoteDormitoryService remoteDormitoryService;
    private final RedisService redisService;
    private final EduAttendanceStaffRuleService eduAttendanceStaffRuleService;
    private final EduAttendanceStaffResultService eduAttendanceStaffResultService;

    private final CommonService commonService;

    @Override
    public IPage<InOutDormPageVO> listInOutPage(InOutPageDTO dto) {
        // 获取学生
        List<Long> studentIds = null;
        ListStudentDTO listStudentDTO = ListStudentDTO.builder().isQueryParent(false).isQuerySchoolName(false).build();
        BeanUtils.copyProperties(dto, listStudentDTO);
        listStudentDTO.setType(null);
        if (dto.getDormId() != null) {
            List<EduDormitoryRoom> data =
                remoteDormitoryService
                    .listDormRoom(ListDormRoomDTO.builder().dormIds(Collections.singletonList(dto.getDormId())).build())
                    .getData();
            if (CollUtil.isNotEmpty(data)) {
                listStudentDTO.setDormRoomIds(data.stream().map(EduDormitoryRoom::getId).collect(Collectors.toList()));
            }
        }
        // 查询匹配的学生
        List<EduStudent> studentList = remoteStudentService.listStudent(listStudentDTO).getData();
        if (CollUtil.isNotEmpty(studentList)) {
            if (StrUtil.isNotBlank(dto.getKeyword())) {
                studentList = studentList.stream()
                    .filter(x -> StrUtil.concat(true, x.getStuName(), x.getStuNumber()).contains(dto.getKeyword()))
                    .collect(Collectors.toList());
            }
            if (CollUtil.isNotEmpty(studentList)) {
                studentIds = studentList.stream().map(EduStudent::getId).collect(Collectors.toList());
            }
        }
        Page<InOutDormPageVO> recordPage = Page.of(dto.getPageNum(), dto.getPageSize());
        recordPage.setRecords(baseMapper.listInOut(recordPage, studentIds, dto.getType(), dto.getStartTime(), dto.getEndTime()));
        if (CollUtil.isNotEmpty(recordPage.getRecords()) && CollUtil.isNotEmpty(studentList)) {
            List<InOutDormPageVO> records = recordPage.getRecords();
            List<Long> studentId = records.stream().map(InOutPageVO::getStudentId).collect(Collectors.toList());
            Map<Long, List<EduStudent>> studengIdGroup = studentList.stream().filter(x -> studentId.contains(x.getId()))
                .collect(Collectors.groupingBy(EduStudent::getId));

            for (InOutPageVO record : records) {
                EduStudent eduStudent = studengIdGroup.get(record.getStudentId()).get(0);
                record.setCampusName(eduStudent.getCampusName());
                record.setStuName(eduStudent.getStuName());
                record.setStuNumber(eduStudent.getStuNumber());
            }
        }
        return recordPage;
    }

    @Override
    public void exportInOut(InOutPageDTO dto, HttpServletResponse response) {
        // 获取学生
        List<Long> studentIds = null;
        ListStudentDTO listStudentDTO = ListStudentDTO.builder().isQueryParent(false).isQuerySchoolName(false).build();
        BeanUtils.copyProperties(dto, listStudentDTO);
        listStudentDTO.setType(null);
        if (dto.getDormId() != null) {
            List<EduDormitoryRoom> data = remoteDormitoryService
                .listDormRoom(ListDormRoomDTO.builder().dormIds(Collections.singletonList(dto.getDormId())).build()).getData();
            if (CollUtil.isNotEmpty(data)) {
                listStudentDTO.setDormRoomIds(data.stream().map(EduDormitoryRoom::getId).collect(Collectors.toList()));
            }
        }
        // 查询匹配的学生
        List<EduStudent> studentList = remoteStudentService.listStudent(listStudentDTO).getData();
        if (CollUtil.isNotEmpty(studentList)) {
            if (StrUtil.isNotBlank(dto.getKeyword())) {
                studentList = studentList.stream()
                    .filter(
                        x -> x.getStuName().contains(dto.getKeyword()) || x.getStuNumber().contains(dto.getKeyword()))
                    .collect(Collectors.toList());
            }
            if (CollUtil.isNotEmpty(studentList)) {
                studentIds = studentList.stream().map(EduStudent::getId).collect(Collectors.toList());
            }
        }
        List<InOutDormPageVO> recordList = baseMapper.listInOut(null, studentIds, dto.getType(), dto.getStartTime(),
            dto.getEndTime());
        if (CollUtil.isNotEmpty(studentList)) {
            for (InOutPageVO record : recordList) {
                for (EduStudent student : studentList) {
                    if (record.getStudentId().equals(student.getId())) {
                        record.setCampusName(student.getCampusName());
                        record.setStuName(student.getStuName());
                        record.setStuNumber(student.getStuNumber());
                        break;
                    }
                }
            }
        }
        if (dto.getType() == 0) {
            ExcelUtil.export("校门进出记录表.xlsx", InOutPageVO.class, recordList.stream().map(x -> {
                InOutPageVO vo = new InOutPageVO();
                BeanUtils.copyProperties(x, vo);
                return vo;
            }).collect(Collectors.toList()), response);
        } else {
            ExcelUtil.export("宿舍进出记录表.xlsx", InOutDormPageVO.class, recordList, response);
        }
    }

    @Override
    public RecordDetailVO getRecordDetail(Long id) {
        return baseMapper.getRecordDetail(id);
    }

    @Override
    public void receiveRecord(DealRecordDTO dto) {
        String createTimeStr = dto.getDate();
        // 从缓存中获取上一条考勤记录时间
        Object lastRecordTime = redisService.hget(CachePrefixConstant.ATTENDANCE_RECORD_LAST, dto.getUserFlag());
        if (createTimeStr.equals(lastRecordTime)) {
            return;
        }
        redisService.hset(CachePrefixConstant.ATTENDANCE_RECORD_LAST, dto.getUserFlag(), createTimeStr);

        // 查设备
        EduAttendanceDevice device = (EduAttendanceDevice) redisService
            .hget(CachePrefixConstant.DEVICE_DATA, dto.getSn());
        if (device == null) {
            device = eduAttendanceDeviceMapper.selectOne(Wrappers.<EduAttendanceDevice>lambdaQuery()
                .eq(EduAttendanceDevice::getSn, dto.getSn()));
            if (device == null) {
                return;
            }
            redisService.hset(CachePrefixConstant.DEVICE_DATA, dto.getSn(), device);
        }
        AttendanceResVO attendanceResVO = dealAttendance(dto, device);
        if (dto.getUserType() == 0 && attendanceResVO != null) {
            try {
                noticeService.sendAttendanceNotice(attendanceResVO);
            } catch (Exception e) {
                log.error("考勤消息推送失败", e);
            }
        }
    }

    @Override
    public List<RecordDetailVO> listRecord(ListRecordDTO dto) {
        return baseMapper.listRecord(dto);
    }

    private AttendanceResVO dealAttendance(DealRecordDTO dto, EduAttendanceDevice device) {
        AttendanceResVO vo = new AttendanceResVO();
        // 学生考勤
        if (dto.getUserType() == 0) {
            EduAttendanceRecord record = new EduAttendanceRecord();
            //考勤记录基本信息
            record.setPicUrl(dto.getPicUrl());
            record.setStudentId(dto.getUserId());
            record.setDeviceId(device.getId());
            record.setDeviceName(device.getName());
            record.setScope(device.getZoneScope());
            record.setZone(device.getType());
            record.setCreateDate(LocalDateTime.now());
            record.setCreateTime(LocalDateTimeUtil.parse(dto.getDate(), "yyyy-MM-dd HH:mm:ss"));
            // 查询学生
            EduStudent student = (EduStudent) redisService
                .hget(CachePrefixConstant.STUDENT_DATA, dto.getUserId().toString());

            if (student == null) {
                student = remoteStudentService.getStudentNoPermission(dto.getUserId()).getData();
                if (student == null) {
                    log.error("学生不存在,无法处理考勤数据,id:[{}]", dto.getUserId().toString());
                    return null;
                } else {
                    redisService.hset(CachePrefixConstant.STUDENT_DATA, dto.getUserId().toString(), student);
                }
            }
            // 处理学生在校离校，在寝离寝状态，处于门禁  与考勤无关
            EduStudent finalStudent = student;
            UPDATE_STUDENT_POOL.execute(() -> {
                //0-校门，1-宿舍
                if (device.getType() == 0) {
                    //更新在校离校
                    if (!device.getZoneScope().equals(finalStudent.getStatus())) {
                        remoteStudentService.updateStudentStatus(finalStudent.getId(), device.getZoneScope(), null);
                    }
                } else {
                    //更新宿舍-在寝离寝状态
                    if (finalStudent.getType() == 1 && !device.getZoneScope().equals(finalStudent.getDormStatus())) {
                        remoteStudentService.updateStudentStatus(finalStudent.getId(), 0, device.getZoneScope());
                    }
                }
//                if (device.getType() == 0 && !device.getZoneScope().equals(finalStudent.getStatus())) {
//                    remoteStudentService.updateStudentStatus(finalStudent.getId(), device.getZoneScope(), null);
//                } else if (finalStudent.getType() == 1 && device.getType() == 1
//                    && !device.getZoneScope().equals(finalStudent.getDormStatus())) {
//                    remoteStudentService.updateStudentStatus(finalStudent.getId(), 0, device.getZoneScope());
//                }
            });
            // 学生相关信息
            record.setSchoolId(student.getSchoolId());
            record.setCampusId(student.getCampusId());
            record.setGradeId(student.getGradeId());
            record.setGradeName(student.getGradeName());
            record.setClassId(student.getClassId());
            record.setClassName(student.getClassName());
            vo.setStudent(student);
            // 该条考勤记录适用的规则
            RuleListVO validRule = eduAttendanceRuleService.getValidRule(
                Arrays.asList(
                    student.getClassId(), student.getGradeId(), student.getSectionId(), student.getCampusId(),
                    -student.getSchoolId()),
                record.getCreateTime(),
                null,
                device.getSn());

            // 学校的考勤设置
            EduAttendanceConfig config =
                (EduAttendanceConfig) redisService.hget(CachePrefixConstant.ATTENDANCE_CONFIG,
                    student.getSchoolId().toString());

            if (config == null) {
                config = eduAttendanceConfigService.getConfig(student.getSchoolId());
                redisService.hset(CachePrefixConstant.ATTENDANCE_CONFIG, student.getSchoolId().toString(), config);
            }

            LocalTime operateTime = record.getCreateTime().toLocalTime();
            //根据规则判断上学考勤还是宿舍考勤
            if (validRule != null) {
                for (int i = 0; i < validRule.getTimeList().size(); i++) {
                    EduAttendanceRuleTime ruleTime = validRule.getTimeList().get(i);
                    if (validRule.getType() == 0) {
                        //上学考勤
                        //
                        if (operateTime.isBefore(ruleTime.getTime1())) {
                            if (ruleTime.getTime1Openset() == 1) {
                                if (operateTime.isAfter(ruleTime.getTime1Start()) && operateTime
                                    .isBefore(ruleTime.getTime1End())) {
                                    // 在有效打卡时间段之内
                                    record.setStatus(0);
                                    record.setStiTime(ruleTime.getTime1());
                                } else {
                                    record.setStatus(10);
                                    record.setStiTime(ruleTime.getTime1());
                                }
                            } else {
                                // 在时间一之前正常
                                record.setStatus(0);
                                record.setStiTime(ruleTime.getTime1());
                            }
                        } else if (operateTime.isAfter(ruleTime.getTime1()) && operateTime
                            .isBefore(ruleTime.getTime2())) {
                            //是否前面有签到记录，如果前面无打卡记录则为迟到，如果有打卡记录则为早退
                            if (fingStudentRecord(student.getId(), validRule.getId(), ruleTime.getId())) {
                                //含有打卡记录为早退
                                record.setStatus(2);
                                record.setStiTime(ruleTime.getTime2());
                            } else {
                                //不含有打卡记录为迟到
                                record.setStatus(1);
                                record.setStiTime(ruleTime.getTime1());
                            }
                        } else if (operateTime.isAfter(ruleTime.getTime2())) {
                            if (fingStudentRecord(student.getId(), validRule.getId(), ruleTime.getId())) {
                                //前面含有打卡记录，如果无打卡记录，则表示下一时间段的开始时间打卡，此次不记录
                                //在时间段2之后  与  下一时间段time1之前为 正常，
                                EduAttendanceRuleTime nextRuleTime = validRule.getTimeList().get(i + 1);
                                if (ObjectUtil.isNotNull(nextRuleTime)) {
                                    //含有下一时间段
                                    if (operateTime.isBefore(nextRuleTime.getTime1())) {
                                        if (ruleTime.getTime2Openset() == 1) {
                                            if (operateTime.isAfter(ruleTime.getTime2Start()) && operateTime
                                                .isBefore(ruleTime.getTime2End())) {
                                                //下一时间段之前，下课考勤正常
                                                record.setStatus(0);
                                                record.setStiTime(ruleTime.getTime2());
                                            } else {
                                                //下一时间段之前，下课考勤正常
                                                record.setStatus(20);
                                                record.setStiTime(ruleTime.getTime2());
                                            }
                                        } else {
                                            //下一时间段之前，下课考勤正常
                                            record.setStatus(0);
                                            record.setStiTime(ruleTime.getTime2());
                                        }
                                    }
                                } else {
                                    if (ruleTime.getTime2Openset() == 1) {
                                        if (operateTime.isAfter(ruleTime.getTime2Start()) && operateTime
                                            .isBefore(ruleTime.getTime2End())) {
                                            //下学有效打卡时间段内
                                            record.setStatus(0);
                                            record.setStiTime(ruleTime.getTime2());
                                        } else {
                                            //未在下学有效打卡时间段内
                                            record.setStatus(20);
                                            record.setStiTime(ruleTime.getTime2());
                                        }
                                    } else {
                                        //不含有下一时间段，
                                        record.setStatus(0);
                                        record.setStiTime(ruleTime.getTime2());
                                    }
                                }
                            }
                        }
                    } else {
                        //宿舍考勤
                        if (operateTime.isBefore(ruleTime.getTime2()) && operateTime.isAfter(ruleTime.getTime1())) {
                            // 在时间二之前、时间一之后正常
                            record.setStatus(0);
                            record.setStiTime(ruleTime.getTime1());
                        } else if (operateTime.isAfter(ruleTime.getTime2()) && operateTime
                            .isBefore(ruleTime.getTime3())) {
                            // 在时间二与时间三之间晚归
                            record.setStatus(4);
                            record.setStiTime(ruleTime.getTime2());
                        } else if (operateTime.isAfter(ruleTime.getTime3())) {
                            //大于晚归时间
                            if (i < validRule.getTimeList().size() - 1) {
                                EduAttendanceRuleTime nextRuleTime = validRule.getTimeList().get(i + 1);
                                if (ObjectUtil.isNotNull(nextRuleTime)) {
                                    if (operateTime.isBefore(nextRuleTime.getTime1())) {
                                        record.setStatus(5);
                                    }
                                } else {
                                    record.setStatus(5);
                                }
                            } else {
                                record.setStatus(5);
                            }
                        }
                    }
                    if (record.getStatus() != null) {
                        // 拿到考勤结果  不再匹配
                        record.setRuleId(validRule.getId());
                        record.setRuleTimeId(ruleTime.getId());
                        break;
                    }
                }
            }
            // 住宿生的宿舍情况
            if (student.getType() == 1 && device.getType() == 1) {
                record.setDormId(student.getDormId());
                record.setDormRoomId(student.getDormRoomId());
                if (student.getDormRoomId() != null) {
                    // 录缓存
                    EduDormitoryRoom dormRoom = (EduDormitoryRoom) redisService
                        .hget(CachePrefixConstant.FACILITY_DORM_ROOM, student.getDormRoomId().toString());
                    if (dormRoom == null) {
                        dormRoom = remoteDormitoryService.getDormRoomNoPermission(student.getDormRoomId()).getData();
                        if (dormRoom != null) {
                            redisService
                                .hset(CachePrefixConstant.FACILITY_DORM_ROOM, student.getDormRoomId().toString(), dormRoom);
                        }
                    }
                    if (dormRoom != null) {
                        record.setDormName(dormRoom.getDormName());
                        record.setDormRoomName(dormRoom.getName());
                    }
                }
            }
            // 判断该次考勤状态
//            if (validRule != null) {
//                for (EduAttendanceRuleTime ruleTime : validRule.getTimeList()) {
//                    // 遍历每一个时间
//                    if (device.getType() == 0) {
//                        // 校门
//                        if (device.getZoneScope() == 0) {
//                            // 进门
//                            if (operateTime.isBefore(ruleTime.getTime1())) {
//                                // 在时间一之前正常
//                                record.setStatus(0);
//                                record.setStiTime(ruleTime.getTime1());
//                            } else if (operateTime.isAfter(ruleTime.getTime1()) && operateTime
//                                    .isBefore(ruleTime.getTime2())) {
//                                // 在时间二与时间一之间为迟到
//                                record.setStatus(1);
//                                record.setStiTime(ruleTime.getTime1());
//                            }
//                        } else if (device.getZoneScope() == 1) {
//                            // 出门
//                            if (operateTime.isBefore(ruleTime.getTime1())) {
//                                // 在时间一之前正常
//                                record.setStatus(0);
//                                record.setStiTime(ruleTime.getTime2());
//                            } else if (operateTime.isAfter(ruleTime.getTime1()) && operateTime
//                                    .isBefore(ruleTime.getTime2())) {
//                                // 在时间二与时间一之间为早退
//                                record.setStatus(2);
//                                record.setStiTime(ruleTime.getTime2());
//                            }
//                        }
//                    } else if (device.getType() == 1) {
//                        // 宿舍
//                        if (device.getZoneScope() == 0) {
//                            // 进门
//                            if (operateTime.isBefore(ruleTime.getTime2()) && operateTime.isAfter(ruleTime.getTime1())) {
//                                // 在时间二之前、时间一之后正常
//                                record.setStatus(0);
//                            } else if (operateTime.isAfter(ruleTime.getTime2()) && operateTime
//                                    .isBefore(ruleTime.getTime3())) {
//                                // 在时间二与时间三之间晚归
//                                record.setStatus(4);
//                            } else if (operateTime.isAfter(ruleTime.getTime3()) && ruleTime.getType() == 1
//                                    && operateTime.isBefore(config.getDormitoryNoonDdl())) {
//                                // 中午的截止考勤时间之后  旷宿时间之前
//                                record.setStatus(5);
//                            } else if (ruleTime.getType() == 2 && (operateTime.isAfter(ruleTime.getTime3())
//                                    || (operateTime.isBefore(config.getDormitoryNightDdl())))) {
//                                // 晚上的截止考勤时间之后或者凌晨的旷宿时间之前
//                                record.setStatus(5);
//                            }
//                        }
//                    }
//                    if (record.getStatus() != null) {
//                        // 拿到考勤结果  不再匹配
//                        record.setRuleId(validRule.getId());
//                        record.setRuleTimeId(ruleTime.getId());
//                        break;
//                    }
//                }
//            }
            // 保存考勤结果
            save(record);
            vo.setRecord(record);
            //生成考勤结果  TODO
            //去查询当前规则下学员的考勤记录，进行综合判断
            
//            if(ObjectUtil.equal("1",config.getState())){
//                //启用考勤
//            }
//            saveAttendanceResult(record);

        } else {
            EduAttendanceStaffRecord staffRecord = new EduAttendanceStaffRecord();
            // 查询教职工
            EduStaff staff = (EduStaff) redisService.hget(CachePrefixConstant.STAFF_DATA, dto.getUserId().toString());
            if (staff == null) {
                staff = remoteStaffService.getStaff(dto.getUserId()).getData();
                redisService.hset(CachePrefixConstant.STAFF_DATA, dto.getUserId().toString(), staff);
            }
            staffRecord.setStaffId(staff.getId());
            staffRecord.setDeviceId(device.getId());
            staffRecord.setSchoolId(staff.getSchoolId());
            staffRecord.setCreateTime(DateUtil.parseLocalDateTime(dto.getDate(), "yyyy-MM-dd HH:mm:ss"));
            staffRecord.setScope(device.getZoneScope());
            staffRecord.setPicUrl(dto.getPicUrl());
            eduAttendanceStaffRecordMapper.insert(staffRecord);

            // 处理职工考勤结果
            dealStaffAttendanceResult(staffRecord);

            vo.setStaff(staff);
        }
        return vo;
    }

    public void saveAttendanceResult(EduAttendanceRecord record) {
        if (ObjectUtil.isNull(record)) {
            return;
        }
        if (ObjectUtil.isNull(record.getStatus())) {
            return;
        }
        //迟到，早退、上学未在打卡时间段、下学未在打卡时间段、晚归 、异常晚归 直接记录考勤结果，其他结果需要统计
        //-1-宿管添加的考勤记录，0-正常，1-迟到，10-上学未在打卡时间段,2-早退，20-下学未在打卡时间段，3-未到,4-晚归，5-异常晚归，6-旷宿
        //查询当天此考勤结果是否已录入
        List<EduAttendanceResult> list = eduAttendanceResultService.list(Wrappers.lambdaQuery(new EduAttendanceResult())
            .eq(EduAttendanceResult::getRuleTimeId, record.getRuleTimeId())
            .eq(EduAttendanceResult::getStudentId, record.getStudentId())
            .eq(EduAttendanceResult::getStatus, record.getStatus())
            .eq(EduAttendanceResult::getAttendanceDate, record.getCreateDate().toLocalDate()));

        EduAttendanceResult eduAttendanceResult = new EduAttendanceResult();
        eduAttendanceResult.setStudentId(record.getStudentId());
        eduAttendanceResult.setSchoolId(record.getSchoolId());
        eduAttendanceResult.setCampusId(record.getCampusId());
        eduAttendanceResult.setGradeId(record.getGradeId());
        eduAttendanceResult.setGradeName(record.getGradeName());
        eduAttendanceResult.setClassId(record.getClassId());
        eduAttendanceResult.setClassName(record.getClassName());
        eduAttendanceResult.setCreateDate(LocalDateTime.now());
        eduAttendanceResult.setAttendanceDate(LocalDate.now());
        eduAttendanceResult.setRuleId(record.getRuleId());
        eduAttendanceResult.setRuleTimeId(record.getRuleTimeId());
        eduAttendanceResult.setRecordId(record.getId());

        //查找出当前时间段内学生已记录的考勤记录
//        EduAttendanceResult alreadyResult = eduAttendanceResultService.getOne(Wrappers.lambdaQuery(new EduAttendanceResult())
//            .eq(EduAttendanceResult::getAttendanceDate, LocalDate.now())
//            .eq(EduAttendanceResult::getStudentId, record.getStudentId())
//            .eq(EduAttendanceResult::getRuleId, record.getRuleId())
//            .eq(EduAttendanceResult::getRuleTimeId, record.getRuleTimeId()));
//
//        if (ObjectUtil.isNull(alreadyResult)) {
//            eduAttendanceResult.setStudentId(record.getStudentId());
//            eduAttendanceResult.setSchoolId(record.getSchoolId());
//            eduAttendanceResult.setCampusId(record.getCampusId());
//            eduAttendanceResult.setGradeId(record.getGradeId());
//            eduAttendanceResult.setGradeName(record.getGradeName());
//            eduAttendanceResult.setClassId(record.getClassId());
//            eduAttendanceResult.setClassName(record.getClassName());
//            eduAttendanceResult.setCreateDate(LocalDateTime.now());
//            eduAttendanceResult.setAttendanceDate(LocalDate.now());
//            eduAttendanceResult.setRuleId(record.getRuleId());
//            eduAttendanceResult.setRuleTimeId(record.getRuleTimeId());
//            eduAttendanceResult.setRecordId(record.getId());
//        } else {
//            eduAttendanceResult.setId(alreadyResult.getId());
//        }

        //，100-正常，201-迟到，202-早退，203-迟到早退，204-旷课,205-请假,211-晚归，212-异常晚归，213-旷宿，214-已被核查但学生还未归寝
        // -1-宿管添加的考勤记录，0-正常，1-迟到，10-上学未在打卡时间段,2-早退，20-下学未在打卡时间段，3-未到,4-晚归，5-异常晚归，6-旷宿
        if (record.getStatus() == 0 || record.getStatus() == 1 || record.getStatus() == 10 || record.getStatus() == 2
            || record.getStatus() == 20
            || record.getStatus() == 4 || record.getStatus() == 5) {
            if (CollUtil.isEmpty(list)) {
                eduAttendanceResult.setStatus(
                    record.getStatus() == 0 ? AttendanceResult.NORMAL.getValue()
                        : record.getStatus() == 1 ? AttendanceResult.STU_LATE
                            .getValue() : record.getStatus() == 10 ? AttendanceResult.STU_START_NOT_IN.getValue()
                            : record.getStatus() == 2 ? AttendanceResult.STU_LEAVE
                                .getValue() : record.getStatus() == 20 ? AttendanceResult.STU_END_NOT_IN.getValue()
                                : record.getStatus() == 4 ? AttendanceResult.STU_D_LATE.getValue()
                                    : AttendanceResult.STU_D_EX_LATE.getValue());

                if (record.getZone() == 1) {
                    //宿舍考勤
                    eduAttendanceResult.setDormId(record.getDormId());
                    eduAttendanceResult.setDormName(record.getDormName());
                    eduAttendanceResult.setDormRoomId(record.getDormRoomId());
                    eduAttendanceResult.setDormRoomName(record.getDormRoomName());
                }
                eduAttendanceResultService.save(eduAttendanceResult);
            }
        }
    }


    public boolean fingStudentRecord(Long studentId, Long ruleId, Long ruleTimeId) {
        List<EduAttendanceRecord> eduAttendanceRecords = baseMapper.selectList(Wrappers.lambdaQuery(new EduAttendanceRecord())
            .eq(EduAttendanceRecord::getStudentId, studentId)
            .eq(EduAttendanceRecord::getRuleId, ruleId)
            .eq(EduAttendanceRecord::getRuleTimeId, ruleTimeId));
        if (ObjectUtil.isNotEmpty(eduAttendanceRecords)) {
            return true;
        }
        return false;
    }

    /**
     * 处理教职工考勤结果
     *
     * @param staffRecord 教职工考勤-进出记录
     * @author ZYJ
     * @date 2022/9/13 16:06
     */
    public void dealStaffAttendanceResult(EduAttendanceStaffRecord staffRecord) {
        // 查询教职工适用的考勤规则
        FindStaffRuleVO staffRuleVO = eduAttendanceStaffRuleService.selectMatchStaffRule(staffRecord);
//        log.info("教师适用考勤规则:{}", staffRuleVO);
        // 没有匹配的规则就不生成考勤结果
        if (Objects.nonNull(staffRuleVO)) {
            boolean isSpecialDate = false;
            // 判断是否为特殊日期
            LocalDate nowDate = LocalDate.now();
            if (CollUtil.isNotEmpty(staffRuleVO.getSpecialDate())) {
                for (EduAttendanceStaffRuleSpecialDate specialDate : staffRuleVO.getSpecialDate()) {
                    if (nowDate.isEqual(specialDate.getDate())) {
                        isSpecialDate = true;
                        break;
                    }
                }
            }
            if (isSpecialDate) {
                return;
            }
            // 判断是否为节假日
            Boolean workDay = commonService.isWorkDay(nowDate);
            if (!workDay) {
                return;
            }
            Long ruleId = staffRuleVO.getId();
            // 考勤-打卡时间段
            List<EduAttendanceStaffRuleTime> staffRuleTimes = staffRuleVO.getRuleTimes();
            // 循环打卡时间段
            for (int i = 0; i < staffRuleTimes.size(); i++) {

                EduAttendanceStaffRuleTime eduAttendanceStaffRuleTime = staffRuleTimes.get(i);
                // 考勤开始时间
                LocalTime startTime = eduAttendanceStaffRuleTime.getStartTime();
                // 考勤结束时间
                LocalTime endTime = eduAttendanceStaffRuleTime.getEndTime();
                Long ruleTimeId = eduAttendanceStaffRuleTime.getId();

                // 判断是否包含白名单. 白名单内不需要考勤
                boolean whiteFlag = false;
                if (CollUtil.isNotEmpty(staffRuleVO.getWhiteList())) {
                    List<Long> list = staffRuleVO.getWhiteList().stream()
                        .map(EduAttendanceStaffRuleWhiteList::getStaffId).collect(Collectors.toList());
                    whiteFlag = list.contains(staffRecord.getStaffId());
                }

                // 进出日期
                LocalDate date = staffRecord.getCreateTime().toLocalDate();
                // 进出时间
                LocalTime time = staffRecord.getCreateTime().toLocalTime();

                // 判断当天是否有生成对应时段的考勤结果
                EduAttendanceStaffResult staffResult = eduAttendanceStaffResultService.getOne(
                    Wrappers.lambdaQuery(new EduAttendanceStaffResult())
                        .eq(EduAttendanceStaffResult::getStaffId, staffRecord.getStaffId())
                        .eq(EduAttendanceStaffResult::getRuleId, ruleId)
                        .eq(EduAttendanceStaffResult::getRuleTimeId, ruleTimeId)
                        .eq(EduAttendanceStaffResult::getAttendanceDate, date)
                );

                // 当天没有考勤结果
                if (Objects.isNull(staffResult)) {
                    // 设置考勤结果基础数据
                    staffResult = new EduAttendanceStaffResult();
                    staffResult.setStaffId(staffRecord.getStaffId());
                    staffResult.setSchoolId(staffRecord.getSchoolId());
                    staffResult.setRuleId(ruleId);
                    staffResult.setRuleTimeId(ruleTimeId);
                    staffResult.setAttendanceDate(date);
                    staffResult.setStartStiTime(eduAttendanceStaffRuleTime.getStartEffectiveStatus() == 0 ?
                        startTime : eduAttendanceStaffRuleTime.getStartEffectiveStartTime());
                    staffResult.setEndStiTime(eduAttendanceStaffRuleTime.getEndEffectiveStatus() == 0 ?
                        endTime : eduAttendanceStaffRuleTime.getEndEffectiveStartTime());
                }
                // 状态 0-正常，1-迟到，2-早退,3-旷工，4-迟到早退，5-上班未在打卡时间段，6-下班未在打卡时间段
                if (time.isBefore(eduAttendanceStaffRuleTime.getStartTime())) {
                    // 启用上班打卡时段
                    if (eduAttendanceStaffRuleTime.getStartEffectiveStatus() == 1) {
                        if (time.isAfter(eduAttendanceStaffRuleTime.getStartEffectiveStartTime()) && time
                            .isBefore(eduAttendanceStaffRuleTime.getStartEffectiveEndTime())) {
                            // 在有效打卡时间段之内
                            staffResult.setStatus(0);
                            staffResult.setStartRealTime(time);
                        } else {
                            staffResult.setStatus(whiteFlag ? 0 : 5);
                            staffResult.setStartRealTime(time);
                        }
                    } else {
                        // 未启用上班打卡时段
                        // 在时间一之前正常
                        staffResult.setStatus(0);
                        staffResult.setStartRealTime(time);
                    }
                    staffRecord.setRuleId(ruleId);
                    staffRecord.setRuleTimeId(ruleTimeId);
                } else if (time.isAfter(eduAttendanceStaffRuleTime.getStartTime()) && time
                    .isBefore(eduAttendanceStaffRuleTime.getEndTime())) {
                    // 是否前面有签到记录，如果前面无打卡记录则为迟到，如果有打卡记录则为早退
                    if (Objects.nonNull(staffResult.getId())) {
                        // 含有打卡记录为早退
                        staffResult.setStatus(whiteFlag ? 0 : 2);
                    } else {
                        // 不含有打卡记录为迟到
                        staffResult.setStatus(whiteFlag ? 0 : 1);
                    }
                    staffResult.setStartRealTime(time);
                    staffRecord.setRuleId(ruleId);
                    staffRecord.setRuleTimeId(ruleTimeId);
                } else if (time.isAfter(eduAttendanceStaffRuleTime.getEndTime())) {
                    // 前面含有打卡记录，如果无打卡记录，则表示下一时间段的开始时间打卡，此次不记录
                    // 在时间段2之后  与  下一时间段time1之前为 正常
                    // 状态 0-正常，1-迟到，2-早退,3-旷工，4-迟到早退，5-上班未在打卡时间段，6-下班未在打卡时间段
                    EduAttendanceStaffRuleTime nextRuleTime = staffRuleTimes.get(i + 1);
                    if (Objects.nonNull(nextRuleTime)) {
                        // 含有下一时间段
                        if (time.isBefore(nextRuleTime.getStartTime())) {
                            if (eduAttendanceStaffRuleTime.getEndEffectiveStatus() == 1) {
                                if (time.isAfter(eduAttendanceStaffRuleTime.getEndEffectiveStartTime()) && time
                                    .isBefore(eduAttendanceStaffRuleTime.getEndEffectiveEndTime())) {
                                    // 下一时间段之前，下班考勤正常
                                    staffResult.setStatus(0);
                                    staffResult.setEndRealTime(time);
                                } else {
                                    // 下一时间段之前，下课考勤正常
                                    staffResult.setStatus(whiteFlag ? 0 : 6);
                                    staffResult.setEndRealTime(time);
                                }
                            } else {
                                // 下一时间段之前，下课考勤正常
                                staffResult.setStatus(0);
                                staffResult.setEndRealTime(time);
                            }
                            staffRecord.setRuleId(ruleId);
                            staffRecord.setRuleTimeId(ruleTimeId);
                        }
                    } else {
                        if (eduAttendanceStaffRuleTime.getEndEffectiveStatus() == 1) {
                            if (time.isAfter(eduAttendanceStaffRuleTime.getEndEffectiveStartTime()) && time
                                .isBefore(eduAttendanceStaffRuleTime.getEndEffectiveEndTime())) {
                                // 下班有效打卡时间段内
                                staffResult.setStatus(0);
                                staffResult.setEndRealTime(time);
                            } else {
                                // 未在下学有效打卡时间段内
                                staffResult.setStatus(whiteFlag ? 0 : 6);
                                staffResult.setEndRealTime(time);
                            }
                        } else {
                            // 不含有下一时间段
                            staffResult.setStatus(0);
                            staffResult.setEndRealTime(time);
                            staffResult.setEndRealTime(time);
                        }
                        staffRecord.setRuleId(ruleId);
                        staffRecord.setRuleTimeId(ruleTimeId);
                    }
                }
                eduAttendanceStaffRecordMapper.updateById(staffRecord);
                boolean b = eduAttendanceStaffResultService.saveOrUpdate(staffResult);
            }
        }
    }
//    public void dealStudentAttendanceResult(EduAttendanceRecord record) {
//        //迟到，
//        Integer status = record.getStatus();
//        eduAttendanceResultService.getOne(Wrappers.lambdaQuery(new EduAttendanceResult())
//                .eq(EduAttendanceResult::getAttendanceDate,LocalDateTimeUtil.now().toLocalDate())
//                .eq(EduAttendanceResult::getStudentId,record.getStudentId()));
//
//    }
}
