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

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yida.data.attendance.dto.AddAttendanceRuleDTO;
import com.yida.data.attendance.dto.AddAttendanceRuleTimeDTO;
import com.yida.data.attendance.dto.AttendanceFaceMatchDTO;
import com.yida.data.attendance.dto.AttendanceRuleAdminUserAddDTO;
import com.yida.data.attendance.dto.AttendanceRuleAdminUserPageDTO;
import com.yida.data.attendance.dto.AttendanceRuleUserAddDTO;
import com.yida.data.attendance.dto.AttendanceRuleUserPageDTO;
import com.yida.data.attendance.dto.DayReportDataDTO;
import com.yida.data.attendance.dto.PageAttendanceRuleDTO;
import com.yida.data.attendance.dto.UpdateAttendanceRuleStatusDTO;
import com.yida.data.attendance.mapper.AttendanceResultMapper;
import com.yida.data.attendance.mapper.AttendanceRuleMapper;
import com.yida.data.attendance.service.AttendanceRuleAddressService;
import com.yida.data.attendance.service.AttendanceRuleAdminService;
import com.yida.data.attendance.service.AttendanceRuleDeviceService;
import com.yida.data.attendance.service.AttendanceRuleObjService;
import com.yida.data.attendance.service.AttendanceRuleObjUserService;
import com.yida.data.attendance.service.AttendanceRuleRemindService;
import com.yida.data.attendance.service.AttendanceRuleService;
import com.yida.data.attendance.service.AttendanceRuleSpecialDateService;
import com.yida.data.attendance.service.AttendanceRuleTimeService;
import com.yida.data.attendance.service.AttendanceRuleWhiteListService;
import com.yida.data.attendance.service.AttendanceRuleWifiService;
import com.yida.data.attendance.vo.AttendanceFaceMatchVO;
import com.yida.data.attendance.vo.AttendanceRuleAdminUserVO;
import com.yida.data.attendance.vo.AttendanceRuleUserVO;
import com.yida.data.attendance.vo.AttendanceRuleVO;
import com.yida.data.attendance.vo.ConflictRuleVO;
import com.yida.data.attendance.vo.DayReportDataVO;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceResult;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRule;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRuleAddress;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRuleAdmin;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRuleDevice;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRuleObj;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRuleObjUser;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRuleRemind;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRuleSpecialDate;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRuleTime;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRuleWhiteList;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRuleWifi;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.system.BaiduApiConfig;
import com.yida.data.common.core.entity.system.Dept;
import com.yida.data.common.core.entity.user.EduStaff;
import com.yida.data.common.core.entity.user.EduStaffDept;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.entity.user.EduUserDept;
import com.yida.data.common.core.entity.user.enums.UserDeptTypeEnum;
import com.yida.data.common.core.enums.BaiDuModuleEnum;
import com.yida.data.common.core.enums.UserTypeEnum;
import com.yida.data.common.core.enums.attendance.AttendanceResultEnum;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.core.utils.BaiDuUtil;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.common.core.utils.FileUtil;
import com.yida.data.common.service.CommonService;
import com.yida.data.school.dto.userLeave.ListUserRequestDTO;
import com.yida.data.school.feign.leave.RemoteLeaveRequestService;
import com.yida.data.school.vo.userLeave.EduLeaveRequestUserVO;
import com.yida.data.system.feign.RemoteDeptService;
import com.yida.data.user.dto.ListStaffDTO;
import com.yida.data.user.dto.ListStudentDTO;
import com.yida.data.user.feign.RemoteStaffService;
import com.yida.data.user.feign.RemoteStudentService;
import com.yida.data.user.feign.RemoteUserDeptService;
import java.io.File;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 教职工考勤规则 Service实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS)
public class AttendanceRuleServiceImpl extends ServiceImpl
    <AttendanceRuleMapper, AttendanceRule> implements AttendanceRuleService {

    private final RedisService redisService;
    private final AttendanceRuleObjService attendanceRuleObjService;
    private final AttendanceRuleObjUserService attendanceRuleObjUserService;
    private final AttendanceRuleSpecialDateService attendanceRuleSpecialDateService;
    private final AttendanceRuleWhiteListService attendanceRuleWhiteListService;
    private final AttendanceRuleDeviceService attendanceRuleDeviceService;
    private final AttendanceRuleWifiService attendanceRuleWifiService;
    private final AttendanceRuleAddressService attendanceRuleAddressService;
    private final AttendanceRuleTimeService attendanceRuleTimeService;
    private final AttendanceRuleAdminService attendanceRuleAdminService;
    private final AttendanceRuleRemindService attendanceRuleRemindService;
    private final AttendanceResultMapper attendanceResultMapper;
    private final RemoteUserDeptService remoteUserDeptService;

    private final RemoteStudentService remoteStudentService;
    private final RemoteStaffService remoteStaffService;
    private final RemoteDeptService remoteDeptService;
    private final CommonService commonService;
    private final RemoteLeaveRequestService remoteLeaveRequestService;

    @Value("${febs.uploadUrl}")
    private String uploadUrl;

    @Override
    public void addAttendanceRule(AddAttendanceRuleDTO dto) {
        if (CollUtil.isEmpty(dto.getAttendanceRuleObjList())) {
            throw new FebsException("请添加打卡对象");
        }
        //检验规则是否冲突
        List<ConflictRuleVO> conflictRuleVOList = checkConflict(dto);
        if (CollUtil.isNotEmpty(conflictRuleVOList)) {
            StringBuilder builder = new StringBuilder();
            for (ConflictRuleVO vo : conflictRuleVOList) {
                builder.append(vo.getDeptName())
                    .append("已存在")
                    .append(vo.getRuleName())
                    .append("规则")
                    .append(",");
            }
            builder.append("上述规则的运行时间与本规则运行时间有重叠，请调整设置。");
            throw new FebsException(builder.toString());
        }

        if (ObjectUtil.isNotNull(dto.getId())) {
            //编辑
            removeAttachedList(Lists.newArrayList(dto.getId()), false);

            //TODO 考勤时段不能删除
            //更新规则缓存信息
            redisService.hdel(CachePrefixConstant.ATTENDANCE_RULE_DATA, String.valueOf(dto.getId()));
        }
        AttendanceRule rule = new AttendanceRule();
        BeanUtils.copyProperties(dto, rule);
        rule.setSchoolId(FebsUtil.getDeptId());
        saveOrUpdate(rule);

        List<AttendanceRuleObj> ruleObjList = new ArrayList<>();
        if (CollUtil.isNotEmpty(dto.getAttendanceRuleObjList())) {
            dto.getAttendanceRuleObjList().forEach(addAttendanceRuleObjDTO -> {
                AttendanceRuleObj attendanceRuleObj = new AttendanceRuleObj();
                BeanUtils.copyProperties(addAttendanceRuleObjDTO, attendanceRuleObj);
                attendanceRuleObj.setUserType(dto.getUserType() == 0 ? 0 : 1);
                attendanceRuleObj.setRuleId(rule.getId());
                ruleObjList.add(attendanceRuleObj);
            });
        }
        if (CollUtil.isNotEmpty(ruleObjList)) {
            attendanceRuleObjService.saveBatch(ruleObjList);
        }

        List<AttendanceRuleSpecialDate> attendanceRuleSpecialDateArrayList = new ArrayList<>();
        if (CollUtil.isNotEmpty(dto.getSpecialDateDTOList())) {
            dto.getSpecialDateDTOList().forEach(specialDateDTO -> {
                AttendanceRuleSpecialDate specialDate = new AttendanceRuleSpecialDate();
                BeanUtils.copyProperties(specialDateDTO, specialDate);
                specialDate.setRuleId(rule.getId());
                attendanceRuleSpecialDateArrayList.add(specialDate);
            });
        }
        if (CollUtil.isNotEmpty(attendanceRuleSpecialDateArrayList)) {
            attendanceRuleSpecialDateService.saveBatch(attendanceRuleSpecialDateArrayList);
        }

        List<AttendanceRuleWhiteList> attendanceRuleWhiteListArrayList = new ArrayList<>();
        if (CollUtil.isNotEmpty(dto.getWhiteListDTOList())) {
            dto.getWhiteListDTOList().forEach(whiteListDTO -> {
                AttendanceRuleWhiteList whiteList = new AttendanceRuleWhiteList();
                BeanUtils.copyProperties(whiteListDTO, whiteList);
                whiteList.setRuleId(rule.getId());
                whiteList.setUserType(dto.getUserType() == 0 ? 0 : 1);
                attendanceRuleWhiteListArrayList.add(whiteList);
            });
        }
        if (CollUtil.isNotEmpty(attendanceRuleWhiteListArrayList)) {
            attendanceRuleWhiteListService.saveBatch(attendanceRuleWhiteListArrayList);
        }

        List<AttendanceRuleDevice> attendanceRuleDeviceArrayList = new ArrayList<>();
        if (CollUtil.isNotEmpty(dto.getDeviceDTOList())) {
            dto.getDeviceDTOList().forEach(deviceDTO -> {
                AttendanceRuleDevice device = new AttendanceRuleDevice();
                BeanUtils.copyProperties(deviceDTO, device);
                device.setRuleId(rule.getId());
                attendanceRuleDeviceArrayList.add(device);
            });
        }
        if (CollUtil.isNotEmpty(attendanceRuleDeviceArrayList)) {
            attendanceRuleDeviceService.saveBatch(attendanceRuleDeviceArrayList);
        }

        List<AttendanceRuleWifi> attendanceRuleWifiArrayList = new ArrayList<>();
        if (CollUtil.isNotEmpty(dto.getWifiDTOList())) {
            dto.getWifiDTOList().forEach(wifiDTO -> {
                AttendanceRuleWifi wifi = new AttendanceRuleWifi();
                BeanUtils.copyProperties(wifiDTO, wifi);
                wifi.setRuleId(rule.getId());
                attendanceRuleWifiArrayList.add(wifi);
            });
        }
        if (CollUtil.isNotEmpty(attendanceRuleWifiArrayList)) {
            attendanceRuleWifiService.saveBatch(attendanceRuleWifiArrayList);
        }

        List<AttendanceRuleAddress> attendanceRuleAddresseList = new ArrayList<>();
        if (CollUtil.isNotEmpty(dto.getAddressDTOList())) {
            dto.getAddressDTOList().forEach(addressDTO -> {
                AttendanceRuleAddress address = new AttendanceRuleAddress();
                BeanUtils.copyProperties(addressDTO, address);
                address.setRuleId(rule.getId());
                attendanceRuleAddresseList.add(address);
            });
        }
        if (CollUtil.isNotEmpty(attendanceRuleAddresseList)) {
            attendanceRuleAddressService.saveBatch(attendanceRuleAddresseList);
        }

        //考勤时段
        List<AttendanceRuleTime> attendanceRuleTimeArrayList = new ArrayList<>();
        if (CollUtil.isNotEmpty(dto.getTimeDTOList())) {
            dto.getTimeDTOList().forEach(timeDTO -> {
                AttendanceRuleTime time = new AttendanceRuleTime();
                BeanUtils.copyProperties(timeDTO, time);
                time.setRuleId(rule.getId());
                attendanceRuleTimeArrayList.add(time);
            });
        }
        if (CollUtil.isNotEmpty(attendanceRuleTimeArrayList)) {
            attendanceRuleTimeService.saveOrUpdateBatch(attendanceRuleTimeArrayList);
        }

        List<AttendanceRuleAdmin> attendanceRuleAdminList = new ArrayList<>();
        if (CollUtil.isNotEmpty(dto.getAdminDTOList())) {
            dto.getAdminDTOList().forEach(adminDTO -> {
                if (ObjectUtil.isNotNull(adminDTO.getDeptId()) && ObjectUtil.isNotNull(adminDTO.getStaffId())) {
                    AttendanceRuleAdmin admin = new AttendanceRuleAdmin();
                    BeanUtils.copyProperties(adminDTO, admin);
                    admin.setRuleId(rule.getId());
                    admin.setUserType(dto.getUserType() == 0 ? 0 : 1);
                    admin.setSchoolId(FebsUtil.getTopDeptId());
                    attendanceRuleAdminList.add(admin);
                }
            });
        }
        if (CollUtil.isNotEmpty(attendanceRuleAdminList)) {
            attendanceRuleAdminService.saveBatch(attendanceRuleAdminList);
        }

        List<AttendanceRuleRemind> attendanceRuleRemindList = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(dto.getRemindDTOList())) {
            dto.getRemindDTOList().forEach(remindDTO -> {
                AttendanceRuleRemind remind = new AttendanceRuleRemind();
                BeanUtils.copyProperties(remindDTO, remind);
                remind.setRuleId(rule.getId());
                remind.setUserType(dto.getUserType() == 0 ? 0 : 1);
                attendanceRuleRemindList.add(remind);
            });
        }
        if (CollUtil.isNotEmpty(attendanceRuleRemindList)) {
            attendanceRuleRemindService.saveBatch(attendanceRuleRemindList);
        }

        //TODO 添加具体的打卡人员
        attendanceRuleObjUserService.addRuleUser(ruleObjList, FebsUtil.getTopDeptId(), rule.getUserType());

        //清除缓存信息
        commonService.clearAttendanceRuleData();
    }


    @Override
    public AttendanceRuleVO getRule(Long id) {
        return baseMapper.getRule(id);
    }

    @Override
    public void deleteRule(List<Long> idList) {
        removeAttachedList(idList, true);
        removeByIds(idList);

        //清除缓存信息
        commonService.clearAttendanceRuleData();
    }

    @Override
    public IPage<AttendanceRuleVO> listRulePage(PageAttendanceRuleDTO dto) {
        return baseMapper
            .listRulePage(dto.toPage(), dto.getSchoolId(), dto.getRuleName(), dto.getType(), dto.getUserType(),
                dto.getStatus());
    }

    @Override
    public List<AttendanceRuleVO> listRule(PageAttendanceRuleDTO dto) {
        return baseMapper
            .listRule(dto.getSchoolId(), dto.getRuleName(), dto.getType(), dto.getUserType(),
                dto.getStatus());
    }

    @Override
    public IPage<AttendanceRuleUserVO> listRuleAttendanceUser(AttendanceRuleUserPageDTO dto) {
        List<Long> userIdList = new ArrayList<>();
        ListStudentDTO param = new ListStudentDTO();
        ListStaffDTO staffParam = new ListStaffDTO();
        if (ObjectUtil.isNotNull(dto.getUserName())) {
            if (ObjectUtil.equals(dto.getUserType(), UserTypeEnum.PARENT_USER_TYPE.getType())) {
                param.setStuName(dto.getUserName());
            } else {
                staffParam.setName(dto.getUserName());
            }
        }
        param.setSchoolId(dto.getSchoolId());
        param.setCampusId(dto.getCampusId());
        param.setSectionId(dto.getSectionId());
        param.setGradeId(dto.getGradeId());
        param.setClassId(dto.getClassId());
        staffParam.setDeptId(dto.getDeptId());
        if (ObjectUtil.isNotNull(dto.getUserName()) || ObjectUtil.isNotNull(dto.getCampusId())
            || ObjectUtil.isNotNull(dto.getSectionId()) || ObjectUtil.isNotNull(dto.getGradeId())
            || ObjectUtil.isNotNull(dto.getClassId())) {
            List<Long> idList = remoteStudentService.listStudent(param).getData().stream().map(EduStudent::getId)
                .collect(Collectors.toList());
            if (CollUtil.isNotEmpty(idList)) {
                userIdList.addAll(idList);
                dto.setUserIdList(userIdList);
            } else {
                dto.setUserIdList(Arrays.asList(-1L));
            }
        }
        if (ObjectUtil.isNotNull(dto.getUserName()) || ObjectUtil.isNotNull(dto.getDeptId())) {
            List<Long> idList = remoteStaffService.listStaff(staffParam).getData().stream().map(EduStaff::getId)
                .collect(Collectors.toList());
            if (CollUtil.isNotEmpty(idList)) {
                userIdList.addAll(idList);
                dto.setUserIdList(userIdList);
            } else {
                dto.setUserIdList(Arrays.asList(-1L));
            }
        }

        IPage<AttendanceRuleUserVO> attendanceRuleUserVOIPage = baseMapper.listRuleAttendanceUser(dto.toPage(), dto);
        List<AttendanceRuleUserVO> records = attendanceRuleUserVOIPage.getRecords();
        for (AttendanceRuleUserVO record : records) {
            if (ObjectUtil.equals(dto.getUserType(), UserTypeEnum.PARENT_USER_TYPE.getType())) {
                //学生信息
                EduStudent student = commonService.getStudentById(record.getUserId());
                record.setUserName(student.getStuName());
                record.setDeptName(student.getCampusName() + "/" + student.getSectionName() + "/" + student.getClassName());
            } else {
                EduStaff staff = commonService.getStaffById(record.getUserId());
                record.setUserName(staff.getName());
                record.setDeptName(staff.getStaffDept().get(0).getDeptName());
            }
        }
        return attendanceRuleUserVOIPage;
    }

    @Override
    public void deleteRuleAttendanceUser(List<Long> ids) {
        //删除今日考勤结果
        for (Long id : ids) {
            AttendanceRuleObjUser objUser = attendanceRuleObjUserService.getById(id);
            attendanceResultMapper.delete(Wrappers.lambdaQuery(new AttendanceResult())
                .eq(AttendanceResult::getAttendanceDate, LocalDate.now())
                .eq(AttendanceResult::getRuleId, objUser.getRuleId())
                .eq(AttendanceResult::getUserId, objUser.getUserId())
                .eq(AttendanceResult::getUserType, objUser.getUserType()));
        }
        //删除主体
        attendanceRuleObjUserService.removeByIds(ids);
    }

    @Override
    public void addRuleAttendanceUser(AttendanceRuleUserAddDTO dto) {
        AttendanceRuleObjUser objUser = new AttendanceRuleObjUser();
        BeanUtils.copyProperties(dto, objUser);
        if (ObjectUtil.equals(dto.getUserType(), UserTypeEnum.PARENT_USER_TYPE.getType())) {
            EduStudent student = commonService.getStudentById(dto.getUserId());
            if (ObjectUtil.isNull(student)) {
                throw new FebsException("用户不存在");
            }
            List<AttendanceRuleObjUser> list = attendanceRuleObjUserService.list(Wrappers.lambdaQuery(new AttendanceRuleObjUser())
                .eq(AttendanceRuleObjUser::getUserId, dto.getUserId())
                .eq(AttendanceRuleObjUser::getUserType, dto.getUserType())
                .eq(AttendanceRuleObjUser::getRuleId, dto.getRuleId()));

            if (CollUtil.isNotEmpty(list)) {
                throw new FebsException("用户已添加");
            }
            if (ObjectUtil.isNotNull(student)) {
                objUser.setDeptId(student.getClassId());
                objUser.setUserName(student.getStuName());
            }

            List<AttendanceRuleObj> objList = attendanceRuleObjService.list(Wrappers.lambdaQuery(new AttendanceRuleObj())
                .eq(AttendanceRuleObj::getRuleId, dto.getRuleId())
                .eq(AttendanceRuleObj::getDeptId, student.getClassId())
                .eq(AttendanceRuleObj::getUserType, dto.getUserType()));

            if (CollUtil.isEmpty(objList)) {
                throw new FebsException("用户部门未加入考勤规则，请编辑规则");
            }
        } else {
            EduStaff staff = commonService.getStaffById(dto.getUserId());
            if (ObjectUtil.isNull(staff)) {
                throw new FebsException("用户不存在");
            }
            List<AttendanceRuleObjUser> list = attendanceRuleObjUserService.list(Wrappers.lambdaQuery(new AttendanceRuleObjUser())
                .eq(AttendanceRuleObjUser::getUserId, dto.getUserId())
                .eq(AttendanceRuleObjUser::getUserType, dto.getUserType())
                .eq(AttendanceRuleObjUser::getRuleId, dto.getRuleId()));

            if (CollUtil.isNotEmpty(list)) {
                throw new FebsException("用户已添加");
            }
            if (ObjectUtil.isNotNull(staff)) {
                objUser.setDeptId(staff.getStaffDept().get(0).getDeptId());
                objUser.setUserName(staff.getName());
            }

            List<AttendanceRuleObj> objList = attendanceRuleObjService.list(Wrappers.lambdaQuery(new AttendanceRuleObj())
                .eq(AttendanceRuleObj::getRuleId, dto.getRuleId())
                .eq(AttendanceRuleObj::getDeptId, staff.getStaffDept().get(0).getDeptId())
                .eq(AttendanceRuleObj::getUserType, dto.getUserType()));

            if (CollUtil.isEmpty(objList)) {
                throw new FebsException("用户部门未加入考勤规则，请编辑规则");
            }
        }

        AttendanceRuleVO rule = getRule(dto.getRuleId());

        AttendanceResult result = new AttendanceResult();
        result.setAttType(rule.getType());
        result.setUserType(objUser.getUserType());
        result.setUserId(objUser.getUserId());
        result.setSchoolId(rule.getSchoolId());
        result.setRuleId(rule.getId());

        for (AddAttendanceRuleTimeDTO ruleTimeDTO : rule.getTimeDTOList()) {
            long count = attendanceResultMapper.selectCount(Wrappers.lambdaQuery(new AttendanceResult())
                .eq(AttendanceResult::getAttendanceDate, LocalDate.now())
                .eq(AttendanceResult::getUserId, objUser.getUserId())
                .eq(AttendanceResult::getRuleId, rule.getId())
                .eq(AttendanceResult::getRuleTimeId, ruleTimeDTO.getId()));
            if (count == 0) {
                result.setRuleTimeId(ruleTimeDTO.getId());
                result.setStartStiTime(ruleTimeDTO.getStartTime());
                result.setEndStiTime(ruleTimeDTO.getEndTime());
                result.setAttendanceDate(LocalDate.now());
            }
        }
        attendanceResultMapper.insert(result);
        attendanceRuleObjUserService.save(objUser);
    }

    @Override
    public void updateRuleStatus(UpdateAttendanceRuleStatusDTO dto) {
        update(Wrappers.lambdaUpdate(new AttendanceRule())
            .eq(AttendanceRule::getId, dto.getId())
            .set(AttendanceRule::getStatus, dto.getStatus()));
    }

    @Override
    public AttendanceRuleVO findUserMatchRule(Integer userType, Long userId, String deviceSn, String wifiName, String wifiBssid,
        LocalDate currentDate, Long schoolId) {
        //查询user 所属deptId
        List<Long> deptIdList = new ArrayList<>();
        if (ObjectUtil.isNull(userType)) {
            return null;
        }
        if (UserTypeEnum.STAFF_USER_TYPE.getType().equals(userType)) {
            //教职工
            EduStaff staff = remoteStaffService.getStaff(userId).getData();
            if (Objects.isNull(staff)) {
                if (redisService.hHasKey(CachePrefixConstant.STAFF_DATA, userId.toString())) {
                    redisService.hdel(CachePrefixConstant.STAFF_DATA, userId.toString());
                }
                log.error("职工不存在,id:[{}]", userId);
                return null;
            }
            if (ObjectUtil.isNull(schoolId)) {
                schoolId = staff.getSchoolId();
            }
            List<Long> staffDeptIdList = staff.getStaffDept().stream().map(EduStaffDept::getDeptId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(staffDeptIdList)) {
                deptIdList = remoteDeptService.listParentDeptByChild(staffDeptIdList).getData().stream().map(Dept::getDeptId)
                    .collect(Collectors.toList());
            }
        } else {
            EduStudent student = remoteStudentService.getStudentNoPermission(userId).getData();

            if (ObjectUtil.isNull(student)) {
                if (redisService.hHasKey(CachePrefixConstant.STUDENT_DATA, userId.toString())) {
                    redisService.hdel(CachePrefixConstant.STUDENT_DATA, userId.toString());
                }
                log.error("学生不存在,id:[{}]", userId);
                return null;
            }
            if (ObjectUtil.isNull(schoolId)) {
                schoolId = student.getSchoolId();
            }
            deptIdList = Lists
                .newArrayList(-student.getSchoolId(), student.getCampusId(), student.getSectionId(), student.getGradeId(),
                    student.getClassId());
        }

        if (CollUtil.isNotEmpty(deptIdList)) {
            if (ObjectUtil.isNotNull(deviceSn)) {
                List<AttendanceRuleVO> userMatchRuleByDevice = baseMapper
                    .findUserMatchRuleByDevice(userType, deptIdList, deviceSn, currentDate, currentDate.getDayOfWeek().getValue(),
                        schoolId);
                if (CollUtil.isEmpty(userMatchRuleByDevice)) {
                    return null;
                } else {
                    return userMatchRuleByDevice.get(0);
                }
            } else if (ObjectUtil.isNotNull(wifiBssid) && ObjectUtil.isNotNull(wifiName)) {
                List<AttendanceRuleVO> userMatchRuleByWifi = baseMapper
                    .findUserMatchRuleByWifi(userType, deptIdList, wifiName, wifiBssid, null, currentDate,
                        currentDate.getDayOfWeek().getValue(),
                        schoolId);
                if (CollUtil.isEmpty(userMatchRuleByWifi)) {
                    return null;
                } else {
                    return userMatchRuleByWifi.get(0);
                }
            }
        }
        return null;
    }

    @Override
    public AttendanceFaceMatchVO AttendanceFaceMatch(AttendanceFaceMatchDTO dto) {
        File file = null;
        try {
            String avatar = "";
            if (UserTypeEnum.STAFF_USER_TYPE.getType().equals(dto.getUserType())) {
                EduStaff staff = commonService.getStaffById(dto.getUserId());
                avatar = staff.getAvatar();
            } else if (UserTypeEnum.PARENT_USER_TYPE.getType().equals(dto.getUserType())) {
                EduStudent student = commonService.getStudentById(dto.getUserId());
                avatar = student.getAvatar();
            } else {
                throw new FebsException("人员类型信息错误, 0=教职工,1=学生");
            }
            if (ObjectUtil.isEmpty(avatar)) {
                throw new FebsException("暂无人员人脸信息，请联系管理员");
            }
            // 查询百度api配置信息
            BaiduApiConfig config = commonService
                .getBaiDuApiConfigByDept(dto.getSchoolId(), BaiDuModuleEnum.FACE_DETECT.getValue());

            if (Objects.isNull(config)) {
                log.error("获取百度api相关信息错误deptId: {}", dto.getSchoolId());
                throw new FebsException("暂未配置人脸对比信息");
            }
            // 人脸对比 阈值80
            String score = BaiDuUtil.faceMatch(config, avatar, dto.getBase64());
            int valid = NumberUtil.isLess(new BigDecimal("65"), new BigDecimal(score)) ? 1 : 0;
            AttendanceFaceMatchVO matchVO = AttendanceFaceMatchVO
                .builder()
                .valid(valid)
                .score(score)
                .build();
            // 对比成功则上传图片
            if (valid == 1) {
                String fileName = FileUtil.getLocalUploadAddress() + UUID.randomUUID() + ".png";
                file = new File(fileName);
                // 上传图片
                file = Base64.decodeToFile(dto.getBase64(), file);
                String url = FileUtil.uploadFileToMediaServer(uploadUrl, file);
                matchVO.setUrl(url);
            } else {
                log.info("用户：{}，人脸比对值：{}", dto.getUserId(), score);
            }
            return matchVO;
        } catch (Exception e) {
            throw new FebsException(e instanceof FebsException ? e.getMessage() : "人脸对比失败");
        } finally {
            if (Objects.nonNull(file)) {
                cn.hutool.core.io.FileUtil.del(file);
            }
        }
    }

    @Override
    public List<AttendanceRuleVO> findByUserIdAndUserType(Long userId, Integer userType) {
        return baseMapper.findByUserIdAndUserType(userId, userType);
    }


    @Override
    public List<AttendanceRuleVO> findUserManageRuleList(Long userId, Integer searchUserType) {
        return baseMapper.findUserManageRuleList(userId, searchUserType);
    }

    @Override
    public List<Long> getSchoolIdList() {
        return baseMapper.getSchoolIdList();
    }

    @Override
    public IPage<AttendanceRuleAdminUserVO> listRuleAttendanceAdminUser(AttendanceRuleAdminUserPageDTO dto) {
        //根据条件查询下级部门ID
        if (ObjectUtil.isNotNull(dto.getClassId())) {
            dto.setDeptIdList(Arrays.asList(dto.getClassId()));
        } else if (ObjectUtil.isNotNull(dto.getGradeId())) {
            List<EduUserDept> deptList = remoteUserDeptService.findListByParent(dto.getGradeId()).getData();
            if (CollUtil.isNotEmpty(deptList)) {
                List<Long> deptIdList = deptList.stream().map(EduUserDept::getDeptId).collect(Collectors.toList());
                deptIdList.add(dto.getGradeId());
                dto.setDeptIdList(deptIdList);
            } else {
                dto.setDeptIdList(Arrays.asList(dto.getGradeId()));
            }
        } else if (ObjectUtil.isNotNull(dto.getSectionId())) {
            List<EduUserDept> deptList = remoteUserDeptService.findListByParent(dto.getSectionId()).getData();
            if (CollUtil.isNotEmpty(deptList)) {
                List<Long> deptIdList = deptList.stream().map(EduUserDept::getDeptId).collect(Collectors.toList());
                deptIdList.add(dto.getSectionId());
                dto.setDeptIdList(deptIdList);
            } else {
                dto.setDeptIdList(Arrays.asList(dto.getGradeId()));
            }
        } else if (ObjectUtil.isNotNull(dto.getCampusId())) {
            List<EduUserDept> deptList = remoteUserDeptService.findListByParent(dto.getCampusId()).getData();
            if (CollUtil.isNotEmpty(deptList)) {
                List<Long> deptIdList = deptList.stream().map(EduUserDept::getDeptId).collect(Collectors.toList());
                deptIdList.add(dto.getCampusId());
                dto.setDeptIdList(deptIdList);
            } else {
                dto.setDeptIdList(Arrays.asList(dto.getGradeId()));
            }
        }

        if (ObjectUtil.isNotEmpty(dto.getStaffName())) {
            ListStaffDTO param = new ListStaffDTO();
            param.setName(dto.getStaffName());
            List<EduStaff> eduStaffList = remoteStaffService.listStaff(param).getData();
            if (CollUtil.isNotEmpty(eduStaffList)) {
                List<Long> staffIdList = eduStaffList.stream().map(EduStaff::getId).collect(Collectors.toList());
                dto.setStaffIdList(staffIdList);
            }
        }

        IPage<AttendanceRuleAdminUserVO> attendanceRuleAdminUserVOIPage = baseMapper
            .listRuleAttendanceAdminUser(dto.toPage(), dto);

        List<AttendanceRuleAdminUserVO> records = attendanceRuleAdminUserVOIPage.getRecords();
        for (AttendanceRuleAdminUserVO record : records) {
            //查询部门Name
            List<EduUserDept> eduUserDeptList = remoteUserDeptService.getParentListByDeptId(record.getDeptId()).getData();
            Collections.reverse(eduUserDeptList);
            record.setDeptName(eduUserDeptList.stream()
                .filter(eduUserDept -> ObjectUtil.isNotNull(eduUserDept) && ObjectUtil.isNotNull(eduUserDept.getDeptName()))
                .map(EduUserDept::getDeptName).collect(Collectors.joining("/")));
            record.setStaffName(commonService.getStaffById(record.getStaffId()).getName());
        }

        return attendanceRuleAdminUserVOIPage;
    }

    @Override
    public void addAttendanceAdminUser(AttendanceRuleAdminUserAddDTO dto) {
        AttendanceRuleAdmin admin = new AttendanceRuleAdmin();
        BeanUtils.copyProperties(dto, admin);
        admin.setUserType(UserTypeEnum.PARENT_USER_TYPE.getType());
        admin.setSchoolId(FebsUtil.getTopDeptId());
        attendanceRuleAdminService.saveOrUpdate(admin);
    }

    @Override
    public void deleteRuleAttendanceAdminUser(List<Long> ids) {
        attendanceRuleAdminService.removeByIds(ids);
    }

    @Override
    public List<DayReportDataVO> getDayReport(Long staffId, Integer userType, Long ruleId, String attendanceDateStr) {

        LocalDate attendanceDate = LocalDate.parse(attendanceDateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        //今日未打卡人员
        List<AttendanceResult> resultList = attendanceResultMapper.selectList(Wrappers.lambdaQuery(new AttendanceResult())
            .eq(AttendanceResult::getRuleId, ruleId)
            .eq(AttendanceResult::getAttendanceDate, attendanceDate)
            .isNull(AttendanceResult::getStartStatus));

        List<AttendanceRuleAdmin> adminList = attendanceRuleAdminService.list(Wrappers.lambdaQuery(new AttendanceRuleAdmin())
            .eq(AttendanceRuleAdmin::getRuleId, ruleId)
            .eq(AttendanceRuleAdmin::getStaffId, staffId));

        List<DayReportDataVO> dayReportDataVOS = new ArrayList<>();
        for (AttendanceRuleAdmin attendanceRuleAdmin : adminList) {
            DayReportDataVO vo = new DayReportDataVO();
            List<Long> deptIdList = new ArrayList<>();
            if (ObjectUtil.equals(UserTypeEnum.PARENT_USER_TYPE.getType(), userType)) {
                EduUserDept userDept = commonService.getUserDept(attendanceRuleAdmin.getDeptId());
                vo.setDeptName(ObjectUtil.isNull(userDept) ? "未知班级" : userDept.getDeptName());
                if (ObjectUtil.isNotNull(userDept)) {
                    if (ObjectUtil.equals(UserDeptTypeEnum.CLASS_TYPE.getValue(), userDept.getDeptType())) {
                        deptIdList = Arrays.asList(userDept.getDeptId());
                    } else {
                        //查看班级
                        deptIdList = remoteUserDeptService
                            .findChildIdByParentAndTypeNoPermission(attendanceRuleAdmin.getDeptId(), 1)
                            .getData().stream().map(EduUserDept::getDeptId).collect(
                                Collectors.toList());
                    }
                }
            } else {
                Dept dept = commonService.getDept(attendanceRuleAdmin.getDeptId());
                vo.setDeptName(ObjectUtil.isNull(dept) ? "未知部门" : dept.getDeptName());
                deptIdList = Arrays.asList(dept.getDeptId());
            }
            //管理总人数
            if (CollUtil.isEmpty(deptIdList)) {
                vo.setTotalNum(0);
                vo.setAbNum(0);
                vo.setRequestNum(0);
            } else {
                List<Long> mangerUserIdList = attendanceRuleObjUserService
                    .list(Wrappers.lambdaQuery(new AttendanceRuleObjUser())
                        .in(AttendanceRuleObjUser::getDeptId, deptIdList)
                        .eq(AttendanceRuleObjUser::getRuleId, ruleId)).stream().map(AttendanceRuleObjUser::getUserId)
                    .collect(
                        Collectors.toList());
                //未打卡人数
                List<AttendanceResult> mangerResultList =
                    CollUtil.isEmpty(mangerUserIdList) ? new ArrayList<>() : resultList.stream()
                        .filter(result -> mangerUserIdList.contains(result.getUserId())).collect(Collectors.toList());

                vo.setTotalNum(mangerUserIdList.size());
                vo.setAbNum(mangerResultList.size());

                //查询请假人数
                if (CollUtil.isEmpty(mangerUserIdList)) {
                    vo.setRequestNum(0);
                } else {
                    ListUserRequestDTO requestDTO = new ListUserRequestDTO();
                    requestDTO.setRequestType(userType);
                    requestDTO.setStartTime(attendanceDate.atTime(LocalTime.of(00, 00, 01)));
                    requestDTO.setEndTime(attendanceDate.atTime(LocalTime.of(23, 59, 59)));
                    requestDTO.setUserIdList(mangerUserIdList);
                    List<EduLeaveRequestUserVO> requestUserVOList = remoteLeaveRequestService.findList(requestDTO).getData();
                    vo.setRequestNum(
                        requestUserVOList.stream().collect(Collectors.groupingBy(EduLeaveRequestUserVO::getUserId))
                            .size());
                }

                String scoreStr = "";
                if (vo.getTotalNum() == 0) {
                    scoreStr = "0.00%";
                } else {
                    double score =
                        (double) ((vo.getTotalNum() - vo.getAbNum()) * 100) / vo
                            .getTotalNum();
                    scoreStr = String.format("%.2f", score) + "%";
                }
                vo.setScore(scoreStr);
                vo.setDate(attendanceDate);
                dayReportDataVOS.add(vo);
            }
        }
        return dayReportDataVOS;
    }

    public List<ConflictRuleVO> checkConflict(AddAttendanceRuleDTO rule) {
        List<Long> deptIdList = rule.getAttendanceRuleObjList().stream().map(x -> x.getDeptId()).collect(Collectors.toList());
        if (CollUtil.isEmpty(deptIdList)) {
            return new ArrayList<>();
        }
        // 查询有关联的部门
        List<Long> deptIds = remoteUserDeptService.getUpAndDownId(deptIdList.toArray(new Long[0])).getData();
        log.info("deptIds:[{}]", deptIds);
        String[] weekList = rule.getWeek().split(",");
        List<ConflictRuleVO> conflictRuleVOList = new ArrayList<>();
        for (String week : weekList) {
            List<ConflictRuleVO> conflictRuleVOS = baseMapper
                .checkNormalRule(deptIds, rule.getStartDate(), rule.getEndDate(), rule.getUserType(), rule.getId(), week);
            if (CollUtil.isNotEmpty(conflictRuleVOS)) {
                conflictRuleVOList.addAll(conflictRuleVOS);
            }
        }
        return conflictRuleVOList;
    }

    /**
     * 删除规则附表
     */
    public void removeAttachedList(List<Long> ruleIdList, Boolean type) {

        attendanceRuleObjService.remove(Wrappers.lambdaQuery(new AttendanceRuleObj())
            .in(AttendanceRuleObj::getRuleId, ruleIdList));

        attendanceRuleObjUserService.remove(Wrappers.lambdaQuery(new AttendanceRuleObjUser())
            .in(AttendanceRuleObjUser::getRuleId, ruleIdList));

        attendanceRuleSpecialDateService.remove(Wrappers.lambdaQuery(new AttendanceRuleSpecialDate())
            .in(AttendanceRuleSpecialDate::getRuleId, ruleIdList));

        attendanceRuleWhiteListService.remove(Wrappers.lambdaQuery(new AttendanceRuleWhiteList())
            .in(AttendanceRuleWhiteList::getRuleId, ruleIdList));

        attendanceRuleDeviceService.remove(Wrappers.lambdaQuery(new AttendanceRuleDevice())
            .in(AttendanceRuleDevice::getRuleId, ruleIdList));

        attendanceRuleWifiService.remove(Wrappers.lambdaQuery(new AttendanceRuleWifi())
            .in(AttendanceRuleWifi::getRuleId, ruleIdList));

        attendanceRuleAddressService.remove(Wrappers.lambdaQuery(new AttendanceRuleAddress())
            .in(AttendanceRuleAddress::getRuleId, ruleIdList));

        if (type) {
            attendanceRuleTimeService.remove(Wrappers.lambdaQuery(new AttendanceRuleTime())
                .in(AttendanceRuleTime::getRuleId, ruleIdList));
        }

        attendanceRuleAdminService.remove(Wrappers.lambdaQuery(new AttendanceRuleAdmin())
            .in(AttendanceRuleAdmin::getRuleId, ruleIdList));

        attendanceRuleRemindService.remove(Wrappers.lambdaQuery(new AttendanceRuleRemind())
            .in(AttendanceRuleRemind::getRuleId, ruleIdList));
    }


}
