package com.chushang.system.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chushang.common.core.exception.ResultException;
import com.chushang.common.core.text.Convert;
import com.chushang.common.core.util.StringUtils;
import com.chushang.common.mybatis.enums.Operator;
import com.chushang.datascope.constants.ScopeConstants;
import com.chushang.datascope.enums.ScopeKeyWord;
import com.chushang.system.entity.dto.ListDeptDTO;
import com.chushang.system.entity.po.SysDept;
import com.chushang.system.entity.vo.TreeSelect;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <p>
 * 部门用于控制各平台的数据权限 服务类
 * </p>
 *
 * @author author
 * @since 2022-08-18
 */
public interface ISysDeptService extends IService<SysDept> {

    List<SysDept> selectDeptList(ListDeptDTO listDept);

    void checkDeptDataScope(Long deptId);

    List<TreeSelect> buildDeptTreeSelect(List<SysDept> deptList);

    List<SysDept> buildDeptTree(List<SysDept> deptList);

    List<Long> selectDeptListByRoleId(Long roleId);

    default boolean checkDeptNameUnique(SysDept dept){
        long deptId = StringUtils.isNull(dept.getDeptId()) ? -1 : dept.getDeptId();
        SysDept info = getOne(new LambdaQueryWrapper<SysDept>()
                .eq(SysDept::getDeptName, dept.getDeptName())
                .eq(SysDept::getParentId, dept.getParentId())
                .last(Operator.LIMIT_ONE.getCharacter()));
        return StringUtils.isNotNull(info) && info.getDeptId() != deptId;
    }

    default long selectNormalChildrenDeptById(Long deptId){
        return count(new LambdaQueryWrapper<SysDept>()
                .eq(SysDept::getStatus, Boolean.FALSE)
                .apply("find_in_set({0}, ancestors)", deptId));
    }

    default boolean hasChildByDeptId(Long deptId){
        return count(new LambdaQueryWrapper<SysDept>()
                .eq(SysDept::getParentId, deptId)
        ) > 0;
    }

    boolean checkDeptExistUser(Long deptId);

    default void add(SysDept dept){
        SysDept info = getById(dept.getParentId());
        // 如果父节点不为正常状态,则不允许新增子节点
        if (!info.getStatus())
        {
            throw new ResultException("部门停用，不允许新增");
        }
        dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
        save(dept);
    }

    default void updateDept(SysDept dept){
        SysDept newParentDept = getById(dept.getParentId());
        SysDept oldDept = getById(dept.getDeptId());
        if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept))
        {
            String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId();
            String oldAncestors = oldDept.getAncestors();
            dept.setAncestors(newAncestors);
            updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
        }

        updateById(dept);

        if (dept.getStatus() && StringUtils.isNotEmpty(dept.getAncestors())
                && !StringUtils.equals("0", dept.getAncestors()))
        {
            // 如果该部门是启用状态，则启用该部门的所有上级部门
            updateParentDeptStatusNormal(dept);
        }
    }

    default void updateParentDeptStatusNormal(SysDept dept)
    {
        String ancestors = dept.getAncestors();
        Integer[] deptIds = Convert.toIntArray(ancestors);
        updateDeptStatusNormal(deptIds);
    }

    default void updateDeptStatusNormal(Integer[] deptIds) {
        SysDept sysDept = new SysDept();
        sysDept.setStatus(true);
        update(sysDept, new LambdaQueryWrapper<SysDept>()
                .in(SysDept::getDeptId, List.of(deptIds)));
    }

    default void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors){
        List<SysDept> children = selectChildrenDeptById(deptId);
        for (SysDept child : children)
        {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (!children.isEmpty())
        {
            updateDeptChildren(children);
        }
    }

    default List<SysDept> selectChildrenDeptById(Long deptId){
        return list(new LambdaQueryWrapper<SysDept>()
                        .apply(" find_in_set({0}, ancestors)", deptId));
    }

    void updateDeptChildren(List<SysDept> children);

    List<String> listScopeDeptIdByRoleId(Long roleId);

    List<String> listScopeDeptIdByDeptId(Long deptId);
}
