package com.bcxin.tenant.domain.services.impls;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import com.bcxin.Infrastructures.UnitWork;
import com.bcxin.Infrastructures.components.EventDispatcher;
import com.bcxin.Infrastructures.components.JsonProvider;
import com.bcxin.Infrastructures.components.RetryProvider;
import com.bcxin.Infrastructures.enums.DepartImPermissionType;
import com.bcxin.Infrastructures.enums.EmploymentStatus;
import com.bcxin.Infrastructures.enums.ProcessedStatus;
import com.bcxin.Infrastructures.exceptions.*;
import com.bcxin.Infrastructures.utils.ExceptionUtil;
import com.bcxin.tenant.domain.DomainConstraint;
import com.bcxin.tenant.domain.entities.DepartmentEmployeeRelationEntity;
import com.bcxin.tenant.domain.entities.DepartmentEntity;
import com.bcxin.tenant.domain.entities.ImportDataEntity;
import com.bcxin.tenant.domain.entities.OrganizationEntity;
import com.bcxin.tenant.domain.enums.ImportedDataCategory;
import com.bcxin.tenant.domain.events.DepartmentCreatedEvent;
import com.bcxin.tenant.domain.events.DepartmentDeleteEvent;
import com.bcxin.tenant.domain.events.DepartmentUpdatedEvent;
import com.bcxin.tenant.domain.exceptions.TenantExceptionConverter;
import com.bcxin.tenant.domain.readers.TenantDbReader;
import com.bcxin.tenant.domain.repositories.*;
import com.bcxin.tenant.domain.services.DepartmentService;
import com.bcxin.tenant.domain.services.commands.*;
import com.bcxin.tenant.domain.services.commands.results.ImportDepartmentCommandResult;
import com.bcxin.tenant.domain.snapshots.DepartImAllowedDepartSnapshot;
import com.bcxin.tenant.domain.snapshots.DepartmentImportedItemResultSnapshot;
import com.bcxin.tenant.domain.snapshots.DepartmentImportedItemSnapshot;
import com.bcxin.tenant.domain.snapshots.DepartmentImportedResultSnapshot;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
public class DepartmentServiceImpl implements DepartmentService {
    private final OrganizationRepository organizationRepository;
    private final DepartmentRepository departmentRepository;
    private final DepartmentEmployeeRelationRepository departmentEmployeeRelationRepository;
    private final JsonProvider jsonProvider;
    private final UnitWork unitWork;
    private final RetryProvider retryProvider;
    private final ImportDataEntityRepository importDataEntityRepository;
    private final EventDispatcher eventDispatcher;
    private final TenantDbReader dbReader;
    private final DepartmentAdminRepository departmentAdminRepository;

    public DepartmentServiceImpl(OrganizationRepository organizationRepository,
                                 DepartmentRepository departmentRepository,
                                 DepartmentEmployeeRelationRepository departmentEmployeeRelationRepository,
                                 JsonProvider jsonProvider,
                                 UnitWork unitWork, RetryProvider retryProvider,
                                 ImportDataEntityRepository importDataEntityRepository,
                                 EventDispatcher eventDispatcher,
                                 TenantDbReader dbReader,
                                 DepartmentAdminRepository departmentAdminRepository) {
        this.organizationRepository = organizationRepository;
        this.departmentRepository = departmentRepository;
        this.departmentEmployeeRelationRepository = departmentEmployeeRelationRepository;
        this.jsonProvider = jsonProvider;
        this.unitWork = unitWork;
        this.retryProvider = retryProvider;
        this.importDataEntityRepository = importDataEntityRepository;
        this.eventDispatcher = eventDispatcher;
        this.dbReader = dbReader;
        this.departmentAdminRepository = departmentAdminRepository;
    }

