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

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.entity.CurrentUser;
import com.yida.data.common.core.entity.constant.AppConstant;
import com.yida.data.common.core.entity.constant.LockPrefixConstant;
import com.yida.data.common.core.entity.message.EduMessageStrategy;
import com.yida.data.common.core.entity.notice.qywx.TextSchoolNotice;
import com.yida.data.common.core.entity.notice.qywx.inside.Text;
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.Role;
import com.yida.data.common.core.entity.system.SystemUser;
import com.yida.data.common.core.entity.system.enums.DeptTypeEnum;
import com.yida.data.common.core.entity.user.*;
import com.yida.data.common.core.entity.user.enums.DeptVisibleTypeEnum;
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.utils.DaHuaUtil;
import com.yida.data.common.core.utils.EnumUtils;
import com.yida.data.common.core.utils.WxUtil;
import com.yida.data.common.service.CommonService;
import com.yida.data.system.mapper.EduAppMapper;
import com.yida.data.system.service.IDeptService;
import com.yida.data.system.service.IRoleService;
import com.yida.data.system.service.IUserService;
import com.yida.data.system.service.QywxService;
import com.yida.data.user.dto.DeleteUserDeptDTO;
import com.yida.data.user.feign.RemoteStaffService;
import com.yida.data.user.feign.RemoteStudentService;
import com.yida.data.user.feign.RemoteTeacherService;
import com.yida.data.user.feign.RemoteUserDeptService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.*;

@Slf4j
@RequiredArgsConstructor
@Transactional
@Service
public class QywxServiceImpl implements QywxService {
    private static ExecutorService USER_THREAD_POLL;

    static {
        USER_THREAD_POLL = new ThreadPoolExecutor(1, 5, 1,
                TimeUnit.MINUTES,
                new LinkedBlockingQueue<>());
    }

    private final IDeptService deptService;
    private final IRoleService roleService;
    private final IUserService userService;
    private final EduAppMapper eduAppMapper;

