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

import static com.yida.data.common.core.entity.constant.CachePrefixConstant.STAFF_DATA;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
//import com.yida.data.attendance.feign.RemoteAttendanceResultService;
//import com.yida.data.attendance.vo.AttendanceRuleCacheVO;
//import com.yida.data.attendance.vo.RuleListVO;
import com.yida.data.common.core.common.ResultMsgType;
import com.yida.data.common.core.entity.CurrentUser;
import com.yida.data.common.core.entity.QueryRequest;
import com.yida.data.common.core.entity.Tree;
import com.yida.data.common.core.entity.UserDeptTree;
import com.yida.data.common.core.entity.attendance.EduAttendanceRuleTime;
import com.yida.data.common.core.entity.constant.AppConstant;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.constant.FebsConstant;
import com.yida.data.common.core.entity.constant.PageConstant;
import com.yida.data.common.core.entity.school.EduDormitory;
import com.yida.data.common.core.entity.system.Dept;
import com.yida.data.common.core.entity.system.EduApp;
import com.yida.data.common.core.entity.system.enums.DeptTypeEnum;
import com.yida.data.common.core.entity.system.enums.RoleEnum;
import com.yida.data.common.core.entity.user.EduStaff;
import com.yida.data.common.core.entity.user.EduStaffWork;
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.EduUserDeptStandardGrade;
import com.yida.data.common.core.entity.user.enums.DeptVisibleTypeEnum;
import com.yida.data.common.core.entity.user.enums.GraduatedStatusEnum;
import com.yida.data.common.core.entity.user.enums.SectionTypeEnum;
import com.yida.data.common.core.entity.user.enums.UserDeptTypeEnum;
import com.yida.data.common.core.enums.IncludeTypeEnum;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.core.utils.*;
import com.yida.data.school.feign.facility.RemoteDormitoryService;
import com.yida.data.system.feign.RemoteDeptService;
import com.yida.data.system.vo.ClassInfoVO;
import com.yida.data.system.vo.SchoolClassInfoVO;
import com.yida.data.user.dto.*;
import com.yida.data.user.mapper.*;
import com.yida.data.user.service.EduStaffService;
import com.yida.data.user.service.EduStaffWorkService;
import com.yida.data.user.service.EduUserDeptService;
import com.yida.data.user.vo.AllDeptInfoVO;
import com.yida.data.user.vo.ClassAttendanceDataVO;
import com.yida.data.user.vo.CollectDataVO;
import com.yida.data.user.vo.TeacherDeptVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 家校部门表(只有学校会有) Service实现
 *
 * @author ZYJ
 * @date 2021-11-11 09:25:44
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduUserDeptServiceImpl extends ServiceImpl
    <EduUserDeptMapper, EduUserDept> implements EduUserDeptService {

    @Lazy
    @Resource
    private EduStaffService eduStaffService;
    private final EduStaffWorkService eduStaffWorkService;

    private final QywxAppMapper appMapper;
    private final EduStaffMapper eduStaffMapper;
    private final EduStudentMapper eduStudentMapper;
    private final EduUserDeptStandardGradeMapper eduUserDeptStandardGradeMapper;

    private final RemoteDeptService remoteDeptService;
    private final RemoteDormitoryService remoteDormitoryService;

    private final WxUtil wxUtil;
    private final RedisService redisService;

    /**
     * 查询所有子节点
     *
     * @param userDeptIdList 家校部门id集合
     * @return java.util.List<com.yida.data.common.core.entity.user.EduUserDept>
     * @author ZYJ
     * @date 2021/11/11 10:10
     */
    @Override
    public List<EduUserDept> findListByParent(List<Long> userDeptIdList) {
        List<EduUserDept> result = new ArrayList<>();
        // 查询直接子部门
        LambdaQueryWrapper<EduUserDept> condition = Wrappers.lambdaQuery(new EduUserDept())
            .in(EduUserDept::getParentId, userDeptIdList)
            .eq(EduUserDept::getVisible, DeptVisibleTypeEnum.VISIBLE_TYPE.getValue())
            .orderByDesc(EduUserDept::getOrderNum);
        List<EduUserDept> child = list(condition);
        if (CollectionUtils.isNotEmpty(child)) {
            result.addAll(child);
            // 查询所有子节点的子节点
            List<Long> childId = child.stream().map(EduUserDept::getDeptId).collect(Collectors.toList());
            result.addAll(findListByParent(childId));
        }
        return result;
    }

    /**
     * 查询直接子节点
     *
     * @param userDeptId 家校部门父节点id，不能为空
     * @return java.util.List<com.yida.data.common.core.entity.user.EduUserDept>
     * @author ZYJ
     * @date 2021/11/11 10:21
     */
    @Override
    public List<EduUserDept> findChildByParent(Long userDeptId) {
        EduUserDept condition = new EduUserDept();
        condition.setParentId(userDeptId);
        condition.setVisible(DeptVisibleTypeEnum.VISIBLE_TYPE.getValue());
        return baseMapper.selectList(Wrappers.lambdaQuery(condition).orderByDesc(EduUserDept::getOrderNum));
    }

    /**
     * 向下查询指定家校部门类型的家校部门数据(可查询非直接子家校部门)
     *
     * @param userDeptIdList 父节点id集合
     * @param type           子节点类型, 1表示班级，2表示年级，3表示学段，4表示校区, 默认所有直接子节点
     * @return java.util.List<com.yida.data.common.core.entity.user.EduUserDept>
     * @author ZYJ
     * @date 2021/11/11 10:28
     */
    @Override
    public List<EduUserDept> findChildByParentAndType(List<Long> userDeptIdList, Integer type) {
        List<EduUserDept> result = list(Wrappers.<EduUserDept>lambdaQuery().in(EduUserDept::getParentId, userDeptIdList)
            .eq(EduUserDept::getDeptType, type)
            .eq(EduUserDept::getVisible, DeptVisibleTypeEnum.VISIBLE_TYPE.getValue())
            .orderByDesc(EduUserDept::getOrderNum));
        if (CollUtil.isEmpty(result)) {
            List<EduUserDept> child = list(Wrappers.<EduUserDept>lambdaQuery()
                .in(EduUserDept::getParentId, userDeptIdList)
                .eq(EduUserDept::getVisible, DeptVisibleTypeEnum.VISIBLE_TYPE.getValue()));
            if (CollUtil.isNotEmpty(child)) {
                result = findChildByParentAndType(child.stream().map(EduUserDept::getDeptId).collect(Collectors.toList()),
                    type);
            }
        }
        return result;
    }

    @Override
    public List<CollectDataVO> findVisibleClassByUserId(Long staffId) {
        //判断当前用户角色
        CurrentUser currentUser = FebsUtil.getCurrentUser();
        List<CollectDataVO> collectDataVO = new ArrayList<>();

        EduStaffWork one = eduStaffWorkService.getOne(Wrappers.<EduStaffWork>lambdaQuery().eq(EduStaffWork::getStaffId, staffId)
            .eq(EduStaffWork::getSchoolId, currentUser.getDeptId()));

        if (ObjectUtil.isNull(one)) {
            //非驻场办公人员
            if (currentUser.getRolePerms().contains(RoleEnum.ROLE_CLASS_PRINCIPAL.getValue())) {
                //查询班主任对应管理的班级
                List<TeacherDeptVO> teacherDeptVOS = eduStaffMapper.listDeptByTeacher(staffId, 3);
                teacherDeptVOS.forEach(teacherDeptVO -> {
                    EduUserDept eduUserDeptClass = this
                        .getOne(Wrappers.lambdaQuery(new EduUserDept()).eq(EduUserDept::getDeptId, teacherDeptVO.getClassId()));

                    EduUserDept eduUserDeptGrade = this
                        .getOne(Wrappers.lambdaQuery(new EduUserDept()).eq(EduUserDept::getDeptId, teacherDeptVO.getGradeId()));
                    //根据班级查询学生信息
                    List<EduStudent> studentList = eduStudentMapper.selectList(
                        Wrappers.lambdaQuery(new EduStudent()).eq(EduStudent::getClassId, teacherDeptVO.getClassId())
                            .orderByAsc(EduStudent::getCollectType));

                    collectDataVO.add(CollectDataVO.builder().classId(eduUserDeptClass.getDeptId())
                        .className(eduUserDeptClass.getDeptName()).gradeName(eduUserDeptGrade.getDeptName())
                        .totalNum((long) studentList.size())
                        .collectNum(studentList.stream().filter(student ->
                            ObjectUtil.isNotNull(student.getAvatar()) && student.getAvatar().contains("zbz.yd-data.com")
                        ).count()).studentList(studentList).build());
                });
            }
        } else {
            //包含年级
            List<EduUserDept> gradeList = findChildByParentAndType(Collections.singletonList(one.getPDeptId()), 2);
            gradeList.forEach(eduUserDept -> {
                List<EduUserDept> childByParent = findChildByParent(eduUserDept.getDeptId());
                childByParent.forEach(eduUserDeptClass -> {
                    //根据班级查询学生信息
                    List<EduStudent> studentList = eduStudentMapper.selectList(
                        Wrappers.lambdaQuery(new EduStudent()).eq(EduStudent::getClassId, eduUserDeptClass.getDeptId())
                            .orderByAsc(EduStudent::getCollectType));
                    collectDataVO.add(CollectDataVO.builder().classId(eduUserDeptClass.getDeptId())
                        .className(eduUserDeptClass.getDeptName())
                        .gradeName(eduUserDept.getDeptName())
                        .totalNum((long) studentList.size())
                        .collectNum(
                            studentList.stream().filter(
                                student -> ObjectUtil.isNotNull(student.getAvatar()) && student.getAvatar()
                                    .contains("zbz.yd-data.com"))
                                .count())
                        .studentList(studentList)
                        .build());
                });
            });
        }
        return collectDataVO;
    }

    @Override
    public List<ClassAttendanceDataVO> findClassAttendanceByUserId(Long staffId, LocalDate date) {

        List<ClassAttendanceDataVO> returnList = new ArrayList<>();
        //判断当前用户角色
        CurrentUser currentUser = FebsUtil.getCurrentUser();
        //取缓存
        List<Object> classAttendanceDataVOList = redisService
            .lGet(CachePrefixConstant.STAFF_MANGE_DEPT + staffId, 0L, -1L);

//        log.info("缓存数据【{}】", classAttendanceDataVOList);

        if (CollUtil.isEmpty(classAttendanceDataVOList)) {
            classAttendanceDataVOList = new ArrayList<>();
            //宿管
            List<EduDormitory> eduDormitoryList = remoteDormitoryService.listDormByMaster(staffId)
                .getData();
            if (CollUtil.isNotEmpty(eduDormitoryList)) {
                for (EduDormitory dormitory : eduDormitoryList) {
                    classAttendanceDataVOList.add(
                        ClassAttendanceDataVO.builder().classId(dormitory.getId()).name(dormitory.getName()).type(1).build());
                }
            }
            //班主任、年级主任、学段主任、学区主任
            //班主任
            List<TeacherDeptVO> totalClassDeptList = new ArrayList<>();
            log.info("用户【{}】角色【{}】", staffId, currentUser.getRolePerms());

            if (currentUser.getRolePerms().contains(RoleEnum.ROLE_CLASS_PRINCIPAL.getValue())) {
                List<TeacherDeptVO> teacherDeptVOS = eduStaffMapper.listDeptByTeacher(staffId, 3);
                for (TeacherDeptVO teacherDeptVO : teacherDeptVOS) {
                    teacherDeptVO.setClassName(this.getById(teacherDeptVO.getClassId()).getDeptName());
                    teacherDeptVO.setGradeName(this.getById(teacherDeptVO.getGradeId()).getDeptName());
                    teacherDeptVO
                        .setCampusName(this.getById(teacherDeptVO.getCampusId()).getDeptName());
                    totalClassDeptList.add(teacherDeptVO);
                }
            }
            //年级主任
            if (currentUser.getRolePerms().contains(RoleEnum.ROLE_GRADE_PRINCIPAL.getValue())) {
                List<TeacherDeptVO> teacherDeptVOS = eduStaffMapper.listDeptByTeacher(staffId, 2);
                teacherDeptVOS.forEach(teacherDeptVO -> {
                    String gradeName = this.getById(teacherDeptVO.getGradeId()).getDeptName();
                    String campusName = this.getById(teacherDeptVO.getCampusId()).getDeptName();
                    List<EduUserDept> childByParent = findChildByParent(teacherDeptVO.getGradeId());
                    childByParent.forEach(eduUserDept -> {
                        TeacherDeptVO teacherDeptVO1 = new TeacherDeptVO();
                        teacherDeptVO1.setGradeId(teacherDeptVO.getGradeId());
                        teacherDeptVO1.setClassId(eduUserDept.getDeptId());
                        teacherDeptVO1
                            .setClassName(this.getById(eduUserDept.getDeptId()).getDeptName());
                        teacherDeptVO1.setGradeName(gradeName);
                        teacherDeptVO1.setCampusName(campusName);
                        totalClassDeptList.add(teacherDeptVO1);
                    });
                });
            }

            //学段主任
            if (currentUser.getRolePerms().contains(RoleEnum.ROLE_SECTION_PRINCIPAL.getValue())) {
                List<TeacherDeptVO> sectionList = eduStaffMapper.listDeptByTeacher(staffId, 5);
                sectionList.forEach(section -> {
                    String campusName = this.getById(section.getCampusId()).getDeptName();
                    List<EduUserDept> gradeList = findChildByParentAndType(Collections.singletonList(section.getSectionId()), 2);
                    gradeList.forEach(grade -> {
                        String gradeName = this.getById(grade.getDeptId()).getDeptName();
                        List<EduUserDept> classList = findChildByParent(grade.getDeptId());
                        classList.forEach(clazz -> {
                            TeacherDeptVO teacherDeptVO = new TeacherDeptVO();
                            teacherDeptVO.setGradeId(grade.getDeptId());
                            teacherDeptVO.setClassId(clazz.getDeptId());
                            teacherDeptVO
                                .setClassName(this.getById(clazz.getDeptId()).getDeptName());
                            teacherDeptVO.setGradeName(gradeName);
                            teacherDeptVO.setCampusName(campusName);
                            totalClassDeptList.add(teacherDeptVO);
                        });
                    });
                });
            }

            //学区主任
            if (currentUser.getRolePerms().contains(RoleEnum.ROLE_CAMPUS_PRINCIPAL.getValue())) {
                List<TeacherDeptVO> campusList = eduStaffMapper.listDeptByTeacher(staffId, 1);
                campusList.forEach(campus -> {
                    String campusName = this.getById(campus.getCampusId()).getDeptName();
                    List<EduUserDept> gradeList = findChildByParentAndType(Collections.singletonList(campus.getCampusId()), 2);
                    gradeList.forEach(grade -> {
                        String gradeName = this.getById(grade.getDeptId()).getDeptName();
                        List<EduUserDept> classList = findChildByParent(grade.getDeptId());
                        classList.forEach(clazz -> {
                            TeacherDeptVO teacherDeptVO = new TeacherDeptVO();
                            teacherDeptVO.setGradeId(grade.getDeptId());
                            teacherDeptVO.setClassId(clazz.getDeptId());
                            teacherDeptVO
                                .setClassName(this.getById(clazz.getDeptId()).getDeptName());
                            teacherDeptVO.setGradeName(gradeName);
                            teacherDeptVO.setCampusName(campusName);
                            totalClassDeptList.add(teacherDeptVO);
                        });
                    });
                });
            }
            //查询学校负责人，即校领导
            List<TeacherDeptVO> schoolList = eduStaffMapper.listDeptByTeacher(staffId, 6);
            if (CollUtil.isNotEmpty(schoolList)) {
                schoolList.forEach(school -> {
                    List<EduUserDept> campusList = findChildByParentAndType(
                        Collections.singletonList(-school.getSchoolId()), 4);
                    campusList.forEach(campus -> {
                        String campusName = this.getById(campus.getDeptId()).getDeptName();
                        List<EduUserDept> gradeList = findChildByParentAndType(Collections.singletonList(campus.getDeptId()),
                            2);
                        gradeList.forEach(grade -> {
                            String gradeName = this.getById(grade.getDeptId()).getDeptName();
                            List<EduUserDept> classList = findChildByParent(grade.getDeptId());
                            classList.forEach(clazz -> {
                                TeacherDeptVO teacherDeptVO = new TeacherDeptVO();
                                teacherDeptVO.setGradeId(grade.getDeptId());
                                teacherDeptVO.setClassId(clazz.getDeptId());
                                teacherDeptVO
                                    .setClassName(this.getById(clazz.getDeptId()).getDeptName());
                                teacherDeptVO.setGradeName(gradeName);
                                teacherDeptVO.setCampusName(campusName);
                                totalClassDeptList.add(teacherDeptVO);
                            });
                        });
                    });
                });
            }

//            log.info("去重前用户所有班级：【{}】", classAttendanceDataVOList);
            if (CollUtil.isNotEmpty(totalClassDeptList)) {
                for (TeacherDeptVO teacherDeptVO : totalClassDeptList) {
                    classAttendanceDataVOList
                        .add(ClassAttendanceDataVO.builder().classId(teacherDeptVO.getClassId()).name(
                            teacherDeptVO.getCampusName() + "/" + teacherDeptVO.getGradeName() + "/" + teacherDeptVO
                                .getClassName()).type(0).build());
                }
            }
            //去重
            classAttendanceDataVOList = classAttendanceDataVOList.stream().distinct().collect(Collectors.toList());

//            log.info("去重后用户所有班级：【{}】", classAttendanceDataVOList);

            if (CollUtil.isNotEmpty(classAttendanceDataVOList)) {
                redisService.llSet(CachePrefixConstant.STAFF_MANGE_DEPT + staffId, classAttendanceDataVOList);
            }
        }
        EduStaff staff = (EduStaff) redisService.hget(STAFF_DATA, staffId.toString());
        if (ObjectUtil.isEmpty(staff)) {
            staff = eduStaffMapper.getStaff(staffId);
        }

//        AttendanceRuleCacheVO attendanceRuleCacheVO = (AttendanceRuleCacheVO) redisService
//            .hget(CachePrefixConstant.SCHOOL_RULE_DATA, staff.getSchoolId().toString());
//        if (ObjectUtil.isNull(attendanceRuleCacheVO) || CollUtil.isEmpty(attendanceRuleCacheVO.getRuleListVOList())) {
//            return new ArrayList<>();
//        }
//        RuleListVO ruleListVO = attendanceRuleCacheVO.getRuleListVOList().get(0);
//
//        List<EduAttendanceRuleTime> todayRuleTimeList = ruleListVO.getTimeList().stream()
//            .filter(r -> r.getDayOfWeek() == LocalDate.now().getDayOfWeek().getValue()).collect(
//                Collectors.toList());

//        Long ruleTimeId = todayRuleTimeList.get(0).getId();

        String ruleTimeId = "";

//        log.info("今日考勤时段ruleTimeID：【{}】", ruleTimeId);
        for (Object o : classAttendanceDataVOList) {
            //统计数据
            //默认一个规则，一个考勤时段
            ClassAttendanceDataVO classAttendanceDataVO = (ClassAttendanceDataVO) o;
            ClassAttendanceDataVO redisData = new ClassAttendanceDataVO();
            if (classAttendanceDataVO.getType() == 0) {
                redisData = (ClassAttendanceDataVO) redisService
                    .hget(CachePrefixConstant.ATTENDANCE_DORMITORY_CLASS + date,
                        classAttendanceDataVO.getClassId().toString() + ruleTimeId);
            } else {
                redisData = (ClassAttendanceDataVO) redisService
                    .hget(CachePrefixConstant.ATTENDANCE_DORMITORY_DORM + date,
                        classAttendanceDataVO.getClassId().toString() + ruleTimeId);
            }
//
//            Integer type = classAttendanceDataVO.getType();
//            List<EduStudent> studentList = new ArrayList<>();
//            if (type == 0) {
//                //班级
//                //根据班级查询学生信息
//                studentList = eduStudentMapper.selectList(
//                    Wrappers.lambdaQuery(new EduStudent()).eq(EduStudent::getClassId, classAttendanceDataVO.getClassId())
//                        .eq(EduStudent::getType, 1));
//            } else {
//                //宿舍
//                //查询宿舍总人数、异常人数
//                ListStudentDTO dto = new ListStudentDTO();
//                dto.setDormIds(Collections.singletonList(classAttendanceDataVO.getClassId()));
//                dto.setType(1);
//                studentList = eduStudentMapper.listStudent(dto);
//            }
//
//            ListResultDTO paramDto = new ListResultDTO();
//            paramDto.setDate(date);
//            paramDto.setStudentIdList(studentList.stream().map(EduStudent::getId).collect(Collectors.toList()));
//            paramDto.setType(1); //类型：0异常，1正常
//            Integer abnormalNum = 0;
//            if (CollUtil.isNotEmpty(studentList)) {
//                abnormalNum = remoteAttendanceResultService
//                    .getAbnormalStudentList(paramDto)
//                    .getData().size();
//            }
//            classAttendanceDataVO.setTotalNum(studentList.size());
//            classAttendanceDataVO.setAbnormalNum(studentList.size() - abnormalNum);
            if (ObjectUtil.isNotNull(redisData)) {
                returnList.add(redisData);
            }
        }
        return returnList;
    }

    @Override
    public List<Object> findClassAttendanceDetailByDeptId(Long deptId, Integer type, LocalDate date) {
        if (type == 0) {
            ClassAttendanceDataVO redisData = (ClassAttendanceDataVO) redisService
                .hget(CachePrefixConstant.ATTENDANCE_DORMITORY_DORM + date,
                    deptId.toString());
            if (ObjectUtil.isNull(redisData)) {
                return new ArrayList<>();
            } else {
                return redisData.getStudentList();
            }
        } else {
            ClassAttendanceDataVO redisData = (ClassAttendanceDataVO) redisService
                .hget(CachePrefixConstant.ATTENDANCE_DORMITORY_CLASS + date,
                    deptId.toString());
            if (ObjectUtil.isNull(redisData)) {
                return new ArrayList<>();
            } else {
                return redisData.getStudentList();
            }
        }

//
//        List<EduStudent> studentList = new ArrayList<>();
//        if (type == 0) {
//            //班级
//            //根据班级查询学生信息
//            ListStudentDTO dto = new ListStudentDTO();
//            dto.setClassId(deptId);
//            dto.setType(1);
//            studentList = eduStudentMapper.listStudentByCondition(dto);
////            studentList = eduStudentMapper.selectList(
////                Wrappers.lambdaQuery(new EduStudent()).eq(EduStudent::getClassId, deptId).eq(EduStudent::getType, 1)
////                    .orderByAsc(EduStudent::getCollectType));
//        } else {
//            //宿舍
//            //查询宿舍总人数、异常人数
//            ListStudentDTO dto = new ListStudentDTO();
//            dto.setDormIds(Collections.singletonList(deptId));
//            dto.setIsQueryUserDept(true);
//            dto.setType(1);
//            studentList = eduStudentMapper.listStudent(dto);
//        }
//
//        ListResultDTO paramDto = new ListResultDTO();
//        paramDto.setDate(date);
//        paramDto.setStudentIdList(studentList.stream().map(EduStudent::getId).collect(Collectors.toList()));
//        paramDto.setType(0); //类型：0异常，1正常
//
//        List<EduAttendanceResult> abnormalStudentList = remoteAttendanceResultService
//            .getAbnormalStudentList(paramDto)
//            .getData();
//
//        log.info("异常数据【{}】", abnormalStudentList);
//
//        Map<Long, List<EduAttendanceResult>> listMap = abnormalStudentList.stream()
//            .collect(Collectors.groupingBy(EduAttendanceResult::getStudentId));
//
//        for (EduStudent student : studentList) {
//            List<EduAttendanceResult> eduAttendanceResultList = listMap.get(student.getId());
//            log.info("eduAttendanceResultList========【{}】", eduAttendanceResultList);
//
//            if (CollUtil.isEmpty(eduAttendanceResultList)) {
//                student.setDormAttStatus(0);
//            } else {
//                EduAttendanceResult eduAttendanceResult = listMap.get(student.getId()).get(0);
//                if (ObjectUtil.isNotNull(eduAttendanceResult)) {
//                    if (ObjectUtil.isNull(eduAttendanceResult.getBeginStatus())) {
//                        student.setDormAttStatus(4);
//                    } else {
//                        student.setDormAttStatus(eduAttendanceResult.getBeginStatus());
//                    }
//                } else {
//                    student.setDormAttStatus(0);
//                }
//            }
//        }
//        return studentList;
    }


    @Override
    public List<EduUserDept> findChildIdByParentAndType(List<Long> userDeptIdList, Integer type, List<EduUserDept> resultList) {
        List<EduUserDept> result = list(Wrappers.<EduUserDept>lambdaQuery().in(EduUserDept::getParentId, userDeptIdList)
            .eq(ObjectUtil.isNotNull(type), EduUserDept::getDeptType, type)
            .eq(EduUserDept::getVisible, DeptVisibleTypeEnum.VISIBLE_TYPE.getValue())
            .eq(EduUserDept::getGraduatedStatus, GraduatedStatusEnum.UNDERGRADUATE_STATUS.getValue())
            .orderByDesc(EduUserDept::getOrderNum));
        if (CollUtil.isEmpty(result)) {
            List<Long> child = list(Wrappers.<EduUserDept>lambdaQuery().in(EduUserDept::getParentId, userDeptIdList)
                .eq(EduUserDept::getVisible, DeptVisibleTypeEnum.VISIBLE_TYPE.getValue())
                .eq(EduUserDept::getGraduatedStatus, GraduatedStatusEnum.UNDERGRADUATE_STATUS.getValue())
                .orderByDesc(EduUserDept::getOrderNum))
                .stream().map(EduUserDept::getDeptId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(child)) {
                findChildIdByParentAndType(child, type, resultList);
            }
        } else {
            resultList.addAll(result);
        }
        return resultList;
    }

    /**
     * 根据家校部门id查询所属学校
     *
     * @param userDeptId 根据家校部门id查询所属学校
     * @return com.yida.data.common.core.entity.system.Dept
     * @author ZYJ
     * @date 2021/11/11 10:53
     */
    @Override
    public Dept findSchoolByDept(Long userDeptId) {
        Long schoolId = this.getById(userDeptId).getSchoolId();
        return this.remoteDeptService.getInfoById(schoolId).getData();
    }

    /**
     * 查询家校部门
     *
     * @param request     分页请求
     * @param dept        查询条件
     * @param includeType 是否包含班级 {@link IncludeTypeEnum}
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @author ZYJ
     * @date 2021/11/11 10:57
     */
    @Override
    public Map<String, Object> findDeptList(QueryRequest request, EduUserDept dept, String includeType) {
        Map<String, Object> result = new HashMap<>(16);
        try {
            List<EduUserDept> deptList = listUserDept(dept, request, includeType);
            List<UserDeptTree> trees = new ArrayList<>();
            buildTrees(trees, deptList, true);
            List<? extends Tree<?>> deptTree = TreeUtil.build(trees);

            result.put(PageConstant.ROWS, deptTree);
            result.put(PageConstant.TOTAL, deptList.size());
        } catch (Exception e) {
            log.error("获取家校部门列表失败", e);
            result.put(PageConstant.ROWS, null);
            result.put(PageConstant.TOTAL, 0);
        }
        return result;
    }

    /**
     * 查询家校部门集合数据
     *
     * @param dept        查询条件
     * @param request     分页、排序条件
     * @param includeType 是否包含班级 {@link IncludeTypeEnum}
     * @return java.util.List<com.yida.data.common.core.entity.user.EduUserDept>
     * @author ZYJ
     * @date 2021/11/11 11:06
     */
    public List<EduUserDept> listUserDept(EduUserDept dept, QueryRequest request, String includeType) {
        // 登陆用户
        CurrentUser currentUser = FebsUtil.getCurrentUser();
        Objects.requireNonNull(currentUser);
        // 需要根据当前角色判断登陆需要查询的数据
        RoleEnum roleEnum = RoleUtil.getMaxRole(currentUser);

        // 学校集合
        List<Dept> schoolList = new ArrayList<>();
        // 学校负责人
        if (RoleEnum.ROLE_SCHOOL_PRINCIPAL.equals(roleEnum)) {
            schoolList.add(this.remoteDeptService.getInfoById(currentUser.getDeptId()).getData());
        } else if (RoleEnum.ROLE_ADMIN.equals(roleEnum)) {
            // 超级管理员
            schoolList.addAll(this.remoteDeptService.listSchoolBySchoolType("").getData());
        }
        QueryWrapper<EduUserDept> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EduUserDept::getVisible, DeptVisibleTypeEnum.VISIBLE_TYPE.getValue());
        if (org.springframework.util.CollectionUtils.isEmpty(schoolList)) {
            log.error("登陆用户获取学校信息错误: {}", currentUser);
            throw new FebsException(ResultMsgType.LOGIN_INFO_ERROR.getValue());
        }
        queryWrapper.lambda().in(EduUserDept::getSchoolId, schoolList.stream().map(Dept::getDeptId).collect(Collectors.toList()));
        if (StringUtils.isNotBlank(dept.getDeptName())) {
            queryWrapper.lambda().like(EduUserDept::getDeptName, dept.getDeptName());
        }
        // 判断是否查询班级数据
        if (IncludeTypeEnum.NOT_INCLUDE_TYPE.getType().equals(includeType)) {
            queryWrapper.lambda().ne(EduUserDept::getDeptType, UserDeptTypeEnum.CLASS_TYPE.getValue());
        }
        SortUtil.handleWrapperSort(request, queryWrapper, "orderNum", FebsConstant.ORDER_DESC, true);

        // 返回的家校部门数据
        List<EduUserDept> list = new ArrayList<>();
        // 封装学校数据
        schoolList.forEach(school -> {
            EduUserDept eduUserDept = new EduUserDept();
            BeanUtils.copyProperties(school, eduUserDept);
            // 此处给学校id添加负号，方便家校部门树的展示
            eduUserDept.setDeptId(-school.getDeptId());
            eduUserDept.setSchoolId(school.getDeptId());
            eduUserDept.setParentId(null);

            list.add(eduUserDept);
        });
        // 查询家校部门数据
        List<EduUserDept> userDeptList = this.baseMapper.selectList(queryWrapper);
        list.addAll(userDeptList);
        return list;
    }

    /**
     * 封装家校部门树
     *
     * @param trees          家校部门树
     * @param deptList       家校部门集合
     * @param schoolDisabled 学校节点是否禁用
     * @author ZYJ
     * @date 2021/11/11 11:05
     */
    private void buildTrees(List<UserDeptTree> trees, List<EduUserDept> deptList, boolean schoolDisabled) {
        deptList.forEach(dept -> {
            UserDeptTree tree = new UserDeptTree();
            // 判断是否禁用节点
            if (DeptTypeEnum.SCHOOL_TYPE.getValue().equals(dept.getDeptType())) {
                tree.setDisabled(schoolDisabled);
            }
            tree.setId(dept.getDeptId().toString());
            tree.setParentId(dept.getParentId() != null ? dept.getParentId().toString() : null);
            tree.setLabel(dept.getDeptName());
            tree.setOrderNum(dept.getOrderNum());
            tree.setWxId(dept.getWxId());
            tree.setType(dept.getDeptType());
            tree.setParentWxId(dept.getParentWxId());
            tree.setIcon(dept.getIcon());
            tree.setCreateDate(dept.getCreateDate());
            tree.setSchoolId(dept.getSchoolId());
            tree.setSectionType(dept.getSectionType());
            trees.add(tree);
        });
    }

    /**
     * 家校部门树
     *
     * @param deptId 根节点Id
     * @return java.util.List
     * @author ZYJ
     * @date 2021/11/11 13:40
     */
    @Override
    public List getUserDeptTree(Long deptId) {

        // 返回的树结构
        List<EduUserDept> allDeptList = new ArrayList<>();
        // 根节点集合
        List<Long> rootIdList = new ArrayList<>();
        // 登陆用户
        CurrentUser currentUser = FebsUtil.getCurrentUser();
        Objects.requireNonNull(currentUser);

        if (Objects.nonNull(deptId)) {
            // 判断是否是学校
            Dept school = this.remoteDeptService.getInfoById(deptId).getData();
            if (Objects.nonNull(school)) {
                EduUserDept eduUserDept = new EduUserDept();
                BeanUtils.copyProperties(school, eduUserDept);
                // 此处给学校id添加负号，方便家校部门树的展示
                eduUserDept.setDeptId(-school.getDeptId());
                eduUserDept.setSchoolId(school.getDeptId());
                eduUserDept.setParentId(null);
                allDeptList.add(eduUserDept);
                rootIdList.add(-deptId);
            } else {
                // 添加根节点
                EduUserDept root = this.getById(deptId);
                if (root.getParentId() != null) {
                    root.setParentId(null);
                    root.setParentWxId(null);
                }
                allDeptList.add(root);
                rootIdList.add(deptId);
            }
        } else {
            // 需要根据当前角色判断登陆需要查询的数据
            RoleEnum roleEnum = RoleUtil.getMaxRole(currentUser);
            // 学校集合
            List<Dept> schoolList = new ArrayList<>();
            // 学校负责人
            if (RoleEnum.ROLE_SCHOOL_PRINCIPAL.equals(roleEnum)) {
                schoolList.add(this.remoteDeptService.getInfoById(currentUser.getDeptId()).getData());
            } else if (RoleEnum.ROLE_ADMIN.equals(roleEnum)) {
                // 超级管理员
                schoolList.addAll(this.remoteDeptService.listSchoolBySchoolType("").getData());
            }
            // 封装学校数据
            schoolList.forEach(school -> {
                EduUserDept eduUserDept = new EduUserDept();
                BeanUtils.copyProperties(school, eduUserDept);
                // 此处给学校id添加负号，方便家校部门树的展示
                eduUserDept.setDeptId(-school.getDeptId());
                eduUserDept.setSchoolId(school.getDeptId());
                eduUserDept.setParentId(null);
                allDeptList.add(eduUserDept);
            });
            rootIdList = schoolList.stream().map(x -> -x.getDeptId()).collect(Collectors.toList());
        }
        // 循环查询子节点
        allDeptList.addAll(findListByParent(rootIdList));
        List<UserDeptTree> trees = new ArrayList<>();
        buildTrees(trees, allDeptList, false);
        return TreeUtil.build(trees);
    }

    @Override
    public List getUserDeptTree(List<Long> deptIds) {
        // 返回的树结构
        List<EduUserDept> allDeptList = new ArrayList<>();
        // 根节点集合
        List<Long> rootIdList = new ArrayList<>();

        if (CollUtil.isNotEmpty(deptIds)) {
            for (Long deptId : deptIds) {
                // 添加根节点
                EduUserDept root = this.getById(deptId);
                if (ObjectUtil.isNotNull(root)) {
                    if (root.getParentId() != null) {
                        root.setParentId(null);
                        root.setParentWxId(null);
                    }
                    allDeptList.add(root);
                    rootIdList.add(deptId);
                }
            }
        }
        // 循环查询子节点
        allDeptList.addAll(findListByParent(rootIdList));
        List<UserDeptTree> trees = new ArrayList<>();
        buildTrees(trees, allDeptList, false);
        return TreeUtil.build(trees);
    }

    /**
     * 根据各层名称查询班级信息
     *
     * @param schoolId    学校id
     * @param campusName  学期名称
     * @param sectionName 学段名称
     * @param gradeName   年级名称
     * @param className   班级名称
     * @return java.util.Map<java.lang.String, com.yida.data.common.core.entity.user.EduUserDept>
     * @author ZYJ
     * @date 2021/11/11 13:51
     */
    @Override
    public Map<String, EduUserDept> findClassInfoByName(Long schoolId, String campusName, String sectionName,
        String gradeName, String className) {
        Map<String, EduUserDept> res = new HashMap<>(16);
        EduUserDept campus = this.getOne(Wrappers.lambdaQuery(new EduUserDept())
            .eq(EduUserDept::getSchoolId, schoolId)
            .eq(EduUserDept::getDeptType, UserDeptTypeEnum.CAMPUS_TYPE.getValue())
            .eq(EduUserDept::getDeptName, campusName));
        EduUserDept section = null;
        EduUserDept grade = null;
        EduUserDept clazz = null;
        if (Objects.nonNull(campus) && StringUtils.isNotBlank(sectionName)) {
            section = this.getOne(Wrappers.lambdaQuery(new EduUserDept())
                .eq(EduUserDept::getParentId, campus.getDeptId())
                .eq(EduUserDept::getDeptName, sectionName));
        }
        if (Objects.nonNull(section) && StringUtils.isNotBlank(gradeName)) {
            grade = this.getOne(Wrappers.lambdaQuery(new EduUserDept())
                .eq(EduUserDept::getParentId, section.getDeptId())
                .eq(EduUserDept::getDeptName, gradeName));
        }
        if (Objects.nonNull(grade) && StringUtils.isNotBlank(className)) {
            clazz = this.getOne(Wrappers.lambdaQuery(new EduUserDept())
                .eq(EduUserDept::getParentId, grade.getDeptId())
                .eq(EduUserDept::getDeptName, className));
        }
        res.put("campus", campus);
        res.put("section", section);
        res.put("grade", grade);
        res.put("class", clazz);
        return res;
    }

    /**
     * 新增学区信息(包含学段、年级和班级)
     *
     * @param saveCampusDTO 保存校区数据请求类
     * @author ZYJ
     * @date 2021/11/17 11:10
     */
    @Override
    public void addCampus(SaveCampusDTO saveCampusDTO) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // 判断校区名称是否存在
        List<EduUserDept> list = this.list(Wrappers.lambdaQuery(new EduUserDept())
            .eq(EduUserDept::getParentId, -saveCampusDTO.getParentId())
            .eq(EduUserDept::getDeptName, saveCampusDTO.getDeptName())
            .eq(EduUserDept::getSchoolId, saveCampusDTO.getSchoolId()));
        if (CollectionUtils.isNotEmpty(list)) {
            throw new FebsException("该校区名称已存在！请重新输入");
        }
        // 封装校区数据
        EduUserDept campus = EduUserDept.builder()
            .deptName(saveCampusDTO.getDeptName())
            // 校区此处取学校部门id的相反数, 便于树形结构展示
            .parentId(-saveCampusDTO.getParentId())
            .schoolId(saveCampusDTO.getSchoolId())
            .createDate(LocalDateTime.now())
            .deptType(UserDeptTypeEnum.CAMPUS_TYPE.getValue())
            // 校区的上级微信id为1
            .parentWxId(1L)
            .build();
        // 判断学校是否绑定了企业微信
        boolean bindFlag = false;
        // 判断学校是否绑定了大华
        boolean bindDaHuaFlag = false;
        EduApp eduApp = null;
        // 保存企业微信校区部门数据
        Dept school = this.remoteDeptService.getInfoById(saveCampusDTO.getSchoolId()).getData();
        if (Objects.nonNull(school)) {
            // 学校绑定了企业微信
            if (school.getSchoolType().contains(Dept.TYPE_QYWX)) {
                bindFlag = true;
                eduApp = appMapper.selectOne(Wrappers.lambdaQuery(new EduApp()).eq(EduApp::getDeptId,
                    school.getDeptId()).eq(EduApp::getCode, AppConstant.CONTACT_SCHOOL));
                if (eduApp != null) {
                    Long wxId = wxUtil.createUserDept(wxUtil.getAccessToken(eduApp.getWxCorpId(),
                        eduApp.getWxSecret()), campus);
                    campus.setWxId(wxId);
                }
            }
            // 学校绑定了大华
            if (school.getSchoolType().contains(Dept.TYPE_DAHUA)) {
                bindDaHuaFlag = true;
                campus.setDaHuaId(DaHuaUtil.addDept(school.getDahuaId(), campus.getDeptName()).getStr("id"));
            }
        }
        // 保存本地校区数据
        this.save(campus);
        boolean finalBindFlag = bindFlag;
        boolean finalBindDaHuaFlag = bindDaHuaFlag;
        EduApp finalEduApp = eduApp;

        // 循环保存学段数据
        for (SectionDTO sectionDTO : saveCampusDTO.getSectionList()) {
            sectionDTO.setSchoolId(saveCampusDTO.getSchoolId());
            sectionDTO.setParentId(campus.getDeptId());
            sectionDTO.setParentWxId(campus.getWxId());
            sectionDTO.setParentDaHuaId(campus.getDaHuaId());

            this.addSection(sectionDTO, false, finalBindFlag, finalEduApp, finalBindDaHuaFlag);
        }
        stopWatch.stop();
        log.error("批量创建家校部门完成！共耗时=================: {}", stopWatch.getTotalTimeSeconds() + "秒");
    }

    /**
     * 新增学段信息(包含年级和班级)
     *
     * @param sectionDTO      保存学段数据请求类
     * @param needCheckSchool 是否需要再次查询学校相关数据
     * @param bindFlag        学校是否绑定企业微信
     * @param eduApp          企业微信应用信息
     * @param bindDaHuaFlag   学校是否绑定大华
     * @author ZYJ
     * @date 2021/11/18 14:00
     */
    @Override
    public void addSection(SectionDTO sectionDTO, boolean needCheckSchool,
        boolean bindFlag, EduApp eduApp, boolean bindDaHuaFlag) {
        // 判断学段名称是否存在
        List<EduUserDept> list = this.list(Wrappers.lambdaQuery(new EduUserDept())
            .eq(EduUserDept::getParentId, sectionDTO.getParentId())
            .eq(EduUserDept::getDeptName, sectionDTO.getDeptName())
            .eq(EduUserDept::getSchoolId, sectionDTO.getSchoolId()));
        if (CollectionUtils.isNotEmpty(list)) {
            throw new FebsException("该学段名称[" + sectionDTO.getDeptName() + "]已存在！请重新选择或输入自定义学段名称");
        }
        // 封装学段数据
        EduUserDept section = EduUserDept.builder()
            .deptName(sectionDTO.getDeptName())
            .parentId(sectionDTO.getParentId())
            .schoolId(sectionDTO.getSchoolId())
            .createDate(LocalDateTime.now())
            .deptType(UserDeptTypeEnum.SECTION_TYPE.getValue())
            // 校区微信id
            .parentWxId(sectionDTO.getParentWxId())
            .sectionType(sectionDTO.getType())
            .build();
        // 设置排序
        if (!SectionTypeEnum.CUSTOM_TYPE.getValue().equals(sectionDTO.getType())) {
            section.setOrderNum(SortUtil.getOrderNumber(Integer.valueOf(sectionDTO.getType()), -1000));
        }

        // 保存企业微信学段部门数据
        if (needCheckSchool) {
            Dept school = this.remoteDeptService.getInfoById(sectionDTO.getSchoolId()).getData();
            if (Objects.nonNull(school)) {
                // 学校绑定了企业微信
                if (school.getSchoolType().contains(Dept.TYPE_QYWX)) {
                    bindFlag = true;
                    eduApp = appMapper.selectOne(Wrappers.lambdaQuery(new EduApp()).eq(EduApp::getDeptId,
                        school.getDeptId()).eq(EduApp::getCode, AppConstant.CONTACT_SCHOOL));
                }
                // 学校绑定了大华
                if (school.getSchoolType().contains(Dept.TYPE_DAHUA)) {
                    bindDaHuaFlag = true;
                }
            }
        }
        boolean finalBindFlag = bindFlag;
        EduApp finalEduApp = eduApp;
        boolean finalBindDaHuaFlag = bindDaHuaFlag;

        // 调用企业微信
        if (finalBindFlag && Objects.nonNull(finalEduApp)) {
            Long wxId = wxUtil.createUserDept(wxUtil.getAccessToken(eduApp.getWxCorpId(), eduApp.getWxSecret()), section);
            section.setWxId(wxId);
        }
        // 调用大华api
        if (finalBindDaHuaFlag) {
            section.setDaHuaId(DaHuaUtil.addDept(sectionDTO.getParentDaHuaId(), section.getDeptName()).getStr("id"));
        }
        this.save(section);

        // 查询对应学段的标准年级
        List<EduUserDeptStandardGrade> eduUserDeptStandardGradeList =
            this.eduUserDeptStandardGradeMapper.selectList(Wrappers.lambdaQuery(new EduUserDeptStandardGrade())
                .eq(EduUserDeptStandardGrade::getType, sectionDTO.getType())
                .orderByAsc(EduUserDeptStandardGrade::getOrderNumber)
                .orderByAsc(EduUserDeptStandardGrade::getId)
                .last("limit " + sectionDTO.getDefaultGradeValue()));
        // 循环保存年级数据
        eduUserDeptStandardGradeList.forEach(standardGrade -> {
            // 封装年级数据
            EduUserDept grade = EduUserDept.builder()
                .deptName(getGradeName(sectionDTO.getType(), standardGrade.getStandardGradeAbbreviation(), null))
                .parentId(section.getDeptId())
                .schoolId(sectionDTO.getSchoolId())
                .createDate(LocalDateTime.now())
                .deptType(UserDeptTypeEnum.GRADE_TYPE.getValue())
                .standardGradeValue(standardGrade.getStandardGradeValue())
                .orderNum(SortUtil.getOrderNumber(standardGrade.getStandardGradeValue(), -1000))
                // 学段微信id
                .parentWxId(section.getWxId())
                .build();
            // 调用企业微信
            if (finalBindFlag && Objects.nonNull(finalEduApp)) {
                Long wxId = wxUtil.createUserDept(wxUtil.getAccessToken(finalEduApp.getWxCorpId(), finalEduApp.getWxSecret()),
                    grade);
                grade.setWxId(wxId);
            }
            // 调用大华api
            if (finalBindDaHuaFlag) {
                grade.setDaHuaId(DaHuaUtil.addDept(section.getDaHuaId(), grade.getDeptName()).getStr("id"));
            }
            this.save(grade);
            // 循环保存班级数据
            for (int i = 1; i <= sectionDTO.getDefaultClassValue(); i++) {
                // 封装班级数据
                EduUserDept classDept = EduUserDept.builder()
                    .deptName(i + "班")
                    .parentId(grade.getDeptId())
                    .schoolId(sectionDTO.getSchoolId())
                    .createDate(LocalDateTime.now())
                    .deptType(UserDeptTypeEnum.CLASS_TYPE.getValue())
                    .orderNum(SortUtil.getOrderNumber(i, -1000))
                    // 年级微信id
                    .parentWxId(grade.getWxId())
                    .build();
                // 调用企业微信
                if (finalBindFlag && Objects.nonNull(finalEduApp)) {
                    Long wxId = wxUtil.createUserDept(wxUtil.getAccessToken(finalEduApp.getWxCorpId(), finalEduApp.getWxSecret()),
                        classDept);
                    classDept.setWxId(wxId);
                }
                // 调用大华api
                if (finalBindDaHuaFlag) {
                    classDept.setDaHuaId(DaHuaUtil.addDept(grade.getDaHuaId(), classDept.getDeptName()).getStr("id"));
                }
                this.save(classDept);
            }
        });

        updateSchoolClassData(sectionDTO.getSchoolId());
    }

    /**
     * 新增年级信息(包含班级)
     *
     * @param saveGradeDTO 保存年级数据请求类
     * @author ZYJ
     * @date 2021/11/19 13:48
     */
    @Override
    public void addGrade(SaveGradeDTO saveGradeDTO) {
        String deptName = getGradeName(saveGradeDTO.getSectionType(), saveGradeDTO.getDeptName(), null);
        // 判断年级名称是否存在
        List<EduUserDept> list = this.list(Wrappers.lambdaQuery(new EduUserDept())
            .eq(EduUserDept::getParentId, saveGradeDTO.getParentId())
            .eq(EduUserDept::getDeptName, deptName)
            .eq(EduUserDept::getSchoolId, saveGradeDTO.getSchoolId()));
        if (CollectionUtils.isNotEmpty(list)) {
            throw new FebsException("该年级名称[" + deptName + "]已存在！请重新选择或输入自定义学段名称");
        }
        // 封装年级数据
        EduUserDept grade = EduUserDept.builder()
            .deptName(deptName)
            .parentId(saveGradeDTO.getParentId())
            .schoolId(saveGradeDTO.getSchoolId())
            .createDate(LocalDateTime.now())
            .deptType(UserDeptTypeEnum.GRADE_TYPE.getValue())
            .standardGradeValue(saveGradeDTO.getStandardGradeValue())
            // 学段微信id
            .parentWxId(saveGradeDTO.getParentWxId())
            .build();

        // 判断学校是否绑定了企业微信
        boolean bindFlag = false;
        //  判断学校是否绑定了大华
        boolean bindDaHuaFlag = false;
        EduApp eduApp = null;
        // 保存企业微信校区年级数据
        Dept school = this.remoteDeptService.getInfoById(saveGradeDTO.getSchoolId()).getData();
        if (Objects.nonNull(school)) {
            // 学校绑定了企业微信
            if (school.getSchoolType().contains(Dept.TYPE_QYWX)) {
                bindFlag = true;
                eduApp = appMapper.selectOne(Wrappers.lambdaQuery(new EduApp()).eq(EduApp::getDeptId,
                    school.getDeptId()).eq(EduApp::getCode, AppConstant.CONTACT_SCHOOL));
                if (eduApp != null) {
                    Long wxId = wxUtil.createUserDept(wxUtil.getAccessToken(eduApp.getWxCorpId(),
                        eduApp.getWxSecret()), grade);
                    grade.setWxId(wxId);
                }
            }
            // 学校绑定了大华
            if (school.getSchoolType().contains(Dept.TYPE_DAHUA)) {
                bindDaHuaFlag = true;
                grade.setDaHuaId(DaHuaUtil.addDept(this.getById(saveGradeDTO.getParentId()).getDaHuaId(),
                    grade.getDeptName()).getStr("id"));
            }
        }
        this.save(grade);

        List<EduUserDept> classList = new ArrayList<>();
        // 循环封装班级数据
        for (int i = 1; i <= saveGradeDTO.getDefaultClassValue(); i++) {
            // 封装班级数据
            EduUserDept classDept = EduUserDept.builder()
                .deptName(i + "班")
                .parentId(grade.getDeptId())
                .schoolId(saveGradeDTO.getSchoolId())
                .createDate(LocalDateTime.now())
                .deptType(UserDeptTypeEnum.CLASS_TYPE.getValue())
                // 年级微信id
                .parentWxId(grade.getWxId())
                .build();
            // 调用企业微信
            if (bindFlag && Objects.nonNull(eduApp)) {
                Long wxId = wxUtil.createUserDept(wxUtil.getAccessToken(eduApp.getWxCorpId(),
                    eduApp.getWxSecret()), classDept);
                classDept.setWxId(wxId);
            }
            // 调用大华api
            if (bindDaHuaFlag) {
                classDept.setDaHuaId(DaHuaUtil.addDept(grade.getDaHuaId(), classDept.getDeptName()).getStr("id"));
            }
            classList.add(classDept);
        }
        // 批量保存班级数据
        this.saveBatch(classList);

        updateSchoolClassData(saveGradeDTO.getSchoolId());
    }

    /**
     * 获取创建年级的标准年级名称
     *
     * @param sectionType               学段类型 {@link SectionTypeEnum}
     * @param standardGradeAbbreviation 企业微信标准年级简称
     * @return java.lang.String
     * @author ZYJ
     * @date 2021/11/17 16:19
     */
    private String getGradeName(String sectionType, String standardGradeAbbreviation, Integer registerYear) {
        String result;
        if (SectionTypeEnum.KINDERGARTEN_TYPE.getValue().equals(sectionType)) {
            result = standardGradeAbbreviation;
        } else {
            result = standardGradeAbbreviation + (Objects.nonNull(registerYear) ? registerYear + "级" : "");
        }
        return result;
    }

    /**
     * 页面添加家校部门
     *
     * @param addUserDeptDTO 添加家校部门请求类
     * @author ZYJ
     * @date 2021/11/19 16:28
     */
    @Override
    public void addUserDept(AddUserDeptDTO addUserDeptDTO) {
        // 判断家校部门名称是否存在
        List<EduUserDept> list = this.list(Wrappers.lambdaQuery(new EduUserDept())
            .eq(EduUserDept::getParentId, addUserDeptDTO.getParentId())
            .eq(EduUserDept::getDeptName, addUserDeptDTO.getDeptName())
            .eq(EduUserDept::getSchoolId, addUserDeptDTO.getSchoolId()));
        if (CollectionUtils.isNotEmpty(list)) {
            throw new FebsException("该部门名称在当前节点下已存在！请重新输入");
        }
        // 封装班级数据
        EduUserDept eduUserDept = EduUserDept.builder()
            .deptName(addUserDeptDTO.getDeptName())
            .parentId(addUserDeptDTO.getParentId())
            .parentWxId(addUserDeptDTO.getParentWxId())
            .deptType(addUserDeptDTO.getDeptType())
            .schoolId(addUserDeptDTO.getSchoolId())
            .createDate(LocalDateTime.now())
            .build();
        // 判断学校绑定状态
        Dept school = this.remoteDeptService.getInfoById(addUserDeptDTO.getSchoolId()).getData();
        if (Objects.nonNull(school)) {
            // 学校绑定了企业微信
            if (school.getSchoolType().contains(Dept.TYPE_QYWX)) {
                EduApp eduApp = appMapper.selectOne(Wrappers.lambdaQuery(new EduApp()).eq(EduApp::getDeptId,
                    school.getDeptId()).eq(EduApp::getCode, AppConstant.CONTACT_SCHOOL));
                if (eduApp != null) {
                    Long wxId = wxUtil.createUserDept(wxUtil.getAccessToken(eduApp.getWxCorpId(), eduApp.getWxSecret()),
                        eduUserDept);
                    eduUserDept.setWxId(wxId);
                }
            }
            // 学校绑定了大华
            if (school.getSchoolType().contains(Dept.TYPE_DAHUA)) {
                String parentDaHuaId;
                if (UserDeptTypeEnum.CAMPUS_TYPE.getValue().equals(addUserDeptDTO.getDeptType())) {
                    parentDaHuaId = school.getDahuaId();
                } else {
                    parentDaHuaId = this.getById(addUserDeptDTO.getParentId()).getDaHuaId();
                }
                eduUserDept.setDaHuaId(DaHuaUtil.addDept(parentDaHuaId, eduUserDept.getDeptName()).getStr("id"));
            }
        }
        this.save(eduUserDept);

        updateSchoolClassData(addUserDeptDTO.getSchoolId());
    }

    /**
     * 编辑家校部门
     *
     * @param editUserDeptDTO 编辑家校部门请求类
     * @author ZYJ
     * @date 2021/11/17 17:27
     */
    @Override
    public void editUserDept(EditUserDeptDTO editUserDeptDTO) {
        // 判断家校部门名称是否存在
        List<EduUserDept> list = this.list(Wrappers.lambdaQuery(new EduUserDept())
            .ne(EduUserDept::getDeptId, editUserDeptDTO.getDeptId())
            .eq(EduUserDept::getParentId, editUserDeptDTO.getParentId())
            .eq(EduUserDept::getDeptName, editUserDeptDTO.getDeptName())
            .eq(EduUserDept::getSchoolId, editUserDeptDTO.getSchoolId()));
        if (CollectionUtils.isNotEmpty(list)) {
            throw new FebsException("该部门名称在当前节点下已存在！请重新输入");
        }
        EduUserDept eduUserDept = EduUserDept.builder()
            .deptId(editUserDeptDTO.getDeptId())
            .deptName(editUserDeptDTO.getDeptName())
            .wxId(this.getById(editUserDeptDTO.getDeptId()).getWxId())
            .updateDate(LocalDateTime.now())
            .build();
        // 判断学校绑定状态
        Dept school = this.remoteDeptService.getInfoById(editUserDeptDTO.getSchoolId()).getData();
        if (Objects.nonNull(school)) {
            // 学校绑定了企业微信
            if (school.getSchoolType().contains(Dept.TYPE_QYWX)) {
                EduApp eduApp = appMapper.selectOne(Wrappers.lambdaQuery(new EduApp()).eq(EduApp::getDeptId,
                    school.getDeptId()).eq(EduApp::getCode, AppConstant.CONTACT_SCHOOL));
                if (eduApp != null) {
                    wxUtil.updateUserDept(wxUtil.getAccessToken(eduApp.getWxCorpId(), eduApp.getWxSecret()), eduUserDept);
                }
            }
            // 学校绑定了大华
            if (school.getSchoolType().contains(Dept.TYPE_DAHUA)) {
                // 修改的部门
                EduUserDept now = this.getById(eduUserDept.getDeptId());
                String parentDaHuaId;
                if (UserDeptTypeEnum.CAMPUS_TYPE.getValue().equals(now.getDeptType())) {
                    parentDaHuaId = school.getDahuaId();
                } else {
                    parentDaHuaId = this.getById(now.getParentId()).getDaHuaId();
                }
                DaHuaUtil.updateDept(now.getDaHuaId(), parentDaHuaId,
                    eduUserDept.getDeptName());
            }
        }
        this.saveOrUpdate(eduUserDept);

        updateSchoolClassData(editUserDeptDTO.getSchoolId());
    }

    /**
     * 批量删除家校部门
     *
     * @param deptIds  家校部门id字符串
     * @param schoolId 学校id
     * @author ZYJ
     * @date 2021/11/19 17:44
     */
    @Override
    public void deleteUserDeptBatch(String deptIds, Long schoolId) {
        String[] ids = deptIds.split(",");
        if (ArrayUtils.isNotEmpty(ids)) {

            boolean bindFlag = false;
            boolean bindDaHuaFlag = false;
            EduApp eduApp = null;
            // 判断学校绑定状态
            Dept school = this.remoteDeptService.getInfoById(schoolId).getData();
            if (Objects.nonNull(school)) {
                // 学校绑定了企业微信
                if (school.getSchoolType().contains(Dept.TYPE_QYWX)) {
                    bindFlag = true;
                    eduApp = appMapper.selectOne(Wrappers.lambdaQuery(new EduApp()).eq(EduApp::getDeptId,
                        school.getDeptId()).eq(EduApp::getCode, AppConstant.CONTACT_SCHOOL));
                }
                // 学校绑定了大华
                if (school.getSchoolType().contains(Dept.TYPE_DAHUA)) {
                    bindDaHuaFlag = true;
                }
            }
            for (String deptId : ids) {
                // 查询是否有子节点
                List<EduUserDept> list = this.list(Wrappers.lambdaQuery(new EduUserDept())
                    .eq(EduUserDept::getParentId, deptId));
                if (CollectionUtils.isNotEmpty(list)) {
                    throw new FebsException("该节点下还包含子部门，无法删除！");
                }
                // TODO 2021/11/20 此处需要判断节点下是否还包含有成员
                // 调用企业微信删除家校部门接口
                if (bindFlag && Objects.nonNull(eduApp)) {
                    wxUtil.deleteUserDept(wxUtil.getAccessToken(eduApp.getWxCorpId(), eduApp.getWxSecret()),
                        this.getById(deptId).getWxId());
                }
                // 绑定了大华
                if (bindDaHuaFlag) {
                    DaHuaUtil.delDept(Collections.singletonList(this.getById(deptId).getDaHuaId()));
                }
                // 删除本地家校部门
                this.removeById(deptId);
            }
        }
        // 删除部门缓存
        redisService.hdel(CachePrefixConstant.USER_DEPT_DATA, ids);

        updateSchoolClassData(schoolId);
    }

    /**
     * 根据学段类型查询对应的标准年级
     *
     * @param sectionType 学段类型 {@link SectionTypeEnum}
     * @return java.util.List<com.yida.data.common.core.entity.user.EduUserDeptStandardGrade>
     * @author ZYJ
     * @date 2021/11/18 17:26
     */
    @Override
    public List<EduUserDeptStandardGrade> listStandardGradeBySectionType(String sectionType) {
        return this.eduUserDeptStandardGradeMapper.selectList(Wrappers.lambdaQuery(new EduUserDeptStandardGrade())
            .eq(EduUserDeptStandardGrade::getType, sectionType));
    }

    /**
     * 查询父级部门是否存在
     *
     * @param deptIdList 家校部门id集合
     * @param parentWxId 家校部门父级企业微信id
     * @return com.yida.data.common.core.entity.user.EduUserDept
     * @author ZYJ
     * @date 2021/11/22 17:53
     */
    @Override
    public EduUserDept getUserDeptByDeptAndWx(List<Long> deptIdList, Long parentWxId) {
        EduUserDept exist = this.getOne(Wrappers.lambdaQuery(new EduUserDept())
            .in(EduUserDept::getParentId, deptIdList)
            .eq(EduUserDept::getVisible, DeptVisibleTypeEnum.VISIBLE_TYPE.getValue())
            .eq(EduUserDept::getWxId, parentWxId));
        if (Objects.isNull(exist)) {
            List<EduUserDept> deptList = list(Wrappers.lambdaQuery(new EduUserDept())
                .in(EduUserDept::getParentId, deptIdList));
            if (CollUtil.isNotEmpty(deptList)) {
                List<Long> deptIds = deptList.stream().map(EduUserDept::getDeptId).collect(Collectors.toList());
                exist = getUserDeptByDeptAndWx(deptIds, parentWxId);
            }
        }
        return exist;
    }

    /**
     * 企业微信创建家校部门
     *
     * @param userDept 创建的家校部门信息
     * @author ZYJ
     * @date 2021/11/22 17:59
     */
    @Override
    public void createUserDept(EduUserDept userDept) {
        this.save(userDept);
    }

    /**
     * 根据学校id和班级企业微信id查询当前学校下对应的班级信息
     *
     * @param schoolId  学校id
     * @param classWxId 班级企业微信id
     * @return com.yida.data.common.core.entity.user.EduUserDept
     * @author ZYJ
     * @date 2021/11/25 16:45
     */
    @Override
    public EduUserDept getClassBySchoolAndWx(Long schoolId, Long classWxId) {
        // 查询校区
        List<EduUserDept> campusList = list(
            Wrappers.<EduUserDept>lambdaQuery().eq(EduUserDept::getParentId, -schoolId)
                .eq(EduUserDept::getDeptType, UserDeptTypeEnum.CAMPUS_TYPE.getValue()));
        List<EduUserDept> sectionList =
            list(Wrappers.<EduUserDept>lambdaQuery()
                .in(EduUserDept::getParentId, campusList.stream().map(EduUserDept::getDeptId).collect(Collectors.toList()))
                .eq(EduUserDept::getDeptType, UserDeptTypeEnum.SECTION_TYPE.getValue()));
        List<EduUserDept> gradeList =
            list(Wrappers.<EduUserDept>lambdaQuery()
                .in(EduUserDept::getParentId, sectionList.stream().map(EduUserDept::getDeptId).collect(Collectors.toList()))
                .eq(EduUserDept::getDeptType, UserDeptTypeEnum.GRADE_TYPE.getValue()));
        return getOne(Wrappers.<EduUserDept>lambdaQuery()
            .in(EduUserDept::getParentId, gradeList.stream().map(EduUserDept::getDeptId).collect(Collectors.toList()))
            .eq(EduUserDept::getWxId, classWxId));
    }

    /**
     * 根据家校部门id查询上级家校部门信息
     *
     * @param deptId 家校部门id
     * @return com.yida.data.common.core.entity.user.EduUserDept
     * @author ZYJ
     * @date 2021/11/30 10:06
     */
    @Override
    public EduUserDept getParentByDeptId(Long deptId) {
        EduUserDept eduUserDept = this.getById(deptId);
        if (ObjectUtil.isNotNull(eduUserDept.getParentId())) {
            return this.getById(eduUserDept.getParentId());
        } else {
            return null;
        }
    }

    @Override
    public List<EduUserDept> getParentListByDeptId(Long deptId) {
        List<EduUserDept> result = new ArrayList<>();
        if (ObjectUtil.isNotNull(deptId)) {
            EduUserDept currentDept = getById(deptId);
            result.add(currentDept);
            if (ObjectUtil.isNotNull(currentDept) && ObjectUtil.isNotNull(currentDept.getParentId())) {
                result.addAll(getParentListByDeptId(currentDept.getParentId()));
            }
            return result;
        } else {
            return null;
        }
    }

    /**
     * 批量保存家校部门
     *
     * @param saveDeptList 批量保存的家校部门数据
     * @author ZYJ
     * @date 2021/11/30 10:20
     */
    @Override
    public void updateBatchUserDept(List<EduUserDept> saveDeptList) {
        this.updateBatchById(saveDeptList);
    }

    /**
     * 递归删除家校部门
     *
     * @param deleteUserDeptDTO 企业微信回调删除本地家校部门请求类
     * @author ZYJ
     * @date 2021/11/30 10:44
     */
    @Override
    public void deleteUserDeptRecur(DeleteUserDeptDTO deleteUserDeptDTO) {

        List<Long> deptIdList = deleteUserDeptDTO.getDeptIdList();
        Dept school = deleteUserDeptDTO.getSchool();

        List<EduUserDept> child = this.list(Wrappers.lambdaQuery(new EduUserDept())
            .in(EduUserDept::getParentId, deptIdList));
        // 先删除子节点
        if (CollUtil.isNotEmpty(child)) {
            deleteUserDeptRecur(DeleteUserDeptDTO.builder()
                .deptIdList(child.stream().map(EduUserDept::getDeptId).collect(Collectors.toList()))
                .school(school)
                .build());
        }
        // 删除大华部门
        if (Objects.nonNull(school) && school.getSchoolType().contains(Dept.TYPE_DAHUA)) {
            List<EduUserDept> userDeptList = this.listByIds(deptIdList);
            DaHuaUtil.delDept(userDeptList.stream().map(EduUserDept::getDaHuaId).collect(Collectors.toList()));
        }
        this.removeByIds(deptIdList);
        // 删除家校部门缓存
        redisService.hdel(CachePrefixConstant.USER_DEPT_DATA, deptIdList.stream().map(Object::toString).toArray(String[]::new));
    }

    /**
     * 同步企业微信家校部门
     *
     * @author ZYJ
     * @date 2021/11/30 13:47
     */
    @Override
    @Transactional
    public void syncUserDept(Long schoolId) {
        // 查询所有和企业微信关联的学校信息
        List<Dept> schoolList = new ArrayList<>();
        if (Objects.isNull(schoolId)) {
            // 查询所有绑定了企业微信的学校信息
            schoolList = remoteDeptService.listSchoolBySchoolType(Dept.TYPE_QYWX).getData();
        } else {
            Dept school = remoteDeptService.getInfoByIdNoPermission(schoolId).getData();
            schoolList.add(school);
        }

        if (CollectionUtils.isNotEmpty(schoolList)) {
            for (Dept school : schoolList) {
                log.info("[{}], schoolId:[{}]开始同步家校部门", school.getDeptName(), school.getDeptId());
                log.info("当前学校信息: {}", school);
                EduApp contactSchoolApp = appMapper.selectOne(Wrappers.lambdaQuery(new EduApp()).eq(EduApp::getDeptId,
                    school.getDeptId()).eq(EduApp::getCode, AppConstant.CONTACT_SCHOOL));
                // 判断学校是否绑定了大华
                boolean bindDaHuaFlag = false;
//                if (school.getSchoolType().contains(Dept.TYPE_DAHUA)) {
//                    bindDaHuaFlag = true;
//                }
                // 查询家校部门列表
                List<Map> schoolDeptList = wxUtil.listSchoolDept(wxUtil.getAccessToken(contactSchoolApp.getWxCorpId(),
                    contactSchoolApp.getWxSecret()), null);
                log.info("家校部门同步的数据: {}", schoolDeptList);
                // 企业微信id缓存
                Map<Long, Long> wxIdAndDeptIdCache = new HashMap<>();
                wxIdAndDeptIdCache.put(1L, -school.getDeptId());
                // 排序缓存
                Map<Long, Integer> wxIdAndOrderCache = new HashMap<>();
                wxIdAndOrderCache.put(1L, 0);

                for (Map dept : schoolDeptList) {
                    String deptName = dept.get("name").toString();
                    Long parentWxId = Long.valueOf(dept.get("parentid").toString());
                    Long wxId = Long.valueOf(dept.get("id").toString());
                    Integer type = Integer.valueOf(dept.get("type").toString());
                    // 排序
                    Object orderObject = dept.get("order");
                    Integer order = Objects.nonNull(orderObject) ? Integer.valueOf(String.valueOf(orderObject)) : null;

                    if (wxId == 1) {
                        continue;
                    }
                    // 判断错误数据. 放在根节点下的非校区数据不同步
                    if (parentWxId == 1 && !UserDeptTypeEnum.CAMPUS_TYPE.getValue().equals(type)) {
                        continue;
                    }

                    EduUserDept existParent = this.getOne(Wrappers.<EduUserDept>lambdaQuery()
                        .eq(EduUserDept::getWxId, parentWxId)
                        .eq(EduUserDept::getSchoolId, school.getDeptId()));
                    if (Objects.isNull(existParent) && parentWxId != 1) {
                        log.error("没有父级部门数据: {}", parentWxId);
                        continue;
                    }
                    // 查询已存在的数据
                    log.info("家校部门查询已存在的数据, wxId: {}, parentWxId: {}, schoolId: {}",
                        wxId, parentWxId, school.getDeptId());
                    Long parentId = wxIdAndDeptIdCache.get(parentWxId);
                    EduUserDept exist = this.getOne(Wrappers.<EduUserDept>lambdaQuery()
                        .eq(EduUserDept::getWxId, wxId)
                        .eq(EduUserDept::getParentWxId, parentWxId)
                        .eq(EduUserDept::getSchoolId, school.getDeptId()));
                    // 进行修改或保存
                    if (exist == null) {
                        exist = new EduUserDept();
                        exist.setCreateDate(LocalDateTime.now());
                        if (UserDeptTypeEnum.SECTION_TYPE.getValue().equals(type)) {
                            // 学段判断, 根据名称获取学段类型
                            try {
                                SectionTypeEnum sectionTypeEnum = EnumUtils.valueOf(SectionTypeEnum.class, exist.getDeptName(),
                                    SectionTypeEnum.class.getMethod("getName"));
                                exist.setSectionType(Objects.nonNull(sectionTypeEnum) ?
                                    sectionTypeEnum.getValue() : SectionTypeEnum.CUSTOM_TYPE.getValue());
                            } catch (Exception e) {
                                log.error("根据名称获取学段类型失败, userDept: {}", dept, e);
                                exist.setSectionType(SectionTypeEnum.CUSTOM_TYPE.getValue());
                            }
                        }
                    } else {
                        // 设置家校部门可见
                        exist.setVisible(DeptVisibleTypeEnum.VISIBLE_TYPE.getValue());
                        exist.setUpdateDate(LocalDateTime.now());
                    }
                    // 设置排序
                    Integer oldOrder = wxIdAndOrderCache.get(parentWxId);
                    if (Objects.isNull(order) && Objects.isNull(exist.getOrderNum())) {
                        order = SortUtil.getOrderNumber(oldOrder, -1000);
                        exist.setOrderNum(order);
                    } else if (Objects.nonNull(order)) {
                        exist.setOrderNum(order);
                    }

                    exist.setParentId(parentId);
                    exist.setDeptName(deptName);
                    exist.setDeptType(type);
                    exist.setWxId(wxId);
                    exist.setParentWxId(parentWxId);
                    exist.setSchoolId(school.getDeptId());
                    // 判断家校部门类型
                    if (UserDeptTypeEnum.GRADE_TYPE.getValue().equals(type)) {
                        // 年级判断, 设置标准年级值
                        if (Objects.nonNull(dept.get("standard_grade"))) {
                            exist.setStandardGradeValue((Integer) dept.get("standard_grade"));
                        }
                        // 毕业状态
                        exist.setGraduatedStatus((Integer) dept.get("is_graduated"));
                    }
                    this.saveOrUpdate(exist);
                    wxIdAndDeptIdCache.put(wxId, exist.getDeptId());
                    wxIdAndOrderCache.put(wxId, 0);
                    wxIdAndOrderCache.put(parentWxId, oldOrder + 1);

                    Long campusId = null;
                    Long sectionId = null;
                    Long gradeId = null;
                    Long classId = null;
                    switch (exist.getDeptType()) {
                        case 1:
                            /// 班级
                            classId = exist.getDeptId();
                            gradeId = exist.getParentId();
                            // 查询学段信息
                            EduUserDept section = getParentByDeptId(gradeId);
                            sectionId = section.getDeptId();
                            campusId = section.getParentId();
                            break;
                        case 2:
                            // 年级
                            gradeId = exist.getDeptId();
                            sectionId = exist.getParentId();
                            campusId = getById(sectionId).getParentId();
                            break;
                        case 3:
                            // 学段
                            sectionId = exist.getDeptId();
                            campusId = exist.getParentId();
                            break;
                        case 4:
                            // 学区
                            campusId = exist.getDeptId();
                            break;
                        default:
                            log.error("家校部门类型错误, 部门信息:{}", dept);
                            break;
                    }
                    // 获取老师列表
                    List<Map> teacherList = (List<Map>) dept.get("department_admins");
                    log.info("teachers:{},dept:{}", teacherList, dept);
                    if (CollUtil.isNotEmpty(teacherList)) {
                        eduStaffService.dealWxTeacherChange(school.getDeptId(), campusId, sectionId, gradeId, classId,
                            teacherList, wxId);
                    }

                    // 判断是否调用大华接口
                    if (bindDaHuaFlag) {
                        // 查询当前部门
                        EduUserDept userDept = getById(exist.getDeptId());
                        log.info("当前家校部门信息: {}", userDept);
                        if (!UserDeptTypeEnum.CAMPUS_TYPE.getValue().equals(userDept.getDeptType()) &&
                            userDept.getParentId() == -school.getDeptId()) {
                            continue;
                        }
                        // 获取父级部门大华id
                        String parentDaHuaId;
//                        if (userDept.getParentId() == -school.getDeptId()) {
                        if (UserDeptTypeEnum.CAMPUS_TYPE.getValue().equals(userDept.getDeptType())) {
                            // 校区使用学校大华id
                            parentDaHuaId = school.getDahuaId();
                        } else {
                            EduUserDept parentDept = getById(userDept.getParentId());
                            parentDaHuaId = parentDept.getDaHuaId();
                            if (!UserDeptTypeEnum.CAMPUS_TYPE.getValue().equals(parentDept.getDeptType()) &&
                                parentDept.getParentId() == -school.getDeptId()) {
                                continue;
                            }
                        }

                        if (StringUtils.isNotBlank(userDept.getDaHuaId())) {
                            // 修改
                            DaHuaUtil.updateDept(userDept.getDaHuaId(), parentDaHuaId, userDept.getDeptName());
                        } else {
                            // 新增
                            userDept.setDaHuaId(DaHuaUtil.addDept(parentDaHuaId, userDept.getDeptName()).getStr("id"));
                            saveOrUpdate(userDept);
                        }
                    }
                }
            }
        }
        log.info("同步家校部门成功");
    }

    /**
     * 处理挂在学校下的家校部门
     *
     * @author ZYJ
     * @date 2021/11/30 14:10
     */
    @Override
    public void dealNoParentUserDept() {
        // 查询所有和企业微信关联的学校信息
        List<Dept> schoolList = this.remoteDeptService.listSchoolBySchoolType(Dept.TYPE_QYWX).getData();
        if (CollectionUtils.isNotEmpty(schoolList)) {
            for (Dept school : schoolList) {
                log.info("[{}]开始处理家校部门数据", school.getDeptName());
                List<EduUserDept> userDeptList = this.list(Wrappers.lambdaQuery(new EduUserDept())
                    .eq(EduUserDept::getVisible, DeptVisibleTypeEnum.INVISIBLE_TYPE.getValue())
                    .eq(EduUserDept::getParentId, -school.getDeptId())
                    .ne(EduUserDept::getDeptType, UserDeptTypeEnum.CAMPUS_TYPE.getValue()));
                for (EduUserDept userDept : userDeptList) {
                    EduUserDept parent = this.getOne(Wrappers.lambdaQuery(new EduUserDept())
                        .eq(EduUserDept::getSchoolId, school.getDeptId())
                        .eq(EduUserDept::getWxId, userDept.getParentWxId()));
                    if (Objects.nonNull(parent)) {
                        userDept.setParentId(parent.getDeptId());
                        userDept.setVisible(DeptVisibleTypeEnum.VISIBLE_TYPE.getValue());
                        this.updateById(userDept);
                    }
                }
            }
        }
    }

    /**
     * 向下获取包含的班级id
     *
     * @param deptIds 父级id集合
     * @return java.util.List<java.lang.Long>
     * @author ZYJ
     * @date 2021/11/30 15:20
     */
    @Override
    public List<Long> listClassByDept(List<Long> deptIds) {
        List<Long> result = new ArrayList<>();
        if (CollUtil.isNotEmpty(deptIds)) {
            List<EduUserDept> child = list(Wrappers.lambdaQuery(new EduUserDept())
                .eq(EduUserDept::getVisible, DeptVisibleTypeEnum.VISIBLE_TYPE.getValue())
                .in(EduUserDept::getParentId, deptIds));
            result.addAll(
                child.stream().filter(x -> UserDeptTypeEnum.CLASS_TYPE.getValue().equals(x.getDeptType()))
                    .map(EduUserDept::getDeptId).collect(Collectors.toList()));
            result.addAll(listClassByDept(
                child.stream().filter(x -> !UserDeptTypeEnum.CLASS_TYPE.getValue().equals(x.getDeptType()))
                    .map(EduUserDept::getDeptId).collect(Collectors.toList())));
        }
        return result;
    }

    /**
     * 查询班级年级等信息
     *
     * @param classId 班级id
     * @return com.yida.data.system.vo.ClassInfoVO
     * @author ZYJ
     * @date 2021/11/30 16:04
     */
    @Override
    public ClassInfoVO getClassInfo(Long classId) {
        ClassInfoVO classInfo = this.baseMapper.getClassInfo(classId);
        // 查询学校及以上信息
        SchoolClassInfoVO schoolInfo = this.remoteDeptService.getSchoolAreaInfo(classInfo.getSchoolId()).getData();
        BeanUtils.copyProperties(schoolInfo, classInfo);
        return classInfo;
    }

    @Override
    public List<Long> getUpId(List<Long> deptId) {
        List<EduUserDept> dept = listByIds(deptId);
        List<Long> ids = new ArrayList<>(deptId);
        if (CollUtil.isNotEmpty(dept)) {
            ids.add(dept.get(0).getSchoolId());
            List<Long> next = dept.stream().map(EduUserDept::getParentId).filter(x -> x > 0).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(next)) {
                ids.addAll(getUpId(next));
            }
        }
        return ids;
    }

    @Override
    public List<Long> getUpAndDownId(List<Long> deptId) {
        List<Long> ids = new ArrayList<>();
        ids.addAll(getUpId(deptId));
        ids.addAll(getDownId(deptId));
        return CollUtil.distinct(ids);
    }

    @Override
    public List<Long> getDownId(List<Long> deptId) {
        List<EduUserDept> child = list(Wrappers.lambdaQuery(new EduUserDept()).in(EduUserDept::getParentId, deptId));
        List<Long> ids = new ArrayList<>(deptId);
        if (CollUtil.isNotEmpty(child)) {
            List<Long> childId = child.stream().map(EduUserDept::getDeptId).collect(Collectors.toList());
            ids.addAll(getDownId(childId));
        }
        return ids;
    }

    @Override
    public AllDeptInfoVO findParentUp(Long deptId, Integer type) {
        AllDeptInfoVO vo = new AllDeptInfoVO();
        // 查询本级
        EduUserDept self = getById(deptId);
        while (self != null && type >= self.getDeptType()) {
            switch (self.getDeptType()) {
                case 1:
                    vo.setClassId(self.getDeptId());
                    vo.setClassName(self.getDeptName());
                    break;
                case 2:
                    vo.setGradeId(self.getDeptId());
                    vo.setGradeName(self.getDeptName());
                    break;
                case 3:
                    vo.setSectionId(self.getDeptId());
                    vo.setSectionName(self.getDeptName());
                    break;
                case 4:
                    vo.setCampusId(self.getDeptId());
                    vo.setCampusName(self.getDeptName());
                    break;
                default:
            }
            self = getById(self.getParentId());
        }
        return vo;
    }

    @Override
    public List<TeacherDeptVO> listClassByStaffId(Long staffId) {
        CurrentUser currentUser = FebsUtil.getCurrentUser();
        //取缓存
        String staffMangeClassData = (String) redisService
            .get(CachePrefixConstant.STAFF_MANGE_CLASS + staffId);

        if (ObjectUtil.isNull(staffMangeClassData)) {
            //任课老师、班主任、年级主任、学段主任、学区主任
            List<TeacherDeptVO> totalClassDeptList = new ArrayList<>();
            //任课老师
            List<TeacherDeptVO> teacherDeptVOS = eduStaffMapper.listDeptByTeacher(currentUser.getIdentityId(), 4);
            //班主任
            if (currentUser.getRolePerms().contains(RoleEnum.ROLE_CLASS_PRINCIPAL.getValue())) {
                List<TeacherDeptVO> teacherDeptVOList = eduStaffMapper.listDeptByTeacher(staffId, 3);
                teacherDeptVOS.addAll(teacherDeptVOList);
            }
            for (TeacherDeptVO teacherDeptVO : teacherDeptVOS) {
                teacherDeptVO.setClassName(this.getById(teacherDeptVO.getClassId()).getDeptName());
                teacherDeptVO.setGradeName(this.getById(teacherDeptVO.getGradeId()).getDeptName());
                teacherDeptVO.setSectionName(this.getById(teacherDeptVO.getSectionId()).getDeptName());
                teacherDeptVO.setCampusName(this.getById(teacherDeptVO.getCampusId()).getDeptName());
                Long studentNum = eduStudentMapper.selectCount(Wrappers.lambdaQuery(new EduStudent())
                    .eq(EduStudent::getClassId, teacherDeptVO.getClassId()));
                //班级人数
                teacherDeptVO.setClassStudentNum(studentNum);
                totalClassDeptList.add(teacherDeptVO);
            }

            //年级主任
            if (currentUser.getRolePerms().contains(RoleEnum.ROLE_GRADE_PRINCIPAL.getValue())) {
                List<TeacherDeptVO> teacherDeptVOList_grade = eduStaffMapper.listDeptByTeacher(staffId, 2);
                for (TeacherDeptVO teacherDeptVO : teacherDeptVOList_grade) {
                    String gradeName = this.getById(teacherDeptVO.getGradeId()).getDeptName();
                    String sectionName = this.getById(teacherDeptVO.getSectionId()).getDeptName();
                    String campusName = this.getById(teacherDeptVO.getCampusId()).getDeptName();
                    List<EduUserDept> childByParent = findChildByParent(teacherDeptVO.getGradeId());
                    for (EduUserDept eduUserDept : childByParent) {
                        TeacherDeptVO teacherDeptVO1 = new TeacherDeptVO();
                        teacherDeptVO1.setGradeId(teacherDeptVO.getGradeId());
                        teacherDeptVO1.setClassId(eduUserDept.getDeptId());
                        teacherDeptVO1
                            .setClassName(this.getById(eduUserDept.getDeptId()).getDeptName());
                        teacherDeptVO1.setGradeName(gradeName);
                        teacherDeptVO1.setSectionName(sectionName);
                        teacherDeptVO1.setCampusName(campusName);

                        Long studentNum = eduStudentMapper.selectCount(Wrappers.lambdaQuery(new EduStudent())
                            .eq(EduStudent::getClassId, eduUserDept.getDeptId()));
                        //班级人数
                        teacherDeptVO1.setClassStudentNum(studentNum);
                        totalClassDeptList.add(teacherDeptVO1);
                    }
                }
            }

            //学段主任
            if (currentUser.getRolePerms().contains(RoleEnum.ROLE_SECTION_PRINCIPAL.getValue())) {
                List<TeacherDeptVO> sectionList = eduStaffMapper.listDeptByTeacher(staffId, 5);
                for (TeacherDeptVO section : sectionList) {
                    String campusName = this.getById(section.getCampusId()).getDeptName();
                    String sectionName = this.getById(section.getSectionId()).getDeptName();
                    List<EduUserDept> gradeList = findChildByParentAndType(Collections.singletonList(section.getSectionId()), 2);
                    for (EduUserDept grade : gradeList) {
                        String gradeName = this.getById(grade.getDeptId()).getDeptName();
                        List<EduUserDept> classList = findChildByParent(grade.getDeptId());
                        for (EduUserDept clazz : classList) {
                            TeacherDeptVO teacherDeptVO = new TeacherDeptVO();
                            teacherDeptVO.setGradeId(grade.getDeptId());
                            teacherDeptVO.setClassId(clazz.getDeptId());
                            teacherDeptVO
                                .setClassName(this.getById(clazz.getDeptId()).getDeptName());
                            teacherDeptVO.setGradeName(gradeName);
                            teacherDeptVO.setCampusName(campusName);
                            Long studentNum = eduStudentMapper.selectCount(Wrappers.lambdaQuery(new EduStudent())
                                .eq(EduStudent::getClassId, clazz.getDeptId()));
                            //班级人数
                            teacherDeptVO.setClassStudentNum(studentNum);
                            totalClassDeptList.add(teacherDeptVO);
                        }
                    }
                }
            }
            //学区主任
            if (currentUser.getRolePerms().contains(RoleEnum.ROLE_CAMPUS_PRINCIPAL.getValue())) {
                List<TeacherDeptVO> campusList = eduStaffMapper.listDeptByTeacher(staffId, 1);
                for (TeacherDeptVO campus : campusList) {
                    String campusName = this.getById(campus.getCampusId()).getDeptName();
                    List<EduUserDept> gradeList = findChildByParentAndType(Collections.singletonList(campus.getCampusId()), 2);
                    for (EduUserDept grade : gradeList) {
                        String gradeName = this.getById(grade.getDeptId()).getDeptName();
                        List<EduUserDept> classList = findChildByParent(grade.getDeptId());
                        for (EduUserDept clazz : classList) {
                            TeacherDeptVO teacherDeptVO = new TeacherDeptVO();
                            teacherDeptVO.setGradeId(grade.getDeptId());
                            teacherDeptVO.setClassId(clazz.getDeptId());
                            teacherDeptVO
                                .setClassName(this.getById(clazz.getDeptId()).getDeptName());
                            teacherDeptVO.setGradeName(gradeName);
                            teacherDeptVO.setCampusName(campusName);

                            Long studentNum = eduStudentMapper.selectCount(Wrappers.lambdaQuery(new EduStudent())
                                .eq(EduStudent::getClassId, clazz.getDeptId()));
                            //班级人数
                            teacherDeptVO.setClassStudentNum(studentNum);

                            totalClassDeptList.add(teacherDeptVO);
                        }
                    }
                }
            }
            //查询学校负责人，即校领导
            List<TeacherDeptVO> schoolList = eduStaffMapper.listDeptByTeacher(staffId, 6);
            if (CollUtil.isNotEmpty(schoolList)) {
                for (TeacherDeptVO school : schoolList) {
                    List<EduUserDept> campusList = findChildByParentAndType(
                        Collections.singletonList(-school.getSchoolId()), 4);
                    for (EduUserDept campus : campusList) {
                        String campusName = this.getById(campus.getDeptId()).getDeptName();
                        List<EduUserDept> gradeList = findChildByParentAndType(Collections.singletonList(campus.getDeptId()),
                            2);
                        for (EduUserDept grade : gradeList) {
                            String gradeName = this.getById(grade.getDeptId()).getDeptName();
                            List<EduUserDept> classList = findChildByParent(grade.getDeptId());
                            for (EduUserDept clazz : classList) {
                                TeacherDeptVO teacherDeptVO = new TeacherDeptVO();
                                teacherDeptVO.setGradeId(grade.getDeptId());
                                teacherDeptVO.setClassId(clazz.getDeptId());
                                teacherDeptVO
                                    .setClassName(this.getById(clazz.getDeptId()).getDeptName());
                                teacherDeptVO.setGradeName(gradeName);
                                teacherDeptVO.setCampusName(campusName);
                                Long studentNum = eduStudentMapper.selectCount(Wrappers.lambdaQuery(new EduStudent())
                                    .eq(EduStudent::getClassId, clazz.getDeptId()));
                                //班级人数
                                teacherDeptVO.setClassStudentNum(studentNum);
                                totalClassDeptList.add(teacherDeptVO);
                            }
                        }
                    }
                }
            }
            //去重
            totalClassDeptList = totalClassDeptList.stream().distinct().collect(Collectors.toList());

            if (CollUtil.isNotEmpty(totalClassDeptList)) {
                redisService
                    .set(CachePrefixConstant.STAFF_MANGE_CLASS + staffId, JSONUtil.toJsonStr(totalClassDeptList));
            }
            return totalClassDeptList;
        } else {
            List<TeacherDeptVO> teacherDeptVOList = JSONUtil.toList(staffMangeClassData, TeacherDeptVO.class);
            return teacherDeptVOList;
        }
    }


    /**
     * 更新学校缓存班级数据信息
     *
     * @param schoolId
     */
    public void updateSchoolClassData(Long schoolId) {
        if (ObjectUtil.isNull(schoolId)) {
            return;
        }
        //查询学校下的所有班级
//        List<Object> classList = new ArrayList<>();
//        List<EduUserDept> campusList = this.findChildByParentAndType(Collections.singletonList(-schoolId), 4);
//        for (EduUserDept campus : campusList) {
//            List<EduUserDept> gradeList = this.findChildByParentAndType(Collections.singletonList(campus.getDeptId()), 2);
//            for (EduUserDept grade : gradeList) {
//                List<EduUserDept> nowList = this.findChildByParentAndType(Collections.singletonList(grade.getDeptId()), 1);
//                for (EduUserDept classDept : nowList) {
//                    classList.add(ClassAttendanceDataVO.builder().type(0).classId(classDept.getDeptId())
//                        .name(campus.getDeptName() + "/" + grade.getDeptName() + "/" + classDept
//                            .getDeptName()).build());
//                }
//            }
//        }
        redisService
            .del(CachePrefixConstant.SCHOOL_CLASS_DATA + schoolId);
    }

    @Override
    public JSONArray getGradeDistribution(Long schoolId) {
        JSONArray jsonArray = JSONUtil.createArray();
        // 查询学校总人数
        long studentNum = eduStudentMapper.selectCount(Wrappers.lambdaQuery(new EduStudent())
            .eq(EduStudent::getSchoolId, schoolId));
        // 查询年级信息
        List<EduUserDept> gradeList = list(Wrappers.lambdaQuery(new EduUserDept())
            .eq(EduUserDept::getDeptType, UserDeptTypeEnum.GRADE_TYPE.getValue())
            .eq(EduUserDept::getVisible, DeptVisibleTypeEnum.VISIBLE_TYPE.getValue())
            .eq(EduUserDept::getGraduatedStatus, GraduatedStatusEnum.UNDERGRADUATE_STATUS.getValue())
            .eq(EduUserDept::getSchoolId, schoolId)
        );
        for (EduUserDept grade : gradeList) {
            JSONObject jsonObject = JSONUtil.createObj()
                .set("gardeName", grade.getDeptName());
            // 查询学段名称
            EduUserDept section = getById(grade.getParentId());
            jsonObject.set("sectionName", section.getDeptName());
            // 查询学区名称
            EduUserDept campus = getById(section.getParentId());
            jsonObject.set("campusName", campus.getDeptName());
            if (studentNum == 0) {
                jsonObject.set("gradeStudentNumber", 0);
                jsonObject.set("percentage", "0%");
            } else {
                // 查询年级人数
                long gradeStudentNumber = eduStudentMapper.selectGradeStudentNumber(grade.getDeptId());
                if (gradeStudentNumber == 0) {
                    jsonObject.set("gradeStudentNumber", 0);
                    jsonObject.set("percentage", "0%");
                } else {
                    jsonObject.set("gradeStudentNumber", gradeStudentNumber);
                    jsonObject.set("percentage", NumberUtil.div(gradeStudentNumber * 100, studentNum, 2) + "%");
                }
            }

            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }
}