    /**
     * 新增部门,
     * 父部门不能为空
     * @param command
     * @return
     */
    @Override
    public String create(DepartmentCommand command) {
        command.validate();
        Optional<OrganizationEntity> organizationOptional = this.organizationRepository.findById(command.getOrganizationId());
        if (!organizationOptional.isPresent()) {
            throw new NotFoundTenantException(String.format("组织(%s)无效!", command.getOrganizationId()));
        }

        if (!StringUtils.hasLength(command.getParentId())) {
            throw new BadTenantException("父部门不能为空");
        }

        Collection<String> departIds = new ArrayList<>();
        if (StringUtils.hasLength(command.getParentId())) {
            departIds.add(command.getParentId());
        }

        if (!CollectionUtils.isEmpty(command.getAllowedDepartIds())) {
            departIds.addAll(command.getAllowedDepartIds());
        }
        Collection<DepartmentEntity> existsDepartments = this.getAndValidateDepartment(command.getOrganizationId(), departIds);

        DepartmentEntity parentDepartment = existsDepartments.stream().filter(ii -> ii.getId().equalsIgnoreCase(command.getParentId())).findFirst().get();

        DepartmentEntity department = DepartmentEntity.create(organizationOptional.get(), parentDepartment, command.getName(), command.getCode(), command.getDisplayOrder());

        DepartImAllowedDepartSnapshot snapshot = DepartImAllowedDepartSnapshot.create(command.getAllowedDepartIds());
        department.change(command.getPermissionType(), snapshot, jsonProvider);

        try {
            this.unitWork.executeTran(() -> {
                this.departmentRepository.save(department);

                this.eventDispatcher.dispatch(DepartmentCreatedEvent.create(department));
            });
            return department.getId();
        } catch (Exception ex) {
            if (DomainConstraint.isUniqueConstraintIssue(ex)) {
                throw new ConflictTenantException("该部门名称已经存在!");
            }

            throw ex;
        }
    }

    /**
     * 修改部门
     *  顶级不能不能设置父部门
     *  不能将子孙部门设置为该部门的父部门
     * @param id
     * @param command
     */
    @Override
    public void update(String id, DepartmentCommand command) {
        command.validate();
        if (!StringUtils.hasLength(id) || !StringUtils.hasLength(command.getOrganizationId())) {
            throw new BadTenantException("无效数据!");
        }

        Collection<String> departIds = new ArrayList<>();
        departIds.add(id);
        if (StringUtils.hasLength(command.getParentId())) {
            departIds.add(command.getParentId());
        }

        if (!CollectionUtils.isEmpty(command.getAllowedDepartIds())) {
            departIds.addAll(command.getAllowedDepartIds());
        }

        Collection<DepartmentEntity> existsDepartments = this.getAndValidateDepartment(command.getOrganizationId(), departIds);
        Optional<DepartmentEntity> departmentOptional = existsDepartments.stream().filter(ii -> ii.getId().equalsIgnoreCase(id)).findFirst();
        if (!departmentOptional.isPresent()) {
            throw new BadTenantException("当前部门已被删除, 请刷新后再试");
        }
        DepartmentEntity department = departmentOptional.get();

        List<String> leaderEmployeeIdList = command.getLeaderEmployeeIdList();
        if (CollectionUtil.isNotEmpty(leaderEmployeeIdList) && !leaderEmployeeIdList.contains("null")) {
            //如果主管的职员id不为空（含有null是内网使用，不包含）
            List<DepartmentEmployeeRelationEntity> relationEntityList = departmentEmployeeRelationRepository.findListByDepartmentIdAndEmployeeIds(department.getId(), leaderEmployeeIdList);
            if (CollectionUtil.isEmpty(relationEntityList)) {
                throw new BadTenantException("所选的职员都不在本部门里面，请重新选择部门主管");
            }
            if (relationEntityList.size() != leaderEmployeeIdList.size()) {
                throw new BadTenantException("所选的职员，存在不在本部门里面，请重新选择部门主管");
            }
        }

        department.change(command.getName(), command.getDisplayOrder());
        DepartImAllowedDepartSnapshot snapshot = DepartImAllowedDepartSnapshot.create(command.getAllowedDepartIds());
        department.change(command.getPermissionType(), snapshot, jsonProvider);

        boolean isChangeParent = false;
        String oldTree = department.getIndexTree();
        String newTree = "";
        String organizationId = command.getOrganizationId();
        if (StringUtils.hasLength(command.getParentId())) {
            if (!command.getParentId().equals(department.getParent().getId())) {
                //如果父级节点有变更
                isChangeParent = true;
            }

            DepartmentEntity parentDepartment = existsDepartments.stream()
                    .filter(ii -> ii.getId().equalsIgnoreCase(command.getParentId())).findFirst().get();
            department.changeSubNodeParent(parentDepartment);

            if (isChangeParent) {
                newTree = department.getIndexTree();
            }
        }

        try {
            boolean finalIsChangeParent = isChangeParent;
            String finalNewTree = newTree;
            this.unitWork.executeTran(() -> {
                this.departmentRepository.save(department);

                this.eventDispatcher.dispatch(DepartmentUpdatedEvent.create(department));

                if (finalIsChangeParent) {
                    //修改部门层级，同步修改子部门的indexTree、部门职员关联表的indexTree、部门管理员的indexTree
                    departmentRepository.updateTreeByDepartmentIndexTree1(oldTree, finalNewTree, organizationId, oldTree.concat("%"));
                    departmentRepository.updateTreeByDepartmentIndexTree2(oldTree, finalNewTree, organizationId, oldTree.concat("%"));
                    departmentRepository.updateTreeByDepartmentIndexTree3(oldTree, finalNewTree, organizationId, oldTree.concat("%"));
                }

                //先清除部门主管，再设置新的
                if (CollectionUtil.isEmpty(leaderEmployeeIdList) || !leaderEmployeeIdList.contains("null")) {
                    departmentEmployeeRelationRepository.updateLeaderTypeFalseByDepartmentId(department.getId());
                    if (CollectionUtil.isNotEmpty(leaderEmployeeIdList)) {
                        departmentEmployeeRelationRepository.updateLeaderTypeTrueByDepartmentIdAndEmployeeIds(department.getId(), leaderEmployeeIdList);
                    }
                }

            });
        } catch (Exception ex) {
            if (DomainConstraint.isUniqueConstraintIssue(ex)) {
                throw new ConflictTenantException("该部门名称已经存在!");
            }

            throw ex;
        }
    }