    private final PasswordEncoder passwordEncoder;
    private final WxUtil wxUtil;
    private final CommonService commonService;
    private final RemoteTeacherService remoteTeacherService;
    private final RemoteStaffService remoteStaffService;
    private final RemoteStudentService remoteStudentService;
    private final RemoteUserDeptService remoteUserDeptService;
    private final RedisService redisService;

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void initSchoolDept(Long schoolId) {
        // 微信id
        Map<Long, Long> wxIdAndId = new ConcurrentHashMap<>();
        // 大华id
        Map<Long, String> wxIdAndDaHuaId = new ConcurrentHashMap<>();
        Map<Long, List<Map>> teacherList = new ConcurrentHashMap<>();
        // 部门对应的父部门ID
        Map<Long, Long> deptParent = new ConcurrentHashMap<>();
        Dept school = deptService.getById(schoolId);
        // 判断是否绑定大华
        boolean bindDaHuaFlag = false;
        if (Objects.nonNull(school) && school.getSchoolType().contains(Dept.TYPE_DAHUA)) {
            bindDaHuaFlag = true;
        }

        EduApp app = eduAppMapper.selectOne(Wrappers.lambdaQuery(new EduApp()).eq(EduApp::getDeptId,
                schoolId).eq(EduApp::getCode, AppConstant.CONTACT_SCHOOL));
        List<Map> deptList = wxUtil.listSchoolDept(wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret()), null);
        List<EduUserDept> camps = new ArrayList<>();
        List<EduUserDept> section = new ArrayList<>();
        List<EduUserDept> grade = new ArrayList<>();
        List<EduUserDept> clazz = new ArrayList<>();
        for (Map map : deptList) {
            Long wxId = Long.valueOf(map.get("id").toString());
            if (wxId == 1) {
                continue;
            }
            Long parentWxId = Long.valueOf(map.get("parentid").toString());
            EduUserDept dept = new EduUserDept();
            dept.setWxId(wxId);
            dept.setParentWxId(parentWxId);
            dept.setDeptType(Integer.valueOf(map.get("type").toString()));
            dept.setDeptName(map.get("name").toString());
            dept.setSchoolId(schoolId);
            dept.setParentId(-schoolId);
            switch (dept.getDeptType()) {
                case 1:
                    // 班级
                    clazz.add(dept);
                    break;
                case 2:
                    // 年级判断, 设置标准年级值
                    if (Objects.nonNull(map.get("standard_grade"))) {
                        dept.setStandardGradeValue((Integer) map.get("standard_grade"));
                    }
                    // 毕业状态
                    dept.setGraduatedStatus((Integer) map.get("is_graduated"));
                    grade.add(dept);
                    break;
                case 3:
                    // 学段判断, 根据名称获取学段类型
                    try {
                        SectionTypeEnum sectionTypeEnum = EnumUtils.valueOf(SectionTypeEnum.class, dept.getDeptName(),
                                SectionTypeEnum.class.getMethod("getName"));
                        dept.setSectionType(Objects.nonNull(sectionTypeEnum) ?
                                sectionTypeEnum.getValue() : SectionTypeEnum.CUSTOM_TYPE.getValue());
                    } catch (Exception e) {
                        log.error("根据名称获取学段类型失败, userDept: {}", dept, e);
                        dept.setSectionType(SectionTypeEnum.CUSTOM_TYPE.getValue());
                    }
                    section.add(dept);
                    break;
                case 4:
                    // 校区此处取学校部门id的相反数, 便于树形结构展示
                    dept.setParentId(-schoolId);
                    camps.add(dept);
                    // 判断是否调用大华api
                    if (bindDaHuaFlag) {
                        dept.setDaHuaId(DaHuaUtil.addDept(school.getDahuaId(), dept.getDeptName()).getStr("id"));
                    }
                    this.remoteUserDeptService.createUserDept(dept);
                    break;
                default:
                    log.error("家校部门类型错误");
                    break;
            }
            teacherList.put(wxId, (List<Map>) map.get("department_admins"));
        }
        for (EduUserDept dept : camps) {
            wxIdAndId.put(dept.getWxId(), dept.getDeptId());
            // 判断是否调用大华api
            if (bindDaHuaFlag) {
                wxIdAndDaHuaId.put(dept.getWxId(), dept.getDaHuaId());
            }
            if (CollUtil.isNotEmpty(teacherList.get(dept.getWxId()))) {
                remoteTeacherService.dealWxTeacherChange(schoolId, dept.getDeptId(), null, null, null,
                        teacherList.get(dept.getWxId()), dept.getWxId());
            }
        }
        for (EduUserDept dept : section) {
            dept.setParentId(wxIdAndId.get(dept.getParentWxId()));
            // 判断是否调用大华api
            if (bindDaHuaFlag) {
                String daHuaId = DaHuaUtil.addDept(wxIdAndDaHuaId.get(dept.getParentWxId()), dept.getDeptName()).getStr("id");
                dept.setDaHuaId(daHuaId);
                wxIdAndDaHuaId.put(dept.getWxId(), daHuaId);
            }
            this.remoteUserDeptService.createUserDept(dept);
            deptParent.put(dept.getDeptId(), dept.getParentId());
        }
        for (EduUserDept dept : section) {
            wxIdAndId.put(dept.getWxId(), dept.getDeptId());
            if (CollUtil.isNotEmpty(teacherList.get(dept.getWxId()))) {
                remoteTeacherService.dealWxTeacherChange(schoolId, dept.getParentId(), dept.getDeptId(), null, null,
                        teacherList.get(dept.getWxId()), dept.getWxId());
            }
        }
        for (EduUserDept dept : grade) {
            dept.setParentId(wxIdAndId.get(dept.getParentWxId()));
            // 判断是否调用大华api
            if (bindDaHuaFlag) {
                String daHuaId = DaHuaUtil.addDept(wxIdAndDaHuaId.get(dept.getParentWxId()), dept.getDeptName()).getStr("id");
                dept.setDaHuaId(daHuaId);
                wxIdAndDaHuaId.put(dept.getWxId(), daHuaId);
            }
            this.remoteUserDeptService.createUserDept(dept);
            deptParent.put(dept.getDeptId(), dept.getParentId());
        }
        Map<Long, EduUserDept> gradeMap = new HashMap<>();
        for (EduUserDept dept : grade) {
            wxIdAndId.put(dept.getWxId(), dept.getDeptId());
            gradeMap.put(dept.getDeptId(), dept);
            if (CollUtil.isNotEmpty(teacherList.get(dept.getWxId()))) {
                remoteTeacherService.dealWxTeacherChange(schoolId, deptParent.get(dept.getParentId()),
                        dept.getParentId(),
                        dept.getDeptId(),
                        null,
                        teacherList.get(dept.getWxId()), dept.getWxId());
            }
        }
        for (EduUserDept dept : clazz) {
            dept.setParentId(wxIdAndId.get(dept.getParentWxId()));
            // 判断是否调用大华api
            if (bindDaHuaFlag) {
                String daHuaId = DaHuaUtil.addDept(wxIdAndDaHuaId.get(dept.getParentWxId()), dept.getDeptName()).getStr("id");
                dept.setDaHuaId(daHuaId);
            }
            this.remoteUserDeptService.createUserDept(dept);
            deptParent.put(dept.getDeptId(), dept.getParentId());
        }
        for (EduUserDept dept : clazz) {
            if (CollUtil.isNotEmpty(teacherList.get(dept.getWxId()))) {
                remoteTeacherService.dealWxTeacherChange(schoolId,
                        deptParent.get(deptParent.get(dept.getParentId())),
                        deptParent.get(dept.getParentId()),
                        dept.getParentId(),
                        dept.getDeptId(),
                        teacherList.get(dept.getWxId()), dept.getWxId());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initDept(Long schoolId) {
        Map<Long, Long> idCache = new HashMap<>();
        Dept school = deptService.getById(schoolId);
        EduApp app = eduAppMapper.selectOne(Wrappers.lambdaQuery(new EduApp()).eq(EduApp::getDeptId,
                schoolId).eq(EduApp::getName, AppConstant.CONTACT));
        List<Map> deptList = wxUtil.listDept(wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret()), 1L);
        deptList.sort((x, y) -> Integer.valueOf(x.get("id").toString()) - Integer.valueOf(y.get("id").toString()));
        for (Map map : deptList) {
            if ("0".equals(map.get("parentid").toString())) {
                continue;
            }
            Dept dept = new Dept();
            dept.setParentWxId(Long.valueOf(map.get("parentid").toString()));
            dept.setWxId(Long.valueOf(map.get("id").toString()));
            if (dept.getParentWxId() == 1) {
                dept.setParentId(school.getDeptId());
            } else {
                dept.setParentId(idCache.get(dept.getParentWxId()));
            }
            dept.setDeptName(map.get("name").toString());
            // 部门类型
            dept.setDeptType(DeptTypeEnum.DEPARTMENT_TYPE.getValue());
            dept.setOrderNum(Integer.valueOf(map.get("order").toString()));
            dept.setAreaId(school.getAreaId());
            deptService.createDept(dept);
            idCache.put(dept.getWxId(), dept.getDeptId());
        }
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void initStaff(Long schoolId, CurrentUser currentUser) {
        Dept school = deptService.getById(schoolId);
        Map<Long, Dept> deptCache = new HashMap<>();
        EduApp app = eduAppMapper.selectOne(Wrappers.lambdaQuery(new EduApp()).eq(EduApp::getDeptId,
                schoolId).eq(EduApp::getName, AppConstant.CONTACT));
        JSONArray staffList = wxUtil.getUserList(wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret()),
                1L);
        List<EduStaff> saveStaff = new ArrayList<>();
        Role staffRole = roleService.getRoleByNameOrCreate("职工");

        for (Object staff : staffList) {
            // 遍历企业微信成员
            JSONObject staffJson = (JSONObject) staff;
            EduStaff eduStaff = new EduStaff();
            eduStaff.setWxId(staffJson.get("userid").toString());
            eduStaff.setName(staffJson.get("name").toString());
            eduStaff.setMobile(staffJson.get("mobile").toString());
            String sex = staffJson.get("gender").toString();
            eduStaff.setSex("1".equals(sex) ? "0" : "2".equals(sex) ? "1" : "2");
            eduStaff.setCreateId(currentUser.getUserId());
            eduStaff.setSchoolId(schoolId);
            eduStaff.setSchoolName(school.getDeptName());
            eduStaff.setAvatar(staffJson.get("avatar").toString());
            eduStaff.setPosition(staffJson.get("position").toString());
            eduStaff.setEmail(staffJson.get("email").toString());
            eduStaff.setAddress(StrUtil.utf8Str(staffJson.get("address")));
            // 成员部门信息
            JSONArray department = staffJson.getJSONArray("department");
            JSONArray isLeader = staffJson.getJSONArray("is_leader_in_dept");
            if (CollUtil.isNotEmpty(department)) {
                List<EduStaffDept> staffDeptList = new ArrayList<>();
                for (int i = 0; i < department.size(); i++) {
                    // 成员的每个部门信息
                    EduStaffDept staffDept = new EduStaffDept();
                    staffDept.setStaffName(eduStaff.getName());
                    staffDept.setDeptWxId(Long.valueOf(department.get(i).toString()));
                    Dept sysDept = deptCache.containsKey(staffDept.getDeptWxId())
                            ? deptCache.get(staffDept.getDeptWxId())
                            : (department.getLong(i) == 1L ? school :
                            deptService.getSysDeptByDeptAndWx(Arrays.asList(schoolId),
                                    staffDept.getDeptWxId()));
                    staffDept.setDeptId(sysDept.getDeptId());
                    staffDept.setDeptName(sysDept.getDeptName());
                    staffDept.setIsLeader(isLeader.getInt(i));
                    staffDept.setCreateId(currentUser.getUserId());
                    staffDept.setIsMain(ObjectUtil.equal(staffJson.get("main_department"),
                            department.get(i)) ? 0 : 1);
                    staffDeptList.add(staffDept);
                }
                eduStaff.setStaffDept(staffDeptList);
            }

            SystemUser systemUser =
                    userService.getOne(Wrappers.lambdaQuery(new SystemUser()).eq(SystemUser::getUsername,
                            eduStaff.getMobile()));
            if (ObjectUtil.isNull(systemUser)) {
                systemUser = new SystemUser();
                systemUser.setNickname(eduStaff.getName());
                systemUser.setPassword(passwordEncoder.encode(SystemUser.DEFAULT_PASSWORD));
                systemUser.setUsername(eduStaff.getMobile());
                systemUser.setMobile(eduStaff.getMobile());
                systemUser.setDeptId(eduStaff.getSchoolId());
                systemUser.setDeptName(eduStaff.getSchoolName());
                systemUser.setAvatar(eduStaff.getAvatar());
                systemUser.setSex(eduStaff.getSex());
                systemUser.setStatus("1");
                systemUser.setUserOrigin(0);
                systemUser.setTeacherWxId(eduStaff.getWxId());
                systemUser.setRoleId(staffRole.getRoleId().toString());
                systemUser.setUserType(1);
                userService.createUser(systemUser);
                eduStaff.setYidaAppUserId(systemUser.getYidaAppUserId());
            }
            eduStaff.setSysUserId(systemUser.getUserId());
            saveStaff.add(eduStaff);
        }
        int size = 2;
        for (int i = 0; i <= saveStaff.size(); i += size) {
            int begin = i;
            int end = Math.min(i + size, saveStaff.size());
            // 500个学生为一组进行操作，防止超时
            USER_THREAD_POLL.execute(() -> {
                remoteStaffService.initStaff(saveStaff.subList(begin, end));
            });
        }
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void initUser(Long schoolId, CurrentUser currentUser) {
        Dept school = deptService.getById(schoolId);
        EduApp app = eduAppMapper.selectOne(Wrappers.lambdaQuery(new EduApp()).eq(EduApp::getDeptId,
                schoolId).eq(EduApp::getCode, AppConstant.CONTACT_SCHOOL));
        JSONArray student = wxUtil.getStudentList(wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret()),
                1L);
        int size = 2;
        for (int i = 0; i <= student.size(); i += size) {
            int begin = i;
            int end = Math.min(i + size, student.size());
            // 分组进行操作，防止超时
            USER_THREAD_POLL.execute(() -> {
                List<EduStudent> saveStudent = new ArrayList<>();
                for (Object o : student.subList(begin, end)) {
                    JSONObject jsonStudent = (JSONObject) o;
                    EduStudent eduStudent = new EduStudent();
                    eduStudent.setWxId(jsonStudent.get("student_userid").toString());
                    eduStudent.setStuNumber(eduStudent.getWxId());
                    eduStudent.setStuName(jsonStudent.get("name").toString());
                    Long wxDeptId = Long.valueOf(jsonStudent.getJSONArray("department").get(0).toString());
                    // 班级
                    EduUserDept clazz = this.remoteUserDeptService.getUserDeptByDeptAndWx(Collections.singletonList(-schoolId), wxDeptId).getData();
                    eduStudent.setClassName(clazz.getDeptName());
                    eduStudent.setClassId(clazz.getDeptId());
                    // 年级
                    EduUserDept grade = this.remoteUserDeptService.getByDeptId(clazz.getParentId()).getData();
                    eduStudent.setGradeId(grade.getDeptId());
                    eduStudent.setGradeName(grade.getDeptName());
                    // 学段
                    EduUserDept section = this.remoteUserDeptService.getByDeptId(grade.getParentId()).getData();
                    eduStudent.setSectionId(section.getDeptId());
                    eduStudent.setSectionName(section.getDeptName());
                    // 学区
                    EduUserDept campus = this.remoteUserDeptService.getByDeptId(section.getParentId()).getData();
                    eduStudent.setCampusId(campus.getDeptId());
                    eduStudent.setCampusName(campus.getDeptName());
                    eduStudent.setSchoolId(schoolId);
                    eduStudent.setSchoolName(school.getDeptName());
                    eduStudent.setCreateId(currentUser.getUserId());
                    eduStudent.setParents(new ArrayList<>());
                    eduStudent.setType(0);
                    JSONArray parents = jsonStudent.getJSONArray("parents");
                    for (Object parentO : parents) {
                        JSONObject parent = (JSONObject) parentO;
                        EduParent eduParent = new EduParent();
                        eduParent.setSchoolId(schoolId);
                        eduParent.setMobile(parent.get("mobile").toString());
                        eduParent.setWxId(parent.get("parent_userid").toString());
                        eduParent.setParentType(parent.get("relation").toString());
                        eduStudent.getParents().add(eduParent);
                    }
                    saveStudent.add(eduStudent);
                }
                this.remoteStudentService.initStudent(saveStudent);
            });
        }
        log.info("初始化家长和学生信息");
    }

    /**
     * @param corpId      学校企业微信corpId
     * @param accessToken 鉴权
     * @param deptId      企业微信学校部门id
     * @param school      学校部门信息
     * @author ZYJ
     * @date 2021/11/22 16:52
     */
    @Override
    public void createSchoolDept(String corpId, String accessToken, Long deptId, Dept school) {
        log.info("开始创建家校部门");
        redisService.lock(LockPrefixConstant.USER_DEPT_CREATE_LOCK + school.getDeptId());

        try {
            // 休眠0.5s减少企业微信api并发情况
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            log.error("休眠失败");
        }
        Map deptInfo = wxUtil.listSchoolDept(accessToken, deptId).get(0);
        EduUserDept userDept = new EduUserDept();
        userDept.setDeptName((String) deptInfo.get("name"));
        userDept.setDeptType((Integer) deptInfo.get("type"));
        userDept.setWxId(Long.valueOf(deptInfo.get("id").toString()));
        userDept.setParentWxId(Long.valueOf(deptInfo.get("parentid").toString()));
        userDept.setSchoolId(school.getDeptId());
        userDept.setCreateDate(LocalDateTime.now());

        if (UserDeptTypeEnum.CAMPUS_TYPE.getValue().equals(userDept.getDeptType())) {
            // 校区此处取学校部门id的相反数, 便于树形结构展示
            userDept.setParentId(-school.getDeptId());
        } else {

            if (UserDeptTypeEnum.SECTION_TYPE.getValue().equals(userDept.getDeptType())) {
                // 学段判断, 根据名称获取学段类型
                try {
                    SectionTypeEnum sectionTypeEnum = EnumUtils.valueOf(SectionTypeEnum.class, userDept.getDeptName(),
                            SectionTypeEnum.class.getMethod("getName"));
                    userDept.setSectionType(Objects.nonNull(sectionTypeEnum) ?
                            sectionTypeEnum.getValue() : SectionTypeEnum.CUSTOM_TYPE.getValue());
                } catch (Exception e) {
                    log.error("根据名称获取学段类型失败, userDept: {}", userDept, e);
                    userDept.setSectionType(SectionTypeEnum.CUSTOM_TYPE.getValue());
                }
            } else if (UserDeptTypeEnum.GRADE_TYPE.getValue().equals(userDept.getDeptType())) {
                // 年级判断, 设置标准年级值
                if (Objects.nonNull(deptInfo.get("standard_grade"))) {
                    userDept.setStandardGradeValue((Integer) deptInfo.get("standard_grade"));
                }
                // 毕业状态
                userDept.setGraduatedStatus((Integer) deptInfo.get("is_graduated"));
            }
            // 查询父级部门
            EduUserDept parent = this.remoteUserDeptService.getUserDeptByDeptAndWx(Collections.singletonList(-school.getDeptId()),
                    userDept.getParentWxId()).getData();
            if (parent != null) {
                log.info("找到家校沟通父部门, parent:{}, dept:{}, school:{}", parent, userDept, school.getDeptId());
                userDept.setParentId(parent.getDeptId());
            } else {
                Thread.yield();
                // 此处取学校部门id的相反数, 便于树形结构展示, 挂在学校层级(用于后续定时任务处理层级关系)
                userDept.setParentId(-school.getDeptId());
                userDept.setVisible(DeptVisibleTypeEnum.INVISIBLE_TYPE.getValue());
            }
        }
        this.remoteUserDeptService.createUserDept(userDept);

        redisService.unlock(LockPrefixConstant.USER_DEPT_CREATE_LOCK + school.getDeptId());
    }

    /**
     * 响应更新家校通讯录部门事件
     */
    @Override
    public void updateSchoolDept(String accessToken, Long deptWxId, Dept school) {
        log.info("开始修改家校部门");
        List<EduUserDept> saveDeptList = new ArrayList<>();
        List<Map> deptList = wxUtil.listSchoolDept(accessToken, deptWxId);
        for (Map map : deptList) {
            // 查询的家校部门数据的部门id
            Long wxDeptId = Long.valueOf(map.get("id").toString());
            EduUserDept dept = remoteUserDeptService.getUserDeptByDeptAndWx(
                    Collections.singletonList(-school.getDeptId()), wxDeptId).getData();
            dept.setDeptName((String) map.get("name"));
            if (ObjectUtil.isNotNull(map.get("order"))) {
                dept.setOrderNum((Integer) map.get("order"));
            }
            Long campusId = null;
            Long sectionId = null;
            Long gradeId = null;
            Long classId = null;
            switch (dept.getDeptType()) {
                case 1:
                    /// 班级
                    classId = dept.getDeptId();
                    gradeId = dept.getParentId();
                    // 查询学段信息
                    EduUserDept section = remoteUserDeptService.getParentByDeptId(gradeId).getData();
                    sectionId = section.getDeptId();
                    campusId = section.getParentId();
                    break;
                case 2:
                    // 年级
                    gradeId = dept.getDeptId();
                    sectionId = dept.getParentId();
                    campusId = remoteUserDeptService.getByDeptId(sectionId).getData().getParentId();
                    break;
                case 3:
                    // 学段
                    sectionId = dept.getDeptId();
                    campusId = dept.getParentId();
                    break;
                case 4:
                    // 学区
                    campusId = dept.getDeptId();
                    break;
                default:
                    log.error("家校部门类型错误, 部门信息:{}", dept);
                    break;
            }
            // 仅处理当前部门负责人
            if (deptWxId.equals(wxDeptId)) {
                // 获取老师列表
                List<Map> teacherList = (List<Map>) map.get("department_admins");
                log.info("teachers:{},dept:{}", teacherList, dept);
                if (CollUtil.isNotEmpty(teacherList)) {
                    remoteTeacherService.dealWxTeacherChange(school.getDeptId(), campusId, sectionId, gradeId, classId, teacherList, deptWxId);
                }
            }
            saveDeptList.add(dept);
            // 更新大华部门
            if (school.getSchoolType().contains(Dept.TYPE_DAHUA)) {
                String parentDaHuaId;
                if (UserDeptTypeEnum.CAMPUS_TYPE.getValue().equals(dept.getDeptType())) {
                    // 学区的上级大华id是学校大华id
                    parentDaHuaId = school.getDahuaId();
                } else {
                    EduUserDept parent = remoteUserDeptService.getByDeptId(dept.getParentId()).getData();
                    parentDaHuaId = parent.getDaHuaId();
                }
                DaHuaUtil.updateDept(dept.getDaHuaId(), parentDaHuaId, dept.getDeptName());
            }
        }
        remoteUserDeptService.updateBatchUserDept(saveDeptList);
        log.info("修改家校部门完成");
    }

    /**
     * 响应删除家校通讯录部门事件
     */
    @Override
    public void deleteSchoolDept(Long deptWxId, Dept school) {
        log.info("开始删除家校部门");
        EduUserDept userDept = this.remoteUserDeptService.getUserDeptByDeptAndWx(Collections.singletonList(-school.getDeptId()), deptWxId).getData();
        log.info("params:{},{},{}", deptWxId, -school.getDeptId(), userDept);
        if (userDept != null) {
            // 未在其他删除回调事件中被删除
            remoteUserDeptService.deleteUserDeptRecur(
                    DeleteUserDeptDTO.builder()
                            .deptIdList(Collections.singletonList(userDept.getDeptId()))
                            .school(school)
                            .build());
        }
    }

    /**
     * 响应新增部门事件
     */
    @Override
    public void createDept(String deptId, String deptName, String parentId, String order, Dept school) {
        Dept parent = !"1".equals(parentId)
                ? deptService.getSysDeptByDeptAndWx(Arrays.asList(school.getDeptId()), Long.valueOf(parentId))
                : school;
        Dept dept = new Dept();
        dept.setDeptName(deptName);
        // 部门类型
        dept.setDeptType(DeptTypeEnum.DEPARTMENT_TYPE.getValue());
        dept.setParentWxId(Long.valueOf(parentId));
        dept.setWxId(Long.valueOf(deptId));
        dept.setParentId(parent.getDeptId());
        dept.setAreaId(parent.getAreaId());
        dept.setOrderNum(Integer.valueOf(order));
        deptService.save(dept);
    }

    /**
     * 响应更新部门事件
     */
    @Override
    public void updateDept(String deptId, String deptName, String parentId, Long schoolId) {
        Dept dept = deptService.getSysDeptByDeptAndWx(Collections.singletonList(schoolId), Long.valueOf(deptId));
        dept.setDeptName(deptName);
        // 部门类型
        dept.setDeptType(DeptTypeEnum.DEPARTMENT_TYPE.getValue());
        dept.setWxId(Long.valueOf(deptId));
        if (StrUtil.isNotBlank(parentId)) {
            Dept parent;
            Long parentWxId = Long.valueOf(parentId);
            if (parentWxId == 1L) {
                parent = deptService.getById(schoolId);
            } else {
                parent = deptService.getSysDeptByDeptAndWx(Collections.singletonList(schoolId), parentWxId);
            }
            dept.setParentWxId(parentWxId);
            dept.setParentId(parent.getDeptId());
            dept.setAreaId(parent.getAreaId());
        }
        deptService.updateById(dept);
    }

    /**
     * 响应删除部门事件
     */
    @Override
    public void deleteDept(String deptId, Long schoolId) {
        log.info("开始删除部门");
        Dept dept = deptService.getSysDeptByDeptAndWx(Arrays.asList(schoolId), Long.valueOf(deptId));
        log.info("params:{},{},{}", deptId, schoolId, dept);
        if (dept != null) {
            // 未在其他删除回调中被删除
            deptService.deleteDeptRecur(Arrays.asList(dept.getDeptId()), null);
        }
    }

    /**
     * 响应新增学生、更新学生事件
     */
    @Override
    public void changeStudent(String accessToken, String wxId, Dept school) {
        JSONObject student = wxUtil.getStudentOrParent(accessToken, wxId);
        JSONArray studentClassIds = student.getJSONArray("department");
        Long deptWxId = Long.valueOf(studentClassIds.get(0).toString());
        // 学生在多个班
        if (studentClassIds.size() > 1) {
            EduStudent eduStudent = remoteStudentService.getStudentByStuNumAndSchool(wxId, school.getDeptId()).getData();
            if (eduStudent != null) {
                // 使用新的部门作为学生班级
                Long oldClassId = eduStudent.getClassId();
                EduUserDept oldClass = this.commonService.getUserDept(oldClassId);
                for (Object classId : studentClassIds) {
                    if (!classId.toString().equals(oldClass.getWxId())) {
                        deptWxId = Long.valueOf(classId.toString());
                    }
                }
            }
        }
        EduUserDept dept = this.remoteUserDeptService.getUserDeptByDeptAndWx(
                Collections.singletonList(-school.getDeptId()), deptWxId).getData();
        if (dept == null) {
            // 部门未创建成功，等待10s，可能是正在响应部门创建事件
            for (int i = 0; i < 20; i++) {
                try {
                    Thread.sleep(500);
                    dept = this.remoteUserDeptService.getUserDeptByDeptAndWx(
                            Collections.singletonList(-school.getDeptId()), deptWxId).getData();
                    if (dept != null) {
                        break;
                    }
                    if (i == 19) {
                        // 循环结束仍未发现部门，将学生挂在学校下
                        dept = EduUserDept.builder()
                                .deptId(school.getDeptId())
                                .deptName(school.getDeptName())
                                .build();
                    }
                } catch (Exception e) {
                    log.error("msg:{}", e.getMessage());
                }
            }
        }
        log.info("学生所属部门，student:{},deptId:{},wxId:{}", student, Objects.requireNonNull(dept).getDeptId(), deptWxId);

        EduStudent eduStudent = new EduStudent();
//        eduStudent.setType(0);
        eduStudent.setStuName(student.get("name").toString());
        // 班级信息
        eduStudent.setClassId(dept.getDeptId());
        eduStudent.setClassName(dept.getDeptName());
        // 年级
        EduUserDept grade = this.commonService.getUserDept(dept.getParentId());
        eduStudent.setSchoolId(school.getDeptId());
        eduStudent.setSchoolName(school.getDeptName());
        if (grade != null) {
            eduStudent.setGradeId(grade.getDeptId());
            eduStudent.setGradeName(grade.getDeptName());
            // 学段
            EduUserDept section = this.commonService.getUserDept(grade.getParentId());
            if (section != null) {
                eduStudent.setSectionId(section.getDeptId());
                eduStudent.setSectionName(section.getDeptName());
                // 学区
                EduUserDept campus = this.commonService.getUserDept(section.getParentId());
                if (campus != null) {
                    eduStudent.setCampusId(campus.getDeptId());
                    eduStudent.setCampusName(campus.getDeptName());
                }
            }
        }
        // 企业微信id
        eduStudent.setWxId(student.get("student_userid").toString());
        eduStudent.setStuNumber(student.get("student_userid").toString());
        // 家长信息
        eduStudent.setParents(new ArrayList<>());
        for (Object parentObj : student.getJSONArray("parents")) {
            JSONObject parent = (JSONObject) parentObj;
            EduParent eduParent = new EduParent();
            eduParent.setMobile(parent.get("mobile").toString());
            eduParent.setWxId(parent.get("parent_userid").toString());
            eduParent.setParentType(parent.get("relation").toString());
            eduParent.setSchoolId(school.getDeptId());
            eduStudent.getParents().add(eduParent);
        }
        remoteStudentService.dealStudentWxChange(eduStudent);
    }

    /**
     * 响应删除学生事件
     */
    @Override
    public void deleteStudent(String wxId, Long schoolId) {
        log.info("delete student:{},{}", wxId, schoolId);
        remoteStudentService.dealStudentWxDelete(wxId, schoolId);
    }

    /**
     * 响应更新家长事件
     */
    @Override
    public void updateParent(String accessToken, String wxId, Long schoolId) {
        JSONObject parent = wxUtil.getStudentOrParent(accessToken, wxId);
        if (parent != null) {
            EduParent eduParent = new EduParent();
            eduParent.setWxId(wxId);
            eduParent.setMobile(parent.get("mobile").toString());
            eduParent.setSchoolId(schoolId);
            eduParent.setChildren(new ArrayList<>());
            for (Object children : parent.getJSONArray("children")) {
                JSONObject child = (JSONObject) children;
                Map<String, Object> childMap = new HashMap<>();
                childMap.put("student_userid", child.get("student_userid").toString());
                childMap.put("relation", child.get("relation").toString());
                eduParent.getChildren().add(childMap);
            }
            remoteStudentService.dealParentWxChange(eduParent, schoolId);
        }
    }

    /**
     * 响应删除家长事件
     */
    @Override
    public void deleteParent(String wxId, Long schoolId) {
        remoteStudentService.dealParentWxDelete(wxId, schoolId);
    }

    /**
     * 响应新建企业用户事件
     */
    @Override
    public void createUser(String name, String wxId, String phone, String email,
                           String gender, String avatar, String department, String isLeader,
                           String mainDepartment, Dept school) {
        EduStaff eduStaff = new EduStaff();
        SystemUser user = userService.findByName(StrUtil.isNotBlank(phone) ? phone : email);
        if (user == null) {
            user = new SystemUser();
            user.setAvatar(avatar);
            user.setMobile(phone);
            user.setEmail(email);
            user.setUsername(StrUtil.isNotBlank(phone) ? phone : email);
            user.setNickname(name);
            user.setDeptId(school.getDeptId());
            user.setStatus("1");
            user.setSex("1".equals(gender) ? "0" : "2".equals(gender) ? "1" : "2");
            user.setUserOrigin(0);
            user.setTeacherWxId(wxId);
            user.setUserType(1);
            userService.createUser(user);
            eduStaff.setYidaAppUserId(user.getYidaAppUserId());
        }
        eduStaff.setSysUserId(user.getUserId());
        eduStaff.setWxId(wxId);
        eduStaff.setMobile(phone);
        eduStaff.setName(name);
        eduStaff.setAvatar(avatar);
        eduStaff.setSchoolId(school.getDeptId());
        eduStaff.setSchoolName(school.getDeptName());
        eduStaff.setSex("1".equals(gender) ? "0" : "2".equals(gender) ? "1" : "2");

        // 成员部门信息
        String[] departmentList = StrUtil.split(department, ",");
        String[] isLeaderList = StrUtil.split(isLeader, ",");
        if (ArrayUtil.isNotEmpty(departmentList)) {
            List<EduStaffDept> staffDeptList = new ArrayList<>();
            for (int i = 0; i < departmentList.length; i++) {
                // 成员的每个部门信息
                EduStaffDept staffDept = new EduStaffDept();
                staffDept.setStaffName(eduStaff.getName());
                staffDept.setDeptWxId(Long.valueOf(departmentList[i]));
                Dept sysDept = ("1".equals(departmentList[i])
                        ? school
                        : deptService.getSysDeptByDeptAndWx(Arrays.asList(school.getDeptId()), staffDept.getDeptWxId()));
                staffDept.setDeptId(sysDept.getDeptId());
                staffDept.setDeptName(sysDept.getDeptName());
                staffDept.setIsLeader(Integer.valueOf(isLeaderList[i]));
                staffDept.setIsMain(ObjectUtil.equal(mainDepartment, departmentList[i]) ? 0 : 1);
                staffDeptList.add(staffDept);
            }
            eduStaff.setStaffDept(staffDeptList);
        }
        remoteTeacherService.saveStaffBySchoolAndWx(eduStaff);
    }

//    /**
//     * 响应更新企业用户事件
//     */
//    @Override
//    public void updateUser(String name, String wxId, String phone, String email,
//                           String gender, String avatar, String department, String isLeader,
//                           String mainDepartment, Dept school) {
//        EduStaff eduStaff = new EduStaff();
//        if (StrUtil.isNotBlank(phone)) {
//            SystemUser user = userService.findByName(phone);
//            if (user == null) {
//                user = new SystemUser();
//                user.setAvatar(avatar);
//                user.setMobile(phone);
//                user.setEmail(email);
//                user.setUsername(StrUtil.isNotBlank(phone) ? phone : email);
//                user.setNickname(name);
//                user.setDeptId(school.getDeptId());
//                user.setStatus("1");
//                user.setSex("1".equals(gender) ? "0" : "2".equals(gender) ? "1" : "2");
//                user.setUserOrigin(0);
//                user.setTeacherWxId(wxId);
//                user.setUserType(1);
//                userService.createUser(user);
//                eduStaff.setYidaAppUserId(user.getYidaAppUserId());
//            }
//            eduStaff.setSysUserId(user.getUserId());
//        } else {
//            SystemUser user =
//                    userService.getOne(Wrappers.lambdaQuery(new SystemUser()).eq(SystemUser::getTeacherWxId
//                            , wxId).eq(SystemUser::getDeptId, school.getDeptId()));
//            if (user == null) {
//                user = new SystemUser();
//                user.setAvatar(avatar);
//                user.setMobile(phone);
//                user.setEmail(email);
//                user.setUsername(StrUtil.isNotBlank(phone) ? phone : email);
//                user.setNickname(name);
//                user.setDeptId(school.getDeptId());
//                user.setStatus("1");
//                user.setSex("1".equals(gender) ? "0" : "2".equals(gender) ? "1" : "2");
//                user.setUserOrigin(0);
//                user.setTeacherWxId(wxId);
//                user.setUserType(1);
//                userService.createUser(user);
//                eduStaff.setYidaAppUserId(user.getYidaAppUserId());
//            }
//            eduStaff.setSysUserId(user.getUserId());
//        }
//        eduStaff.setWxId(wxId);
//        eduStaff.setMobile(phone);
//        eduStaff.setName(name);
//        eduStaff.setAvatar(avatar);
//        eduStaff.setSchoolId(school.getDeptId());
//        eduStaff.setSchoolName(school.getDeptName());
//        eduStaff.setSex("1".equals(gender) ? "0" : "2".equals(gender) ? "1" : "2");
//
//        // 成员部门信息
//        String[] departmentList = StrUtil.split(department, ",");
//        String[] isLeaderList = StrUtil.split(isLeader, ",");
//        if (ArrayUtil.isNotEmpty(departmentList)) {
//            List<EduStaffDept> staffDeptList = new ArrayList<>();
//            for (int i = 0; i < departmentList.length; i++) {
//                // 成员的每个部门信息
//                EduStaffDept staffDept = new EduStaffDept();
//                staffDept.setStaffName(eduStaff.getName());
//                staffDept.setDeptWxId(Long.valueOf(departmentList[i]));
//                Dept sysDept = ("1".equals(departmentList[i])
//                        ? school
//                        : deptService.getSysDeptByDeptAndWx(Arrays.asList(school.getDeptId()), staffDept.getDeptWxId()));
//                staffDept.setDeptId(sysDept.getDeptId());
//                staffDept.setDeptName(sysDept.getDeptName());
//                staffDept.setIsLeader(Integer.valueOf(isLeaderList[i]));
//                staffDept.setIsMain(ObjectUtil.equal(mainDepartment,
//                        departmentList[i]) ? 0 : 1);
//                staffDeptList.add(staffDept);
//            }
//            eduStaff.setStaffDept(staffDeptList);
//        }
//        remoteTeacherService.saveStaffBySchoolAndWx(eduStaff);
//    }

    /**
     * 响应更新企业用户事件
     */
    @Override
    public void updateUser(String name, String wxId, String phone, String email,
                           String gender, String avatar, String department, String isLeader,
                           String mainDepartment, Dept school) {
        EduStaff eduStaff = remoteStaffService.getStaffByWxOrMobileOrOpenId(wxId, null, null, school.getDeptId()).getData();
        if (Objects.isNull(eduStaff)) {
            eduStaff = new EduStaff();
        }
        if (StrUtil.isNotBlank(phone)) {
            SystemUser user = userService.findByMobile(phone);
            if (user == null) {
                user = new SystemUser();
                user.setAvatar(avatar);
                user.setMobile(phone);
                user.setEmail(email);
                user.setUsername(StrUtil.isNotBlank(phone) ? phone : email);
                user.setNickname(name);
                user.setDeptId(school.getDeptId());
                user.setStatus("1");
                user.setSex("1".equals(gender) ? "0" : "2".equals(gender) ? "1" : "2");
                user.setUserOrigin(0);
                user.setTeacherWxId(wxId);
                user.setUserType(1);
                userService.createUser(user);
                eduStaff.setYidaAppUserId(user.getYidaAppUserId());
                eduStaff.setSysUserId(user.getUserId());
            }
            eduStaff.setMobile(phone);
        } else {
            SystemUser user = null;
            if (Objects.nonNull(eduStaff.getId())) {
                user = userService.getById(eduStaff.getSysUserId());
            }
            if (user == null) {
                user = new SystemUser();
                user.setAvatar(avatar);
                user.setMobile(phone);
                user.setEmail(email);
                user.setUsername(StrUtil.isNotBlank(phone) ? phone : email);
                user.setNickname(name);
                user.setDeptId(school.getDeptId());
                user.setStatus("1");
                user.setSex("1".equals(gender) ? "0" : "2".equals(gender) ? "1" : "2");
                user.setUserOrigin(0);
                user.setTeacherWxId(wxId);
                user.setUserType(1);
                userService.createUser(user);
                eduStaff.setYidaAppUserId(user.getYidaAppUserId());
                eduStaff.setSysUserId(user.getUserId());
            }
        }
        eduStaff.setWxId(wxId);
        if (StrUtil.isNotBlank(name)) {
            eduStaff.setName(name);
        }
        if (StrUtil.isNotBlank(avatar)) {
            eduStaff.setAvatar(avatar);
        }
        eduStaff.setSchoolId(school.getDeptId());
        eduStaff.setSchoolName(school.getDeptName());
        if (StrUtil.isNotBlank(gender)) {
            eduStaff.setSex("1".equals(gender) ? "0" : "2".equals(gender) ? "1" : "2");
        }

        // 成员部门信息
        String[] departmentList = StrUtil.split(department, ",");
        String[] isLeaderList = StrUtil.split(isLeader, ",");
        if (ArrayUtil.isNotEmpty(departmentList)) {
            List<EduStaffDept> staffDeptList = new ArrayList<>();
            for (int i = 0; i < departmentList.length; i++) {
                // 成员的每个部门信息
                EduStaffDept staffDept = new EduStaffDept();
                staffDept.setStaffName(eduStaff.getName());
                staffDept.setDeptWxId(Long.valueOf(departmentList[i]));
                Dept sysDept = ("1".equals(departmentList[i])
                        ? school
                        : deptService.getSysDeptByDeptAndWx(Arrays.asList(school.getDeptId()), staffDept.getDeptWxId()));
                staffDept.setDeptId(sysDept.getDeptId());
                staffDept.setDeptName(sysDept.getDeptName());
                staffDept.setIsLeader(Integer.valueOf(isLeaderList[i]));
                staffDept.setIsMain(ObjectUtil.equal(mainDepartment,
                        departmentList[i]) ? 0 : 1);
                staffDeptList.add(staffDept);
            }
            eduStaff.setStaffDept(staffDeptList);
        }
        remoteTeacherService.saveStaffBySchoolAndWx(eduStaff);
    }

    /**
     * 响应删除企业用户事件
     */
    @Override
    public void deleteUser(String wxId, Long schoolId) {
        remoteStaffService.dealWxUserDelete(wxId, schoolId);
    }

    /**
     * 调用家长关注发送通知方法
     *
     * @param parentId 企业微信家长id
     * @param schoolId 学校id
     * @author ZYJ
     * @date 2021/8/19 11:36
     */
    @Override
    public void sendParentSubscribeMessage(String parentId, Long schoolId) {
        EduApp app = commonService.getAppByCodeAndSchool(AppConstant.INDEX_PARENT, null, schoolId);
        // 创建发送通知实体类
        TextSchoolNotice textSchoolNotice = new TextSchoolNotice();
        // 传入被通知的家长id
        textSchoolNotice.setTo_parent_userid(Collections.singletonList(parentId));
        textSchoolNotice.setAgentid(app.getWxAgentId());
        // 封装发送的通知
        EduMessageStrategy eduMessageStrategy = this.remoteStudentService.getEduMessageStrategyBySchoolId(schoolId).getData();
        log.info("当前学校-->{}的关系回复消息是-->{}: ", schoolId, JSONUtil.toJsonStr((eduMessageStrategy)));
        if (Optional.ofNullable(eduMessageStrategy).isPresent()
                && StringUtils.isNotBlank(eduMessageStrategy.getContent())) {
            // 设置内容信息
            String content = eduMessageStrategy.getContent().replace("<p>", "")
                    .replace("</p>", "\n")
                    .replace(" rel=\"noopener noreferrer\" target=\"_blank\"", "");
            textSchoolNotice.setText(new Text(content));
            // 调用企业微信发送通知方法
            wxUtil.pushSchoolNotice(
                    wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret()),
                    textSchoolNotice);
        } else {
            log.error("家长关注发送通知方法失败, 当前学校-->{} 没有默认消息数据: ", schoolId);
        }
    }

