package com.qmth.teachcloud.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.teachcloud.common.bean.dto.OrgDto;
import com.qmth.teachcloud.common.bean.dto.excel.DescribeImportDto;
import com.qmth.teachcloud.common.bean.dto.excel.SysOrgImportDto;
import com.qmth.teachcloud.common.bean.params.UserSaveParams;
import com.qmth.teachcloud.common.bean.result.RoleResult;
import com.qmth.teachcloud.common.bean.result.SysUserResult;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicCourse;
import com.qmth.teachcloud.common.entity.SysOrg;
import com.qmth.teachcloud.common.entity.SysRole;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.FieldUniqueEnum;
import com.qmth.teachcloud.common.enums.OrgTypeEnum;
import com.qmth.teachcloud.common.enums.RoleTypeEnum;
import com.qmth.teachcloud.common.mapper.SysOrgMapper;
import com.qmth.teachcloud.common.service.*;
import com.qmth.teachcloud.common.util.ExcelUtil;
import com.qmth.teachcloud.common.util.JdbcErrorUtil;
import com.qmth.teachcloud.common.util.ResultUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 学校组织架构 服务实现类
 * </p>
 *
 * @author xf
 * @since 2021-03-23
 */
@Service
public class SysOrgServiceImpl extends ServiceImpl<SysOrgMapper, SysOrg> implements SysOrgService {

    @Resource
    private SysUserService sysUserService;
    @Resource
    private SysRoleService sysRoleService;
    @Resource
    private SysOrgMapper sysOrgMapper;
    @Resource
    private CommonCacheService commonCacheService;
    @Resource
    private BasicCourseService basicCourseService;

    @Override
    public List<OrgDto> listOrgTree(RoleTypeEnum specialPrivilegeEnum, boolean withoutPrintingRoom, String courseCode, Set<Long> orgIds) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        List<SysUserResult> finalSysUserResultList = sysUserService.findSysUserResultListNew(schoolId, specialPrivilegeEnum);
        if (!CollectionUtils.isEmpty(finalSysUserResultList)) {
            finalSysUserResultList.forEach(e -> {
                if (Objects.nonNull(e.getRoleIds())) {
                    String[] roldIds = StringUtils.split(e.getRoleIds(), ";");
                    List<RoleResult> roleResultList = new ArrayList<>(roldIds.length);
                    for (int y = 0; y < roldIds.length; y++) {
                        String[] strs = StringUtils.split(roldIds[y], ",");
                        roleResultList.add(new RoleResult(Long.parseLong(strs[0]), strs[1]));
                    }
                    e.setRoleResultList(roleResultList);
                }
            });
        }
        List<OrgDto> orgList = this.listOrgAll(schoolId);
        if (withoutPrintingRoom) {
            orgList = orgList.stream().filter(e -> !OrgTypeEnum.PRINTING_HOUSE.name().equals(e.getType())).collect(Collectors.toList());
        }
        if (CollectionUtils.isNotEmpty(orgIds)) {
            orgList = orgList.stream().filter(e -> orgIds.contains(e.getId())).collect(Collectors.toList());
        }
        Map<Long, OrgDto> map = orgList.stream()
                .peek(e -> {
                    // 加入机构下所有人员查询
                    e.setSysUserList(finalSysUserResultList.stream().filter(f -> Objects.nonNull(f.getOrgId()) && f.getOrgId().equals(e.getId())).collect(Collectors.toList()));
                })
                .collect(Collectors.toMap(OrgDto::getId, Function.identity(), (dto1, dto2) -> dto1));