    @Override
    public void delete(DeleteDepartmentCommand command) {
        DepartmentEntity department =
                this.getDepartment(command.getId(), command.getOrganizationId(), false);

        boolean hasChildNode = false;
        if (department.getDepartmentEmployeeRelations().size() > 0
        && department.getDepartmentEmployeeRelations().stream().anyMatch(ix -> !EmploymentStatus.OffJob.equals(ix.getEmployee().getStatus()))) {
            hasChildNode = true;
        } else if (department.getChildren().size() > 0) {
            hasChildNode = true;
        }

        if (hasChildNode) {
            throw new NotAllowedTenantException("请确保删除子部门或者成员之后, 再进行该部门的删除!");
        }

        this.unitWork.executeTran(() -> {
            this.departmentRepository.deleteByIds(command.getOrganizationId(), ListUtil.toList(department.getId()));
            this.eventDispatcher.dispatch(DepartmentDeleteEvent.create(department.getId()));
        });
    }

    @Override
    public ImportDepartmentCommandResult batchImport(ImportDepartmentCommand command) {
        Optional<OrganizationEntity> organizationOptional = this.organizationRepository.findById(command.getOrganizationId());
        if (!organizationOptional.isPresent()) {
            throw new NotFoundTenantException("组织无效!");
        }
        OrganizationEntity organization = organizationOptional.get();

        Collection<DepartmentEntity> wholeDepartments = this.departmentRepository.getAllByOrganId(organization.getId());

        AtomicReference<ImportDepartmentCommandResult> result = new AtomicReference<>();
        this.retryProvider.execute(() -> {
            ImportDepartmentCommandResult r = this.buildChildDepartment(organization, wholeDepartments, command);
            result.set(r);
        }, 3);


        return result.get();
    }