    @Override
    public void updateUserInfo(String userId, Dept school, EduApp app) {
        // 查询用户详细信息
        JSONObject userDetail = wxUtil.getUserDetail(wxUtil.getAccessToken(app.getWxCorpId(), app.getWxSecret()), userId);
        // 查询职工数据
        EduStaff eduStaff = remoteStaffService.getStaffByWxOrMobileOrOpenId(userId, null, null, school.getDeptId()).getData();
        if (Objects.isNull(eduStaff)) {
            log.error("职工信息错误, userId: {}, schoolId: {}", userId, school.getDeptId());
            return;
        }
        String name = userDetail.getStr("name");
        eduStaff.setName(name);
        // 职位
        eduStaff.setPosition(userDetail.getStr("position"));

        // 成员部门信息
        JSONArray departmentList = userDetail.getJSONArray("department");
        JSONArray leaderInDept = userDetail.getJSONArray("is_leader_in_dept");
        // 主部门信息
        String mainDepartment = userDetail.getStr("main_department");
        if (ArrayUtil.isNotEmpty(departmentList)) {
            List<EduStaffDept> staffDeptList = new ArrayList<>();
            for (int i = 0; i < departmentList.size(); i++) {
                // 部门id
                String deptId = String.valueOf(departmentList.get(i));
                // 成员的每个部门信息
                EduStaffDept staffDept = new EduStaffDept();
                staffDept.setStaffName(eduStaff.getName());
                staffDept.setDeptWxId(Long.valueOf(deptId));
                Dept sysDept = ("1".equals(deptId)
                        ? school
                        : deptService.getSysDeptByDeptAndWx(Collections.singletonList(school.getDeptId()), staffDept.getDeptWxId()));
                staffDept.setDeptId(sysDept.getDeptId());
                staffDept.setDeptName(sysDept.getDeptName());
                staffDept.setIsLeader(Integer.valueOf(String.valueOf(leaderInDept.get(i))));
                staffDept.setIsMain(ObjectUtil.equal(mainDepartment, deptId) ? 0 : 1);
                staffDeptList.add(staffDept);
            }
            eduStaff.setStaffDept(staffDeptList);
        }
        remoteTeacherService.saveStaffBySchoolAndWx(eduStaff);
    }
}