        Iterator<Long> iterator = map.keySet().iterator();
        Set<Long> deleteKeys = new HashSet<>();
        while (iterator.hasNext()) {
            Long parentId = iterator.next();
            if (map.get(parentId).getParentId() != null) {
                if (Objects.nonNull(map.get(map.get(parentId).getParentId()))) {
                    map.get(map.get(parentId).getParentId()).getChildren().add(map.get(parentId));
                    deleteKeys.add(parentId);
                }
            }
        }
        for (Long key : deleteKeys) {
            map.remove(key);
        }
        List<OrgDto> list = new ArrayList<>(map.values());
        if ((specialPrivilegeEnum == RoleTypeEnum.MARKER) && Objects.nonNull(courseCode)) {
            List<SysUserResult> resultList = sysUserService.findCourseSysUserResultList(schoolId, courseCode);
            list.get(0).setCourseUserList(resultList);
        }
        return list;
    }

    /**
     * 获取所有机构
     *
     * @param schoolId
     * @return
     */
    @Override
    public List<OrgDto> listOrgAll(Long schoolId) {
        return sysOrgMapper.listOrgAll(schoolId);
    }

    @Override
    @Transactional(propagation = Propagation.NESTED)
    public boolean saveOrg(SysOrg org, SysUser sysUser) {
        boolean success = false;
        try {
            Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
            // 机构代码不为空，校验唯一性
//            if (StringUtils.isNotBlank(org.getCode())) {
//                QueryWrapper<SysOrg> queryWrapper = new QueryWrapper<>();
//                queryWrapper.lambda().eq(SysOrg::getSchoolId, schoolId)
//                        .eq(SysOrg::getCode, org.getCode());
//                SysOrg codeSysOrg = this.getOne(queryWrapper);
//
//                if (codeSysOrg != null && (org.getId() == null || !org.getId().equals(codeSysOrg.getId()))) {
//                    throw ExceptionResultEnum.ERROR.exception("机构代码已存在");
//                }
//
//                // 机构代码以code开头，则清除缓存
//                if (org.getCode().startsWith(SystemConstant.ORG_PREFIX)) {
//                    commonCacheService.removeMaxOrgCode(schoolId);
//                }
//            }
            // 机构代码为空，若为一级学院，则自动生成code
//            else {
//                SysOrg sysOrgRoot = this.getOne(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSchoolId, schoolId).eq(SysOrg::getType, OrgTypeEnum.SCHOOL));
            // 学校下第一级机构，自动生成code
//                if (sysOrgRoot != null && org.getParentId().equals(sysOrgRoot.getId())) {
//                    Integer maxOrgCode = commonCacheService.getMaxOrgCode(schoolId);
//                    Integer currentCode = maxOrgCode + 1;
//                    commonCacheService.setMaxOrgCode(schoolId, currentCode);
//                    org.setCode(SystemConstant.ORG_PREFIX + currentCode);
//                }
//            }

            if (org.getId() == null) {// 新增
                org.setSchoolId(schoolId);
                org.insertInfo(sysUser.getId());
                success = this.save(org);
            } else { // 修改
                // 已经推送到云阅卷，不允许修改机构代码
                SysOrg sysOrg = this.getById(org.getId());
                if (sysOrg.getThirdRelateId() != null && !org.getCode().equals(sysOrg.getCode())) {
                    throw ExceptionResultEnum.ERROR.exception("机构已经同步到云阅卷，不支持修改机构代码");
                }
                org.updateInfo(sysUser.getId());
                success = this.updateById(org);
            }
            commonCacheService.updateOrgCollegeLevelCache(schoolId);
        } catch (Exception e) {
            if (e instanceof DuplicateKeyException) {
                String errorColumn = e.getCause().toString();
                String columnStr = errorColumn.substring(errorColumn.lastIndexOf("key") + 3, errorColumn.length()).replaceAll("'", "");
                throw ExceptionResultEnum.SQL_ERROR.exception("[" + FieldUniqueEnum.convertToTitle(columnStr) + "]数据不允许重复插入");
            } else if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return success;
    }

    @Transactional
    @Override
    public boolean saveReportOrg(SysOrg org) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        org.setSchoolId(schoolId);
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();

        QueryWrapper<SysOrg> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysOrg::getSchoolId, org.getSchoolId()).eq(SysOrg::getParentId, org.getParentId()).eq(SysOrg::getCode, org.getCode());
        SysOrg sysOrg = this.getOne(queryWrapper);

        // 新增
        if (org.getId() == null) {
            if (sysOrg != null) {
                throw ExceptionResultEnum.ERROR.exception("机构代码已存在");
            }
            org.setId(SystemConstant.getDbUuid());
            org.setCreateId(sysUser.getId());
            org.setCreateTime(System.currentTimeMillis());
            org.setCreateTime(System.currentTimeMillis());
            return this.save(org);
        }
        // 修改
        else {
            if (sysOrg != null && org.getId().longValue() != sysOrg.getId().longValue()) {
                throw ExceptionResultEnum.ERROR.exception("机构代码已存在");
            }
            org.setUpdateId(sysUser.getId());
            org.setUpdateTime(System.currentTimeMillis());
            return this.updateById(org);
        }
    }

    @Override
    public SysOrg findByForeignKey(Long schoolId, String collegeCode, String collegeName) {
        List<SysOrg> tbSchoolCollegeList = this.list(new QueryWrapper<SysOrg>().lambda()
                .eq(SysOrg::getSchoolId, schoolId)
                .eq(SysOrg::getCode, collegeCode)
                .eq(SysOrg::getName, collegeName));
        if (tbSchoolCollegeList.size() != 1) {
            throw ExceptionResultEnum.ERROR.exception("学院基础数据信息异常");
        }
        return tbSchoolCollegeList.get(0);
    }

    /**
     * 查询机构ids
     *
     * @param orgId
     * @return
     */
    @Override
    public List<Long> findCollegeIds(Long orgId) {
        QueryWrapper<SysOrg> sysOrgQueryWrapper = new QueryWrapper<>();
        sysOrgQueryWrapper.lambda().eq(SysOrg::getParentId, orgId)
                .eq(SysOrg::getEnable, true);
        List<SysOrg> sysOrgList = this.list(sysOrgQueryWrapper);
        return Objects.nonNull(sysOrgList) ? sysOrgList.stream().map(s -> s.getId()).collect(Collectors.toList()) : null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long searchOrInsert(Long schoolId, String collegeName) {
        Long orgId;
        List<SysOrg> sysOrgList = this.list(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSchoolId, schoolId));
        List<SysOrg> parentOrgList = sysOrgList.stream().filter(e -> e.getParentId() == null || e.getParentId() == 0).collect(Collectors.toList());
        Long parentId;
        if (parentOrgList.size() == 0) {
            parentId = SystemConstant.getDbUuid();
            SysOrg parentTemp = new SysOrg();
            parentTemp.setId(parentId);
            parentTemp.setEnable(true);
            parentTemp.setSchoolId(schoolId);
            parentTemp.setName(SystemConstant.PARENT_ORG);
            parentTemp.setCode(SystemConstant.PARENT_ORG);
            this.save(parentTemp);
        } else {
            parentId = parentOrgList.get(0).getId();
        }

        SysOrg sysOrg = this.getOne(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSchoolId, schoolId).eq(SysOrg::getName, collegeName));
        if (Objects.isNull(sysOrg)) {
            // 创建学院
            orgId = SystemConstant.getDbUuid();
            SysOrg temp = new SysOrg();
            temp.setId(orgId);
            temp.setName(collegeName);
            temp.setCode(collegeName);
            temp.setSchoolId(schoolId);
            temp.setEnable(true);
            temp.setParentId(parentId);
            this.save(temp);

            // 创建院长用户
            SysUser old = sysUserService.getOne(new QueryWrapper<SysUser>().lambda()
                    .eq(SysUser::getSchoolId, schoolId)
                    .eq(SysUser::getLoginName, collegeName)
                    .eq(SysUser::getRealName, collegeName));
            Long id = 0L;
            if (Objects.nonNull(old)) {
                id = old.getId();
            }
            SysRole role = sysRoleService.list(new QueryWrapper<SysRole>().lambda().eq(SysRole::getType, RoleTypeEnum.PRESIDENT)).get(0);
            List<Long> roleIds = new ArrayList<>();
            roleIds.add(role.getId());

            UserSaveParams userSaveParams = new UserSaveParams();
            if (id > 0) {
                userSaveParams.setId(id);
            }

            userSaveParams.setSchoolId(schoolId);
            userSaveParams.setLoginName(collegeName);
            userSaveParams.setRealName(collegeName);
            userSaveParams.setPassword(SystemConstant.DEFAULT_PASSWORD);
            userSaveParams.setOrgId(orgId);
            userSaveParams.setEnable(true);
            userSaveParams.setRoleIds(roleIds.toArray(new Long[0]));
            sysUserService.saveUserNoAuth(userSaveParams);
        } else {
            orgId = sysOrg.getId();
        }
        return orgId;
    }

    /**
     * 递归树查询(同级及以上)
     *
     * @param orgId
     * @param school
     * @param college
     * @return
     */
    @Override
    public List<SysOrg> findByConnectByParentId(Long orgId, Boolean school, Boolean college) {
        return sysOrgMapper.findByConnectByParentId(orgId, school, college);
    }

    /**
     * 递归树查询(同级及以下)
     *
     * @param orgId
     * @return
     */
    @Override
    public List<SysOrg> findByConnectByRootOrgId(Long orgId) {
        return sysOrgMapper.findByConnectByRootOrgId(orgId);
    }

    @Override
    public List<SysOrg> findDeepByOrgIdAndType(String orgType) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        if (Objects.nonNull(orgType) && (Objects.equals(orgType, "SCHOOL") || Objects.equals(orgType, "PRINTING_HOUSE"))) {
            return sysOrgMapper.findByConnectByRootOrgIdAndType(sysUser.getOrgId(), OrgTypeEnum.valueOf(orgType).name());
        } else {
            return sysOrgMapper.findByConnectByRootOrgIdAndFilter(sysUser.getOrgId(), true);
        }