    @Override
    public void dispatch(ChangeDepartmentDisplayOrderCommand command) {
        DepartmentEntity department = this.getDepartment(command.getId(), command.getOrganizationId(), false);
        department.change(department.getName(), command.getDisplayOrder());

        this.unitWork.executeTran(()->{
            this.departmentRepository.save(department);
        });
    }

    @Override
    public void dispatch(BatchAssignImPermissionCommand command) {
        command.validate();

        Collection<String> selectedDepartIds = new ArrayList<>();
        selectedDepartIds.addAll(command.getDepartIds());
        if (command.getPermissionType() == DepartImPermissionType.Special) {
            selectedDepartIds.addAll(command.getAllowedDepartIds());
        }

        Collection<DepartmentEntity> allSelectedDepartments =
                this.departmentRepository.getByIds(command.getOrganizationId(), selectedDepartIds);

        Collection<String> notExistsDepartIds =
                selectedDepartIds.stream().filter(ii -> !allSelectedDepartments.stream().anyMatch(ix -> ix.getId().equals(ii)))
                        .collect(Collectors.toList());
        if (notExistsDepartIds.size() > 0) {
            throw new BadTenantException(String.format("选择的部门(%s)列表无效", notExistsDepartIds.stream().collect(Collectors.joining(","))));
        }

        Collection<DepartmentEntity> departments = allSelectedDepartments.stream().filter(ii ->
                        command.getDepartIds().stream().anyMatch(ix -> ix.equals(ii.getId())))
                .collect(Collectors.toList());

        DepartImAllowedDepartSnapshot snapshot = DepartImAllowedDepartSnapshot.create(command.getAllowedDepartIds());
        this.unitWork.executeTran(() -> {
            departments.forEach(dept -> {
                dept.change(command.getPermissionType(), snapshot, this.jsonProvider);
                this.departmentRepository.save(dept);
            });
        });
    }

    @Override
    public void dispatch(BatchMoveDepartEmployeeCommand command) {
        if (CollectionUtils.isEmpty(command.getFromDepartIds())) {
            throw new BadTenantException("要转移的部门列表不能为空!");
        }

        if (!StringUtils.hasLength(command.getDestDepartId())) {
            throw new BadTenantException("目标部门不能为空!");
        }

        if (command.getFromDepartIds().contains(command.getDestDepartId())) {
            throw new BadTenantException("目标部门不能包含在要转移的源部门中!");
        }

        Collection<String> ids = command.getFromDepartIds()
                .stream().collect(Collectors.toList());
        ids.add(command.getDestDepartId());

        Collection<DepartmentEntity> departments =
                this.departmentRepository.getByIds(command.getOrganizationId(), ids);

        Optional<DepartmentEntity> destOptional = departments.stream().filter(ii -> ii.getId().equals(command.getDestDepartId())).findFirst();
        if (!destOptional.isPresent()) {
            throw new NotFoundTenantException("转移目标部门不存在!", command.getDestDepartId());
        }

        Collection<String> missedDepartIds =
                command.getFromDepartIds().stream().filter(ii -> !departments.stream().anyMatch(ix -> ix.getId().equals(ii)))
                        .collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(missedDepartIds)) {
            throw new NotFoundTenantException("找不到源部门信息", missedDepartIds);
        }

        DepartmentEntity destDepartment = destOptional.get();
        Collection<DepartmentEntity> sourceDepartments = departments.stream()
                .filter(ii -> command.getFromDepartIds().contains(ii.getId()))
                .collect(Collectors.toList());

