package com.maintain.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.maintain.common.constant.CacheNames;
import com.maintain.common.constant.UserConstants;
import com.maintain.common.core.domain.entity.ExternalDept;
import com.maintain.common.core.domain.entity.SysDept;
import com.maintain.common.core.domain.entity.SysRole;
import com.maintain.common.core.domain.entity.SysUser;
import com.maintain.common.core.service.DeptService;
import com.maintain.common.enums.IsEnableStatus;
import com.maintain.common.exception.ServiceException;
import com.maintain.common.helper.DataBaseHelper;
import com.maintain.common.helper.LoginHelper;
import com.maintain.common.utils.StringUtils;
import com.maintain.common.utils.TreeBuildUtils;
import com.maintain.common.utils.redis.CacheUtils;
import com.maintain.common.utils.spring.SpringUtils;
import com.maintain.system.mapper.SysDeptMapper;
import com.maintain.system.mapper.SysRoleMapper;
import com.maintain.system.mapper.SysUserMapper;
import com.maintain.system.service.ISysDeptService;
import com.maintain.system.util.ExternalDataDispose;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 部门管理 服务实现
 *
 * @author Lion Li
 */
@RequiredArgsConstructor
@Service
public class SysDeptServiceImpl implements ISysDeptService, DeptService {

    private final SysDeptMapper baseMapper;
    private final SysRoleMapper roleMapper;
    private final SysUserMapper userMapper;

