package com.inspect.system.service.impl;

import com.inspect.base.core.exception.ServiceException;
import com.inspect.base.core.text.Convert;
import com.inspect.base.core.utils.SpringUtils;
import com.inspect.base.core.utils.StringUtils;
import com.inspect.common.aspect.annotation.DataScope;
import com.inspect.common.security.utils.SecurityUtils;
import com.inspect.system.base.domain.SysDept;
import com.inspect.system.base.domain.SysRole;
import com.inspect.system.base.domain.SysUser;
import com.inspect.system.domain.vo.TreeSelect;
import com.inspect.system.mapper.SysDeptMapper;
import com.inspect.system.mapper.SysRoleMapper;
import com.inspect.system.service.ISysDeptService;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SysDeptServiceImpl implements ISysDeptService {
    @Autowired
    private SysDeptMapper deptMapper;
    @Autowired
    private SysRoleMapper roleMapper;

    @DataScope(
            deptAlias = "d"
    )
    public List<SysDept> selectDeptList(SysDept dept) {
        return this.deptMapper.selectDeptList(dept);
    }

    public List buildDeptTree(List<SysDept> sysDeptList) {
        List<SysDept> returnList = new ArrayList<>();
        List<Long> tempList = new ArrayList<>();
        Iterator<SysDept> iterator = sysDeptList.iterator();
        SysDept dept;
        while (iterator.hasNext()) {
            dept = iterator.next();
            tempList.add(dept.getDeptId());
        }

        iterator = sysDeptList.iterator();
        while (iterator.hasNext()) {
            dept = iterator.next();
            if (!tempList.contains(dept.getParentId())) {
                this.recursionFn(sysDeptList, dept);
                returnList.add(dept);
            }
        }

        if (returnList.isEmpty()) {
            returnList = sysDeptList;
        }

        return returnList;
    }

    public List buildDeptTreeSelect(List<SysDept> sysDeptList) {
        List<SysDept> deptTrees = buildDeptTree(sysDeptList);
        return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    public List<Long> selectDeptListByRoleId(Long roleId) {
        SysRole role = this.roleMapper.selectRoleById(roleId);
        return this.deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());
    }

    public SysDept selectDeptById(Long deptId) {
        return this.deptMapper.selectDeptById(deptId);
    }

    public int selectNormalChildrenDeptById(Long deptId) {
        return this.deptMapper.selectNormalChildrenDeptById(deptId);
    }

    public boolean hasChildByDeptId(Long deptId) {
        int result = this.deptMapper.hasChildByDeptId(deptId);
        return result > 0;
    }

    public boolean checkDeptExistUser(Long deptId) {
        int result = this.deptMapper.checkDeptExistUser(deptId);
        return result > 0;
    }

    public String checkDeptNameUnique(SysDept dept) {
        Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId();
        SysDept info = this.deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId());
        return StringUtils.isNotNull(info) && info.getDeptId().longValue() != deptId.longValue() ? "1" : "0";
    }

    public void checkDeptDataScope(Long deptId) {
        if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
            SysDept dept = new SysDept();
            dept.setDeptId(deptId);
            List<SysDept> sysDeptList = SpringUtils.getAopProxy(this).selectDeptList(dept);
            if (StringUtils.isEmpty(sysDeptList)) {
                throw new ServiceException("没有权限访问部门数据！");
            }
        }

    }

    public int insertDept(SysDept dept) {
        SysDept info = this.deptMapper.selectDeptById(dept.getParentId());
        if (!"0".equals(info.getStatus())) {
            throw new ServiceException("部门停用，不允许新增");
        } else {
            dept.setAncestors(info.getAncestors() + StringUtils.COMMA + dept.getParentId());
            return this.deptMapper.insertDept(dept);
        }
    }

    public int updateDept(SysDept dept) {
        SysDept newParentDept = this.deptMapper.selectDeptById(dept.getParentId());
        SysDept oldDept = this.deptMapper.selectDeptById(dept.getDeptId());
        if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept)) {
            String newAncestors = newParentDept.getAncestors() + StringUtils.COMMA + newParentDept.getDeptId();
            String oldAncestors = oldDept.getAncestors();
            dept.setAncestors(newAncestors);
            this.updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
        }

        int result = this.deptMapper.updateDept(dept);
        if ("0".equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors()) && !StringUtils.equals("0", dept.getAncestors())) {
            this.updateParentDeptStatusNormal(dept);
        }

        return result;
    }

    private void updateParentDeptStatusNormal(SysDept dept) {
        String ancestors = dept.getAncestors();
        Long[] deptIds = Convert.toLongArray(ancestors);
        this.deptMapper.updateDeptStatusNormal(deptIds);
    }

    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
        List<SysDept> children = this.deptMapper.selectChildrenDeptById(deptId);

        for (SysDept child : children) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }

        if (!children.isEmpty()) {
            this.deptMapper.updateDeptChildren(children);
        }

    }

    public int deleteDeptById(Long deptId) {
        return this.deptMapper.deleteDeptById(deptId);
    }

    private void recursionFn(List<SysDept> list, SysDept t) {
        List<SysDept> childList = this.getChildList(list, t);
        t.setChildren(childList);

        for (SysDept tChild : childList) {
            if (this.hasChild(list, tChild)) {
                this.recursionFn(list, tChild);
            }
        }

    }

    private List<SysDept> getChildList(List<SysDept> list, SysDept t) {
        List<SysDept> sysDeptList = new ArrayList<>();

        for (SysDept temp : list) {
            if (StringUtils.isNotNull(temp.getParentId()) && temp.getParentId().longValue() == t.getDeptId().longValue()) {
                sysDeptList.add(temp);
            }
        }

        return sysDeptList;
    }

    private boolean hasChild(List<SysDept> list, SysDept t) {
        return !this.getChildList(list, t).isEmpty();
    }
}