        this.retryProvider.execute(() -> {
            try {
                this.unitWork.executeTran(() -> {
                    destDepartment.moveEmployeesFrom(sourceDepartments);
                    for (DepartmentEntity department : departments) {
                        this.departmentRepository.save(department);
                    }
                });
            } catch (Exception ex) {
                TenantExceptionAbstract exceptionAbstract = TenantExceptionConverter.cast(ex);
                if (exceptionAbstract instanceof ConflictTenantException) {
                    /*
                    for (DepartmentEntity department : departments) {
                        this.unitWork.detach(department);
                    }
                     */
                    this.unitWork.detachAll();

                    String detailMsg = ExceptionUtil.getStackMessage(ex);
                    if (detailMsg.contains(DomainConstraint.UNIQUE_DEPARTMENT_EMPLOYEE_RELATION_DEPARTMENT_EMPLOYEE)) {
                        Collection<String> employeeRelationIds =
                                this.dbReader.getDuplicatedEmployeeRelationIds(command.getFromDepartIds(), command.getDestDepartId());
                        if (employeeRelationIds.size() > 0) {
                            this.unitWork.executeNewTran(() -> {
                                this.departmentRepository.clearDuplicatedEmployeeRelationIds(employeeRelationIds);
                            });

                            throw new RetryableTenantException("用户已经再该部门, 无法重复转移, 请进行删除", ex);
                        }
                    }
                }

                throw exceptionAbstract;
            }
        }, 2);
    }

    @Override
    public void dispatch(BatchDeleteDepartmentCommand command) {
        if(!StringUtils.hasLength(command.getOrganizationId())) {
            throw new BadTenantException(String.format("所在组织(%s)无效!",command.getOrganizationId()));
        }

        if(CollectionUtils.isEmpty(command.getDepartIds())) {
            throw new BadTenantException("要删除的部门列表不能为空!");
        }

        try {
            Collection<DepartmentEntity> departmentEntities = this.departmentRepository.getByIds(command.getOrganizationId(), command.getDepartIds());
            Collection<String> notExistsDepartIds = command.getDepartIds().stream().filter(ii -> !departmentEntities.stream().anyMatch(ix -> ix.getId().equals(ii)))
                    .collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(notExistsDepartIds)) {
                throw new BadTenantException(String.format("无法找到部门(%s)信息, 请刷新后再试!", notExistsDepartIds.stream().collect(Collectors.joining(";"))));
            }

            Optional<DepartmentEntity> rootDepartOptional = departmentEntities.stream().filter(ii->ii.getLevel()==0)
                    .findFirst();
            if(rootDepartOptional.isPresent()) {
                throw new BadTenantException(String.format("不允许删除顶级部门(%s)", rootDepartOptional.get().getName()));
            }

            for (DepartmentEntity department : departmentEntities) {
                if (department.getDepartmentEmployeeRelations().size() > 0
                        && department.getDepartmentEmployeeRelations().stream().anyMatch(ix -> !EmploymentStatus.OffJob.equals(ix.getEmployee().getStatus()))) {
                    throw new NotAllowedTenantException(String.format("删除部门【(%s)】之前，请先确保转移部门成员!", department.getName()));
                } else if (department.getChildren().size() > 0) {
                    throw new NotAllowedTenantException(String.format("删除部门【(%s)】之前，请先确保转移其子部门关系!", department.getName()));
                }
            }

            this.unitWork.executeTran(() -> {
                Collection<String> departmentIds = departmentEntities.stream().map(DepartmentEntity::getId).collect(Collectors.toList());
                this.departmentRepository.clearDepartmentAdminByDepartIds(departmentIds);
                this.departmentRepository.deleteByIds(command.getOrganizationId(),departmentIds);
            });
        } catch (Exception ex) {
            if (ex.toString().contains("DataIntegrity")) {
                throw new BadTenantException("删除部门之前，请先确保转移部门成员及其子部门关系", ex);
            }

            if(ex instanceof TenantExceptionAbstract) {
                throw ex;
            }

            ex.printStackTrace();
            throw new BadTenantException("系统异常, 请联系管理员");
        }
    }

    private DepartmentEntity getDepartment(String id, String organizationId, boolean isAllowedIdEmpty) {
        if (!StringUtils.hasLength(id)) {
            if (isAllowedIdEmpty) {
                return null;
            } else {
                throw new NotFoundTenantException("部门不能为空!");
            }
        }

        Optional<DepartmentEntity> departmentOptional = this.departmentRepository.findById(id);
        if (!departmentOptional.isPresent()) {
            throw new NotFoundTenantException(String.format("找不到部门(%s)信息!", id));
        }

        DepartmentEntity department = departmentOptional.get();
        if (department.getOrganization() == null || !department.getOrganization().getId().equals(organizationId)) {
            throw new NotAllowedTenantException();
        }

        return department;
    }

    private ImportDepartmentCommandResult buildChildDepartment(
            OrganizationEntity organization,
            Collection<DepartmentEntity> existsDepartments,
            ImportDepartmentCommand command) {

        List<DepartmentImportedItemSnapshot>
                sortedChildDepartmentItems = command.getItems().stream()
                .sorted((t1, t2) -> t1.getTreeDepth() - t2.getTreeDepth()).collect(Collectors.toList());

        Collection<DepartmentEntity> existsAndNewDepartments = new ArrayList<>();
        existsAndNewDepartments.addAll(existsDepartments);

        Collection<DepartmentImportedItemResultSnapshot> processedDetails = new ArrayList<>();

        Collection<DepartmentEntity> newDepartments = new ArrayList<>();
        ImportDataEntity importDataEntity = ImportDataEntity.create(
                organization.getId(),
                command.getPath(),
                ImportedDataCategory.Department);

        for (DepartmentImportedItemSnapshot item : sortedChildDepartmentItems) {

            Collection<String> invalidLogs = new ArrayList<>();
            try {
                if (!StringUtils.hasLength(item.getName())) {
                    invalidLogs.add("部门名称不能为空");
                }

                DepartmentEntity matchedParentDepartment = this.getDepartmentByTreeName(existsAndNewDepartments, item.getParentTreeName());
                if (matchedParentDepartment == null) {
                    invalidLogs.add(String.format("父部门(%s)无效", item.getParentTreeName()));
                }

                int displayOrder = 0;
                if (StringUtils.hasLength(item.getDisplayOrder())) {
                    try {
                        displayOrder = Integer.parseInt(item.getDisplayOrder());
                    } catch (Exception ex) {
                        invalidLogs.add("排序无效");
                    }
                }
                DepartImPermissionType permissionType = null;
                try {
                    permissionType = translate2PermissionType(item.getPermissionType());
                } catch (Exception ex) {
                    invalidLogs.add(ex.getMessage());
                }

                if (invalidLogs.size() == 0) {
                    DepartmentEntity newDepartment = DepartmentEntity.create(organization, matchedParentDepartment, item.getName(), null, displayOrder);
                    //DepartmentEntity newDepartment = matchedParentDepartment.addChild(item.getName(), displayOrder);
                    newDepartment.change(permissionType, DepartImAllowedDepartSnapshot.create(Collections.EMPTY_LIST), jsonProvider);
                    //this.departmentRepository.save(newDepartment);
                    existsAndNewDepartments.add(newDepartment);
                    newDepartments.add(newDepartment);
                }
            } catch (Exception ex) {
                invalidLogs.add(ex.getMessage());
                ex.printStackTrace();
            } finally {
                processedDetails.add(DepartmentImportedItemResultSnapshot.create(item, invalidLogs));
                ProcessedStatus status = ProcessedStatus.Done;
                String message = "导入成功";
                if (!CollectionUtils.isEmpty(invalidLogs)) {
                    status = ProcessedStatus.Error;
                    message = invalidLogs.stream().collect(Collectors.joining(";"));
                }
                importDataEntity.addProcessedDataItem(this.jsonProvider.getJson(item), status, message);
            }
        }

        DepartmentImportedResultSnapshot result = DepartmentImportedResultSnapshot.create(processedDetails);

        try {
            this.unitWork.executeTran(() -> {
                this.importDataEntityRepository.save(importDataEntity);

                newDepartments.forEach(di -> {
                    this.departmentRepository.save(di);
                    this.eventDispatcher.dispatch(DepartmentCreatedEvent.create(di));
                });
            });
        } catch (Exception ex) {
            newDepartments.forEach(di -> {
                this.unitWork.detach(di);
            });
            this.unitWork.detach(importDataEntity);
        }

        return ImportDepartmentCommandResult.create(importDataEntity.getId(), result);
    }

    private DepartmentEntity getDepartmentByTreeName(Collection<DepartmentEntity> wholeDepartments, String parentTreeName) {
        Optional<DepartmentEntity> rootOptional = wholeDepartments.stream().filter(ii -> ii.getParent() == null).findFirst();
        if (!rootOptional.isPresent()) {
            throw new BadTenantException("企业部门体系异常，找不到顶级部门，请联系管理员");
        }

        DepartmentEntity root = rootOptional.get();
        if (!StringUtils.hasLength(parentTreeName)) {
            return root;
        }

        Optional<DepartmentEntity> matchedDepartmentOptional = wholeDepartments.stream().filter(ii -> {
            boolean flag = parentTreeName.equalsIgnoreCase(ii.getName()) ||
                    parentTreeName.endsWith(String.format("/%s", ii.getName()));

            return flag;
        }).findFirst();

        if (!matchedDepartmentOptional.isPresent()) {
            throw new BadTenantException(String.format("找不到父部门(%s)信息(由于数据权限问题, 有可能你无法看到顶级部门, 因此导致该错误)", parentTreeName));
        }

        DepartmentEntity matchedDepartment = matchedDepartmentOptional.get();
        StringBuilder fullPathName = new StringBuilder();
        DepartmentEntity loopDepartment = matchedDepartment;
        int index = 0;
        while (loopDepartment != null) {
            if (index > 0) {
                fullPathName.insert(0, "/");
            }

            fullPathName.insert(0, loopDepartment.getName());

            index++;
            loopDepartment = loopDepartment.getParent();
        }

        if (!fullPathName.toString().equals(parentTreeName)) {
            throw new BadTenantException(String.format("找不到父部门(%s)信息", parentTreeName));
        }

        return matchedDepartment;
    }

    private String getDepartmentTreeName(DepartmentEntity department) {
        if (department == null) {
            return null;
        }

        if (department.getParent() == null) {
            return department.getName();
        }

        return String.format("%s/%s", getDepartmentTreeName(department.getParent()), department.getName());
    }

    private Collection<DepartmentEntity> getAndValidateDepartment(String organizationId,  Collection<String> selectedDepartIds) {
        Collection<String> departIds = new ArrayList<>();
        if (selectedDepartIds != null) {
            departIds.addAll(selectedDepartIds);
        }

        if (CollectionUtils.isEmpty(departIds)) {
            return Collections.EMPTY_LIST;
        }

        Collection<DepartmentEntity> departmentEntities = this.departmentRepository.getByIds(organizationId, departIds);
        Collection<String> invalidDepartIds = departIds.stream().filter(ii -> !departmentEntities.stream().anyMatch(ix -> ix.getId().equalsIgnoreCase(ii)))
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(invalidDepartIds)) {
            throw new ArgumentTenantException(String.format("选择的部门(%s)信息不存在", invalidDepartIds.stream().collect(Collectors.joining(","))));
        }


        return departmentEntities;
    }

    private static DepartImPermissionType translate2PermissionType(String permissionText) {
        if (!StringUtils.hasLength(permissionText)) {
            return DepartImPermissionType.JustOnDepart;
        }
        permissionText = permissionText.replace(" ", "");
        switch (permissionText) {
            case "可见所在部门成员":
                return DepartImPermissionType.JustOnDepart;
            case "可见所在部门及下级部门成员":
                return DepartImPermissionType.OnDepartAndSub;
            case "可见自己":
                return DepartImPermissionType.JustSelf;
            case "可见全部成员":
                return DepartImPermissionType.Whole;
            case "可见指定部门":
                return DepartImPermissionType.Special;
        }

        throw new BadTenantException(String.format("部门成员通讯录权限配置(%s)信息无效", permissionText));
    }
}
