package com.simuwang.base.components;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.simuwang.base.common.support.dos.OnlyIdNameDO;
import com.simuwang.base.mapper.system.SysMenuMapper;
import com.simuwang.base.mapper.system.SysRoleMapper;
import com.simuwang.base.mapper.system.SysUserMapper;
import com.simuwang.base.pojo.dos.sys.SysMenuDO;
import com.simuwang.base.pojo.dos.sys.SysRoleDO;
import com.simuwang.base.pojo.dos.sys.SysUserDO;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author wangzaijun
 * @date 2024/9/13 17:08
 * @description 用户权限服务
 */
@Service
public class UserAuthService {
    private final SysUserMapper userMapper;
    private final SysRoleMapper roleMapper;
    private final SysMenuMapper menuMapper;

    public UserAuthService(SysUserMapper userMapper, SysRoleMapper roleMapper, SysMenuMapper menuMapper) {
        this.userMapper = userMapper;
        this.roleMapper = roleMapper;
        this.menuMapper = menuMapper;
    }

    /**
     * 更新用户密码
     *
     * @param entity /
     */
    public void updatePwd(SysUserDO entity) {
        this.userMapper.updateById(entity);
    }

    /**
     * 根据用户账号获取用户信息
     *
     * @param username 用户账号
     * @return /
     */
    public SysUserDO getUserInfoByUsername(String username) {
        LambdaQueryWrapper<SysUserDO> wrapper = Wrappers.lambdaQuery(SysUserDO.class)
                .eq(SysUserDO::getUserName, username);
        return this.userMapper.selectOne(wrapper);
    }

    /**
     * 根据用户id获取角色权限列表
     *
     * @param userId 用户id
     * @return /
     */
    public List<SysRoleDO> listUserRoleByUserId(Integer userId) {
        boolean admin = this.isAdmin(userId);
        if (admin) {
            return this.userMapper.selectAllRole();
        }
        return this.userMapper.selectRoleByUserId(userId);
    }

    /**
     * 根据用户id获取菜单列表
     *
     * @param userId 用户id
     * @return /
     */
    public List<SysMenuDO> listUserMenuByUserId(Integer userId) {
        boolean admin = this.isAdmin(userId);
        if (admin) {
            return this.userMapper.selectAllMenu();
        }
        return this.userMapper.selectMenuByUserId(userId);
    }

    /**
     * 获取用户绑定的角色
     *
     * @param userId 用户id
     * @return /
     */
    public List<OnlyIdNameDO> userBindRoles(Integer userId) {
        boolean admin = this.isAdmin(userId);
        if (admin) {
            return this.userMapper.allRoles();
        }
        return this.userMapper.listBindRoles(userId);
    }

    /**
     * 角色分配的权限
     *
     * @param roleId 角色id
     * @return /
     */
    public List<OnlyIdNameDO> roleAssignPerms(Integer roleId) {
        boolean adminByRole = this.isAdminByRole(roleId);
        if (adminByRole) {
            return this.roleMapper.allPerms();
        }
        List<OnlyIdNameDO> dataList = this.roleMapper.listAssignPerms(roleId);
        if (CollUtil.isNotEmpty(dataList)) {
            // 找到所有父id是上述数据的
            List<Integer> menuIds = dataList.stream().map(OnlyIdNameDO::getId).distinct().collect(Collectors.toList());
            LambdaQueryWrapper<SysMenuDO> wrapper = Wrappers.lambdaQuery(SysMenuDO.class)
                    .select(SysMenuDO::getMenuId, SysMenuDO::getParentId)
                    .in(SysMenuDO::getParentId, menuIds)
                    .eq(SysMenuDO::getStatus, 1);
            List<SysMenuDO> tempList = this.menuMapper.selectList(wrapper);
            // 过滤存在父节点引用的菜单id
            List<Integer> pids = tempList.stream().map(SysMenuDO::getParentId).distinct().collect(Collectors.toList());
            dataList.removeIf(e -> pids.contains(e.getId()));
        }
        return dataList;
    }

    /**
     * 判断用户是否超级管理员
     * 1、如果用户id为0或者1则为超级管理员
     * 2、或者用户有system和admin角色
     *
     * @param userId 用户id
     * @return /
     */
    private boolean isAdmin(Integer userId) {
        if (Objects.equals(0, userId) || Objects.equals(1, userId)) {
            return true;
        }
        List<SysRoleDO> roles = this.userMapper.selectRoleByUserId(userId);
        SysRoleDO adminRole = roles.stream()
                .filter(e -> Objects.equals(1, e.getRoleId())
                        || "system".equalsIgnoreCase(e.getRoleKey())
                        || "admin".equalsIgnoreCase(e.getRoleKey()))
                .findFirst().orElse(null);
        return adminRole != null;
    }

    /**
     * 根据角色id判断角色是否管理员
     *
     * @param roleId 角色id
     * @return /
     */
    private boolean isAdminByRole(Integer roleId) {
        if (Objects.equals(1, roleId)) {
            return true;
        }
        SysRoleDO role = this.roleMapper.selectById(roleId);
        return role != null
                && ("system".equalsIgnoreCase(role.getRoleKey()) || "admin".equalsIgnoreCase(role.getRoleKey()));
    }
}