    /**
     * 查询部门管理数据
     *
     * @param dept 部门信息
     * @return 部门信息集合
     */
    @Override
    public List<SysDept> selectDeptList(SysDept dept) {
        LambdaQueryWrapper<SysDept> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysDept::getDelFlag, "0")
            .eq(ObjectUtil.isNotNull(dept.getDeptId()), SysDept::getDeptId, dept.getDeptId())
            .eq(ObjectUtil.isNotNull(dept.getParentId()), SysDept::getParentId, dept.getParentId())
            .like(StringUtils.isNotBlank(dept.getDeptName()), SysDept::getDeptName, dept.getDeptName())
            .eq(StringUtils.isNotBlank(dept.getStatus()), SysDept::getStatus, dept.getStatus())
            .orderByAsc(SysDept::getParentId)
            .orderByAsc(SysDept::getOrderNum);
        return baseMapper.selectDeptList(lqw);
    }

    /**
     * 查询当前登录人所在部门以及下属部门管理数据
     *
     * @return 部门信息集合
     */
    @Override
    public List<SysDept> selectCurrentDeptList() {
        return baseMapper.selectChildrenDeptById(LoginHelper.getDeptId());
    }

    /**
     * 查询部门树结构信息
     *
     * @param dept 部门信息
     * @return 部门树信息集合
     */
    @Override
    public List<Tree<Long>> selectDeptTreeList(SysDept dept) {
        // 只查询未禁用部门
        dept.setStatus(UserConstants.DEPT_NORMAL);
        List<SysDept> depts = this.selectDeptList(dept);
        return buildDeptTreeSelect(depts);
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param depts 部门列表
     * @return 下拉树结构列表
     */
    @Override
    public List<Tree<Long>> buildDeptTreeSelect(List<SysDept> depts) {
        if (CollUtil.isEmpty(depts)) {
            return CollUtil.newArrayList();
        }
        return TreeBuildUtils.build(depts, (dept, tree) ->
            tree.setId(dept.getDeptId())
                .setParentId(dept.getParentId())
                .setName(dept.getDeptName())
                .setWeight(dept.getOrderNum()));
    }

    /**
     * 根据角色ID查询部门树信息
     *
     * @param roleId 角色ID
     * @return 选中部门列表
     */
    @Override
    public List<Long> selectDeptListByRoleId(Long roleId) {
        SysRole role = roleMapper.selectById(roleId);
        return baseMapper.selectDeptListByRoleId(roleId, role.getDeptCheckStrictly());
    }

    /**
     * 根据部门ID查询信息
     *
     * @param deptId 部门ID
     * @return 部门信息
     */
    @Cacheable(cacheNames = CacheNames.SYS_DEPT, key = "#deptId")
    @Override
    public SysDept selectDeptById(Long deptId) {
        SysDept dept = baseMapper.selectById(deptId);
        if (ObjectUtil.isNull(dept)) {
            return null;
        }
        SysDept parentDept = baseMapper.selectOne(new LambdaQueryWrapper<SysDept>()
            .select(SysDept::getDeptName).eq(SysDept::getDeptId, dept.getParentId()));
        dept.setParentName(ObjectUtil.isNotNull(parentDept) ? parentDept.getDeptName() : null);
        return dept;
    }

    /**
     * 通过部门ID查询部门名称
     *
     * @param deptIds 部门ID串逗号分隔
     * @return 部门名称串逗号分隔
     */
    @Override
    public String selectDeptNameByIds(String deptIds) {
        List<String> list = new ArrayList<>();
        for (Long id : StringUtils.splitTo(deptIds, Convert::toLong)) {
            SysDept dept = SpringUtils.getAopProxy(this).selectDeptById(id);
            if (ObjectUtil.isNotNull(dept)) {
                list.add(dept.getDeptName());
            }
        }
        return String.join(StringUtils.SEPARATOR, list);
    }

    /**
     * 根据ID查询所有子部门数（正常状态）
     *
     * @param deptId 部门ID
     * @return 子部门数
     */
    @Override
    public long selectNormalChildrenDeptById(Long deptId) {
        return baseMapper.selectCount(new LambdaQueryWrapper<SysDept>()
            .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL)
            .apply(DataBaseHelper.findInSet(deptId, "ancestors")));
    }

    /**
     * 是否存在子节点
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public boolean hasChildByDeptId(Long deptId) {
        return baseMapper.exists(new LambdaQueryWrapper<SysDept>()
            .eq(SysDept::getParentId, deptId));
    }

    /**
     * 查询部门是否存在用户
     *
     * @param deptId 部门ID
     * @return 结果 true 存在 false 不存在
     */
    @Override
    public boolean checkDeptExistUser(Long deptId) {
        return userMapper.exists(new LambdaQueryWrapper<SysUser>()
            .eq(SysUser::getDeptId, deptId));
    }

    /**
     * 校验部门名称是否唯一
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public boolean checkDeptNameUnique(SysDept dept) {
        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysDept>()
            .eq(SysDept::getDeptName, dept.getDeptName())
            .eq(SysDept::getParentId, dept.getParentId())
            .ne(ObjectUtil.isNotNull(dept.getDeptId()), SysDept::getDeptId, dept.getDeptId()));
        return !exist;
    }

    /**
     * 校验部门是否有数据权限
     *
     * @param deptId 部门id
     */
    @Override
    public void checkDeptDataScope(Long deptId) {
        if (!LoginHelper.isAdmin()) {
            SysDept dept = new SysDept();
            dept.setDeptId(deptId);
            List<SysDept> depts = this.selectDeptList(dept);
            if (CollUtil.isEmpty(depts)) {
                throw new ServiceException("没有权限访问部门数据！");
            }
        }
    }

    /**
     * 新增保存部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public int insertDept(SysDept dept) {
        SysDept info = baseMapper.selectById(dept.getParentId());
        // 如果父节点不为正常状态,则不允许新增子节点
        if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) {
            throw new ServiceException("部门停用，不允许新增");
        }
        dept.setAncestors(info.getAncestors() + StringUtils.SEPARATOR + dept.getParentId());
        return baseMapper.insert(dept);
    }

    /**
     * 修改保存部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#dept.deptId")
    @Override
    public int updateDept(SysDept dept) {
        SysDept newParentDept = baseMapper.selectById(dept.getParentId());
        SysDept oldDept = baseMapper.selectById(dept.getDeptId());
        if (ObjectUtil.isNotNull(newParentDept) && ObjectUtil.isNotNull(oldDept)) {
            String newAncestors = newParentDept.getAncestors() + StringUtils.SEPARATOR + newParentDept.getDeptId();
            String oldAncestors = oldDept.getAncestors();
            dept.setAncestors(newAncestors);
            updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
        }
        int result = baseMapper.updateById(dept);
        if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors())
            && !StringUtils.equals(UserConstants.DEPT_NORMAL, dept.getAncestors())) {
            // 如果该部门是启用状态，则启用该部门的所有上级部门
            updateParentDeptStatusNormal(dept);
        }
        return result;
    }

    /**
     * 修改该部门的父级部门状态
     *
     * @param dept 当前部门
     */
    private void updateParentDeptStatusNormal(SysDept dept) {
        String ancestors = dept.getAncestors();
        Long[] deptIds = Convert.toLongArray(ancestors);
        baseMapper.update(null, new LambdaUpdateWrapper<SysDept>()
            .set(SysDept::getStatus, UserConstants.DEPT_NORMAL)
            .in(SysDept::getDeptId, Arrays.asList(deptIds)));
    }

    /**
     * 修改子元素关系
     *
     * @param deptId       被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
        List<SysDept> children = baseMapper.selectList(new LambdaQueryWrapper<SysDept>()
            .apply(DataBaseHelper.findInSet(deptId, "ancestors")));
        List<SysDept> list = new ArrayList<>();
        for (SysDept child : children) {
            SysDept dept = new SysDept();
            dept.setDeptId(child.getDeptId());
            dept.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
            list.add(dept);
        }
        if (CollUtil.isNotEmpty(list)) {
            if (baseMapper.updateBatchById(list)) {
                list.forEach(dept -> CacheUtils.evict(CacheNames.SYS_DEPT, dept.getDeptId()));
            }
        }
    }

    /**
     * 删除部门管理信息
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#deptId")
    @Override
    public int deleteDeptById(Long deptId) {
        return baseMapper.deleteById(deptId);
    }

    @Override
    public void deptExtracted() {
        List<SysDept> sysDeptList = ExternalDataDispose.deptExtracted();
        baseMapper.insertBatch(sysDeptList);
    }

    /**
     * 根据外部接口同步部门数据
     */
    @Override
    public void deptSync() {
        String res = com.zxw.util.tm.HttpTmEncryptUtil.sendPostRequest("http://10.100.102.67:22220/api/basis/deptInfoExtRepair", null, null);
        Map map = JSONUtil.toBean(res, Map.class);
        System.out.println(JSONUtil.toJsonStr(map.get("data")));
        List<ExternalDept> departmentList = JSONUtil.toList(JSONUtil.toJsonStr(map.get("data")), ExternalDept.class);
        List<SysDept> sysDeptList = baseMapper.selectList();
        departmentList.forEach(department -> {
            // 查询是否已存在系统
            if (sysDeptList.stream().noneMatch(item -> null != item.getExternalDeptCode() && item.getExternalDeptCode().equals(department.getDeptCode()))) {
                if (department.getUpperDeptCode().equals("-1")) {
                    SysDept sysDept = new SysDept();
                    sysDept.setAncestors("0,1");
                    sysDept.setParentId(1L);
                    sysDept.setDeptName(department.getDeptName());
                    sysDept.setExternalDeptCode(department.getDeptCode());
                    // 状态转换
                    sysDept.setStatus(
                        department.getStatus().equals("已启用")
                            ? String.valueOf(IsEnableStatus.NO.getCode()) // 0正常 1停用
                            : String.valueOf(IsEnableStatus.YES.getCode())
                    );
                    int flag = baseMapper.insert(sysDept);
                    if (flag > 0) {
                        sysDeptList.add(sysDept);
                    }
                } else {
                    Optional<SysDept> first = sysDeptList.stream()
                        .filter(item -> item.getExternalDeptCode() != null && item.getExternalDeptCode().equals(department.getUpperDeptCode()))
                        .findFirst();
                    if (first.isPresent()) {
                        SysDept sysDept = getSysDept(department, first);
                        int flag = baseMapper.insert(sysDept);
                        if (flag > 0) {
                            sysDeptList.add(sysDept);
                        }
                    }else {
                        System.out.println("不存在部门："+ department.getDeptName());
                    }
                }
            }
        });
    }

    @NotNull
    private static SysDept getSysDept(ExternalDept department, Optional<SysDept> first) {
        SysDept dept = first.get();
        SysDept sysDept = new SysDept();
        sysDept.setAncestors(dept.getAncestors() + StringUtils.SEPARATOR + dept.getDeptId());
        sysDept.setParentId(dept.getDeptId());
        sysDept.setDeptName(department.getDeptName());
        sysDept.setExternalDeptCode(department.getDeptCode());
        // 状态转换
        sysDept.setStatus(
            department.getStatus().equals("已启用")
                ? String.valueOf(IsEnableStatus.NO.getCode()) // 0正常 1停用
                : String.valueOf(IsEnableStatus.YES.getCode())
        );
        return sysDept;
    }

}