//        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
//        Set<Long> orgIds = new HashSet<>(); // 下级机构集合
//        Set<Long> authOrgIdSet = new HashSet<>(); // 当前用户数据权限下的机构集合
//        Set<Long> orgIdSet = new HashSet<>(); // 输入机构下的所有下级机构集合
//        if (auth) {
//            authOrgIdSet = teachcloudCommonService.listSubOrgIds(null);
//        }
//        if (SystemConstant.longNotNull(orgId)) {
//            orgIdSet = teachcloudCommonService.listSubOrgIds(orgId);
//        }
//        orgIds.addAll(authOrgIdSet);
//        orgIds.addAll(orgIdSet);
//        QueryWrapper<SysOrg> queryWrapper = new QueryWrapper<>();
//        queryWrapper.lambda().eq(SysOrg::getSchoolId, schoolId);
//        if (Objects.nonNull(orgTypeEnum)) {
//            queryWrapper.lambda().eq(SysOrg::getType, orgTypeEnum);
//        }
//        queryWrapper.lambda().eq(SysOrg::getEnable, true);
//        if (orgIds.size() > 0) {
//            queryWrapper.lambda().in(SysOrg::getId, orgIds);
//        }
//        return this.list(queryWrapper);
    }

    @Override
    public List<SysOrg> findParentsByOrgId(Long orgId) {
        SysOrg sysOrg = this.getById(orgId);
        Long parentId = sysOrg.getParentId();
        List<SysOrg> result = new ArrayList<>();
        if (SystemConstant.longNotNull(parentId)) {
            result = this.findTopDFS(null, parentId);
        }
        return result;
    }

    @Override
    public Set<Long> findDeepOrgIdListByUserId(Long userId) {
        List<Long> orgIdList = sysUserService.findOrgIdListByUserId(userId);
        return this.findDeepOrgIdListByOrgIdList(orgIdList);
    }

    @Override
    public Set<Long> findDeepOrgIdListByOrgIdList(List<Long> orgIdList) {
        Set<Long> orgIdSet = new HashSet<>(orgIdList);
        Set<Long> finishedIdSet = this.findDeepDFS(new HashSet<>(), orgIdSet, new HashSet<>());

        // 加上他自己所在的机构
        finishedIdSet.addAll(orgIdSet);
        return finishedIdSet;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Long> createOrGetOrgByOrgInfo(List<String> orgInfoList, SysUser requestUser) {
        Map<String, Long> map = new HashMap<>();
        for (String orgInfo : orgInfoList) {
            // 父机构id
            Long schoolId = requestUser.getSchoolId();
            List<SysOrg> topLevelOrg = this.list(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSchoolId, schoolId).eq(SysOrg::getType, OrgTypeEnum.SCHOOL));
            if (topLevelOrg.size() != 1) {
                throw ExceptionResultEnum.ERROR.exception("顶级机构信息获取异常");
            }
            Long parentId = topLevelOrg.get(0).getId();

            String[] arr = orgInfo.split(SystemConstant.ORG_SPLIT);
            for (int i = 0; i < arr.length; i++) {
                SysOrg targetOrg;
                String orgDetailName = "";
                String orgName = arr[i];

                // 拼机构元素详细名称
                for (int j = 0; j <= i; j++) {
                    orgDetailName = orgDetailName + arr[j] + SystemConstant.ORG_SPLIT;
                }
                if (orgDetailName.length() > 0) {
                    orgDetailName = orgDetailName.substring(0, orgDetailName.length() - SystemConstant.ORG_SPLIT.length());
                }
                if (!map.containsKey(orgDetailName)) {
                    // 在map中没有找到，就去数据库查找
                    targetOrg = this.getOne(new QueryWrapper<SysOrg>()
                            .lambda()
                            .eq(SysOrg::getSchoolId, schoolId)
                            .eq(SysOrg::getName, orgName)
                            .eq(SysOrg::getParentId, parentId));

                    // 如果在数据库中也没有找到这个机构元素，则新建当前机构元素并保存在数据库
                    if (Objects.isNull(targetOrg)) {
                        targetOrg = this.saveOrgElement(parentId, orgName, requestUser);
                    }

                    // 不管是已有的还是新建的机构，都保存在map中方便后面查询 格式：（k -> 化学学院/核化学/聚变化学 v -> 11111111111）
                    map.put(orgDetailName, targetOrg.getId());
                    // 更新parentId为该机构元素的id，并作为数组下一个节点的父机构id
                    parentId = targetOrg.getId();
                } else {
                    // 如果map中本身就有该机构元素，则直接获取该机构元素id作为 数组下一个节点的父机构id
                    parentId = map.get(orgDetailName);
                }
            }
        }
        commonCacheService.updateOrgCollegeLevelCache(requestUser.getSchoolId());
        return map;
    }


    @Override
    public SysOrg findCollegeLevelOrgByOrgId(Long orgId) {
        if (!SystemConstant.longNotNull(orgId)) {
            throw ExceptionResultEnum.ERROR.exception("机构id不存在");
        }
        SysOrg result = null;
        List<SysOrg> orgList = this.findParentsByOrgId(orgId).stream().distinct().collect(Collectors.toList());
        // 加上自己
        orgList.add(this.getById(orgId));
        List<SysOrg> schoolOrgList = orgList.stream().filter(e -> OrgTypeEnum.SCHOOL.equals(e.getType())).collect(Collectors.toList());
        if (schoolOrgList.size() == 1) {
            SysOrg schoolOrg = schoolOrgList.get(0);
            Long schoolOrgId = schoolOrg.getId();
            List<SysOrg> collegeOrgList = orgList.stream().filter(e -> schoolOrgId.equals(e.getParentId())).collect(Collectors.toList());
            if (collegeOrgList.size() == 1) {
                result = collegeOrgList.get(0);
            }
        }
        return result;
    }

    @Override
    public List<SysOrg> findCollegeLevelOrgList(Long schoolId) {
        SysOrg schoolOrg = this.getOne(new QueryWrapper<SysOrg>()
                .lambda()
                .eq(SysOrg::getSchoolId, schoolId)
                .eq(SysOrg::getType, OrgTypeEnum.SCHOOL));

        Long schoolOrgId = schoolOrg.getId();

        return this.list(new QueryWrapper<SysOrg>()
                        .lambda()
                        .eq(SysOrg::getSchoolId, schoolId)
                        .eq(SysOrg::getParentId, schoolOrgId))
                .stream()
                .filter(e -> !OrgTypeEnum.PRINTING_HOUSE.equals(e.getType()))
                .collect(Collectors.toList());
    }

    @Override
    public void exportOrgData(HttpServletResponse response, boolean withoutPrintingRoom) throws Exception {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        List<SysOrgImportDto> sysOrgImportDtoList = new ArrayList<>();
        SysOrg schoolLevelOrg = this.getOne(new QueryWrapper<SysOrg>().lambda()
                .eq(SysOrg::getSchoolId, schoolId)
                .eq(SysOrg::getType, OrgTypeEnum.SCHOOL));
        if (Objects.isNull(schoolLevelOrg)) {
            throw ExceptionResultEnum.ERROR.exception("学校级机构不存在");
        }
        Long schoolLevelOrgId = schoolLevelOrg.getId();
        this.buildChildOrgInfoByParentId(schoolLevelOrgId, null, sysOrgImportDtoList);
        if (!withoutPrintingRoom) {
            // 需要导出印刷厂
            List<SysOrg> printHousesOrg = this.list(new QueryWrapper<SysOrg>()
                    .lambda()
                    .eq(SysOrg::getSchoolId, schoolId)
                    .eq(SysOrg::getParentId, schoolLevelOrgId)
                    .eq(SysOrg::getType, OrgTypeEnum.PRINTING_HOUSE));
            List<SysOrgImportDto> printHouses = printHousesOrg.stream().flatMap(e -> {
                SysOrgImportDto sysOrgImportDto = new SysOrgImportDto();
                sysOrgImportDto.setName(e.getName());
                return Stream.of(sysOrgImportDto);
            }).collect(Collectors.toList());
            sysOrgImportDtoList.addAll(printHouses);
        }
        // 生成excel文件
        ExcelUtil.excelExport("机构数据", SysOrgImportDto.class, sysOrgImportDtoList, response);
    }

    @Override
    public void executeImportSysOrgLogic(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(inputStream, Lists.newArrayList(SysOrgImportDto.class, DescribeImportDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> finalExcelList, 2);
            List<String> orgInfoList = new ArrayList<>();
            for (int i = 0; i < finalList.size(); i++) {
                LinkedMultiValueMap<Integer, Object> excelMap = finalList.get(i);
                List<Object> sysOrgImportDtoList = excelMap.get(i);
                //  处理机构
                if (CollectionUtils.isNotEmpty(sysOrgImportDtoList) && sysOrgImportDtoList.get(0) instanceof SysOrgImportDto) {
                    List<SysOrgImportDto> datasource = sysOrgImportDtoList.stream().map(e -> {
                        SysOrgImportDto sysOrgImportDto = new SysOrgImportDto();
                        BeanUtils.copyProperties(e, sysOrgImportDto);
                        return sysOrgImportDto;
                    }).collect(Collectors.toList());
                    if (datasource.size() > 0) {
                        datasource.forEach(e -> orgInfoList.add(e.getName()));
                    }
                }
            }
            if (orgInfoList.size() > 0) {
                SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
                this.createOrGetOrgByOrgInfo(orgInfoList, requestUser);
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof DataIntegrityViolationException || e instanceof BadSqlGrammarException) {
                String content = JdbcErrorUtil.parseErrorMsg(e.getMessage().toString());
                throw ExceptionResultEnum.SQL_ERROR.exception(content);
            } else if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
    }

    @Override
    public SysOrg findRootOrg(Long schoolId) {
        QueryWrapper<SysOrg> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysOrg::getSchoolId, schoolId)
                .eq(SysOrg::getType, OrgTypeEnum.SCHOOL);
        return this.getOne(queryWrapper);
    }

    @Override
    public SysOrg findCollegeByCourseCode(Long schoolId, String courseCode) {
        // 顶级机构
        SysOrg rootOrg = this.findRootOrg(schoolId);

        BasicCourse basicCourse = basicCourseService.findByCourseCode(courseCode, schoolId);

        List<SysOrg> sysOrgList = this.findByConnectByParentId(Long.valueOf(basicCourse.getTeachingRoomId()), false, false);
        if (sysOrgList.isEmpty()) {
            throw ExceptionResultEnum.ERROR.exception(String.format("未找到课程[%s（%s）]所属机构及上级机构", basicCourse.getName(), basicCourse.getCode()));
        }
        Optional<SysOrg> orgOptional = sysOrgList.stream().filter(m -> m.getParentId() != null && m.getParentId().equals(rootOrg.getId())).findFirst();
        if (!orgOptional.isPresent()) {
            throw ExceptionResultEnum.ERROR.exception(String.format("未找到课程[%s（%s）]所属学院", basicCourse.getName(), basicCourse.getCode()));
        }
        SysOrg collegeOrg = orgOptional.get();
        return collegeOrg;
    }

    @Override
    public SysOrg findCollegeByOrgId(Long schoolId, Long orgId) {
        // 顶级机构
        SysOrg rootOrg = this.findRootOrg(schoolId);

        List<SysOrg> sysOrgList = this.findByConnectByParentId(Long.valueOf(orgId), false, false);
        if (sysOrgList.isEmpty()) {
            return null;
        }
        Optional<SysOrg> orgOptional = sysOrgList.stream().filter(m -> rootOrg.getId().equals(m.getParentId())).findFirst();
        return orgOptional.isPresent() ? orgOptional.get() : null;
    }

    @Override
    public SysOrg findByCode(Long schoolId, String orgCode) {
        QueryWrapper<SysOrg> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysOrg::getSchoolId, schoolId)
                .eq(SysOrg::getCode, orgCode);
        return this.getOne(queryWrapper);
    }

    /**
     * 根据子机构id深度优先搜索其父机构们
     *
     * @param sysOrgList 目标父机构们
     * @param orgId      子机构id
     * @return 父亲们
     */
    private List<SysOrg> findTopDFS(List<SysOrg> sysOrgList, Long orgId) {
        if (CollectionUtils.isEmpty(sysOrgList)) {
            sysOrgList = new ArrayList<>();
        }
        SysOrg sysOrg = this.getById(orgId);
        if (Objects.isNull(sysOrg)) {
            throw ExceptionResultEnum.ERROR.exception("找不到机构");
        }
        sysOrgList.add(sysOrg);
        Long parentId = sysOrg.getParentId();
        if (SystemConstant.longNotNull(parentId)) {
            this.findTopDFS(sysOrgList, parentId);
        }
        return sysOrgList;
    }

    /**
     * 根据机构id集合深度搜索他们的子机构并且避免重复搜索（机构集合不在同一级导致的重复搜索）
     *
     * @param searchedIdSet 已经进行搜索过的机构id集合（标记）
     * @param targetIdSet   目标机构集合（下一级机构）
     * @param finishedIdSet 完成搜索的所有符合条件机构id集合（结果）
     * @return finishedIdSet
     */
    private Set<Long> findDeepDFS(Set<Long> searchedIdSet, Set<Long> targetIdSet, Set<Long> finishedIdSet) {
        for (Long targetId : targetIdSet) {
            if (!searchedIdSet.contains(targetId)) {
                Set<Long> orgIdSet = this.list(new QueryWrapper<SysOrg>()
                                .lambda()
                                .eq(SysOrg::getParentId, targetId))
                        .stream()
                        .map(SysOrg::getId)
                        .collect(Collectors.toSet());

                if (orgIdSet.size() > 0) {
                    searchedIdSet.add(targetId);
                    finishedIdSet.addAll(orgIdSet);
                    this.findDeepDFS(searchedIdSet, orgIdSet, finishedIdSet);
                }
            }
        }
        return finishedIdSet;
    }

    /**
     * 新增机构元素
     *
     * @param parentId    父机构id
     * @param orgName     机构名称
     * @param requestUser 请求用户
     * @return 新增后的机构id
     */
    private SysOrg saveOrgElement(Long parentId, String orgName, SysUser requestUser) {
        SysOrg checkOrg = this.getOne(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getName, orgName).eq(SysOrg::getSchoolId, requestUser.getSchoolId()));
        if (Objects.nonNull(checkOrg)) {
            // 数据库中存在该名字的机构
            SysOrg p1 = this.getById(checkOrg.getParentId());
            SysOrg p2 = this.getById(parentId);
            if (SystemConstant.isOneNull(p1, p2)) {
                throw ExceptionResultEnum.ERROR.exception("未找到父机构");
            }
            throw ExceptionResultEnum.ERROR.exception("机构创建失败：机构[" + orgName + "]存在多个不同的上级机构 " +
                    "-> 已存在机构关系[..." + p1.getName() + SystemConstant.ORG_SPLIT + orgName + "...]，却又创建机构关系[..." + p2.getName() + SystemConstant.ORG_SPLIT + orgName + "...]");
        }

        SysOrg sysOrg = new SysOrg();
        sysOrg.setSchoolId(requestUser.getSchoolId());
        sysOrg.insertInfo(requestUser.getId());
        sysOrg.setParentId(parentId);
        sysOrg.setName(orgName);
        sysOrg.setEnable(true);

        SysOrg sysOrgRoot = this.getOne(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSchoolId, requestUser.getSchoolId()).eq(SysOrg::getType, OrgTypeEnum.SCHOOL));
        // 学校下第一级机构，自动生成code
        if (sysOrgRoot != null && parentId.equals(sysOrgRoot.getId())) {
            Integer maxOrgCode = commonCacheService.getMaxOrgCode(sysOrg.getSchoolId());
            Integer currentCode = maxOrgCode + 1;
            commonCacheService.setMaxOrgCode(sysOrg.getSchoolId(), currentCode);
            sysOrg.setCode(SystemConstant.ORG_PREFIX + currentCode);
        }
        this.save(sysOrg);

        return sysOrg;
    }

    /**
     * 根据父机构id构建该父机构下所有子机构信息集合
     *
     * @param parentId   父机构id
     * @param parentInfo 父机构信息
     * @param result     子机构信息结果集
     */
    private void buildChildOrgInfoByParentId(Long parentId, String parentInfo, List<SysOrgImportDto> result) {
        if (SystemConstant.longNotNull(parentId)) {
            List<SysOrg> childOrgList = this.list(new QueryWrapper<SysOrg>().lambda()
                            .eq(SysOrg::getParentId, parentId))
                    .stream()
                    .filter(e -> !OrgTypeEnum.PRINTING_HOUSE.equals(e.getType()))
                    .collect(Collectors.toList());
            for (SysOrg child : childOrgList) {
                String orgInfo = child.getName();
                if (SystemConstant.strNotNull(parentInfo)) {
                    orgInfo = parentInfo + SystemConstant.ORG_SPLIT + orgInfo;
                }
                SysOrgImportDto sysOrgImportDto = new SysOrgImportDto();
                sysOrgImportDto.setName(orgInfo);
                result.add(sysOrgImportDto);
                this.buildChildOrgInfoByParentId(child.getId(), orgInfo, result);
            }
        }
    }
}
