package com.microservices.system.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.constant.CacheConstants;
import com.microservices.common.core.constant.SecurityConstants;
import com.microservices.common.core.enums.SystemRole;
import com.microservices.common.core.enums.UserIdentityStatus;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.PageUtils;
import com.microservices.common.core.utils.html.EscapeUtil;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.httpClient.domain.GitLinkRequestUrl;
import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.common.redis.service.RedisService;
import com.microservices.common.security.service.TokenService;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.system.api.RemoteCmsService;
import com.microservices.system.api.RemotePmsService;
import com.microservices.system.api.RemoteZoneService;
import com.microservices.system.api.domain.SysDept;
import com.microservices.system.api.domain.SysRole;
import com.microservices.system.api.domain.SysUser;
import com.microservices.system.api.domain.SysUserDeptRole;
import com.microservices.system.api.utils.FeignUtils;
import com.microservices.system.domain.dto.GitLinkUserDeptRoleByDeptInput;
import com.microservices.system.domain.dto.SysUserDeptRoleByDeptInput;
import com.microservices.system.domain.vo.GitLinkUserSearchVo;
import com.microservices.system.mapper.SysDeptMapper;
import com.microservices.system.mapper.SysUserDeptRoleMapper;
import com.microservices.system.mapper.SysUserMapper;
import com.microservices.system.service.ISysDeptRoleService;
import com.microservices.system.service.ISysRoleService;
import com.microservices.system.service.ISysUserDeptRoleService;
import com.microservices.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 用户与部门及部门内角色关联Service业务层处理
 *
 * @author otto
 * @date 2023-04-11
 */
@Service
public class SysUserDeptRoleServiceImpl implements ISysUserDeptRoleService {
    private static final Logger logger = LoggerFactory.getLogger(SysUserDeptRoleServiceImpl.class);
    @Autowired
    private SysUserDeptRoleMapper sysUserDeptRoleMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    private ISysRoleService sysRoleService;
    @Autowired
    private ISysDeptRoleService sysDeptRoleService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private RemoteCmsService remoteCmsService;
    @Autowired
    private RemoteZoneService remoteZoneService;
    @Autowired
    private RemotePmsService remotePmsService;
    @Autowired
    private GitLinkRequestHelper gitLinkRequestHelper;
    @Autowired
    private TokenService tokenService;

    /**
     * 查询用户与部门及部门内角色关联列表
     *
     * @param userName 用户名
     * @param deptId 组织Id
     * @param roleId 角色Id
     * @return 用户与部门及部门内角色关联
     */
    @Override
    public GenericsTableDataInfo<SysUserDeptRole> selectSysUserDeptRoleListByDept(Long deptId, String userName, String nickName, String roleId) {
        List<Long> virtualRoleIdList = sysRoleService.getVirtualRoleIdList();
        PageUtils.startPage();
        return PageUtils.toPage(sysUserDeptRoleMapper.selectSysUserDeptRoleListByDeptId(deptId, userName, nickName, roleId, virtualRoleIdList));
    }

    /**
     * 批量删除用户与部门及部门内角色关联
     *
     * @param deptId  组织Id
     * @param userIds 需要删除的用户与部门及部门内角色关联主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteSysUserDeptRoleByDeptIdAndUserIds(Long deptId, Long[] userIds) {
        SysDept sysDept = sysDeptMapper.selectDeptById(deptId);
        if (CacheConstants.DEPT_TYPE_TSZQ == sysDept.getDeptType()) {
            List<Long> memberUserIdList = FeignUtils.getReturnData(
                    remoteZoneService.checkUsersIsMemberInDept(deptId, userIds, SecurityConstants.INNER)
            );
            // 检查该身份是否为会员用户，若是则将身份调整为会员并且不删除该身份
            if (memberUserIdList != null && !memberUserIdList.isEmpty()) {
                userIds = Arrays.stream(userIds).filter(x -> !memberUserIdList.contains(x)).toArray(Long[]::new);
                SysRole memberRole = sysRoleService.selectRoleByKey(SystemRole.ZONE_MEMBER.getRoleKey());
                for (Long userId : memberUserIdList) {
                    updateSysUserDeptRole(userId, deptId, memberRole.getRoleId());
                }
            }
        }

        if (userIds == null || userIds.length == 0) {
            return 1;
        }
        for (Long userId : userIds) {
            SysUserDeptRole userIdentify = sysUserDeptRoleMapper.selectSysUserDeptRoleByUserIdAndDeptId(userId, deptId);
            updateUserGitLinkRole(userId, deptId, userIdentify.getRoleId(), null, OPERATE_REMOVE);
        }
        int success = deleteUserIdentityByDeptIdAndUserIds(sysDept, userIds);
        for (Long userId : userIds) {
            updateUserLoginInfoByUserId(userId);
        }
        return success;
    }

    private int deleteUserIdentityByDeptIdAndUserIds(SysDept sysDept, Long[] userIds) {
        if (CacheConstants.DEPT_TYPE_PMS == sysDept.getDeptType()) {
            return sysUserDeptRoleMapper.updateUserIdentifyListState(sysDept.getDeptId(), userIds, UserIdentityStatus.QUIT.getState());
        } else {
            return sysUserDeptRoleMapper.deleteSysUserDeptRoleByDeptIdAndUserIds(sysDept.getDeptId(), userIds);
        }
    }

    /**
     * 根据组织下所有身份更新组织下所有用户登录态缓存信息
     *
     * @param sysUserDeptRoleList 组织下所有身份
     */
    private void updateUserLoginInfoByUserIdentifyList(List<SysUserDeptRole> sysUserDeptRoleList) {
        for (SysUserDeptRole sysUserDeptRole : sysUserDeptRoleList) {
            SysUser sysUser = sysUserDeptRole.getSysUser();
            if (sysUser != null) {
                // 删除缓存中该用户身份列表信息
                redisService.deleteObject(CacheConstants.getUserIdentifyListKey(sysUser.getUserName()));
            }
        }
    }

    /**
     * 根据用户Id更新用户登录态缓存信息
     *
     * @param userId 用户Id
     */
    private void updateUserLoginInfoByUserId(Long userId) {
        SysUser sysUser = sysUserMapper.selectUserById(userId);
        if (sysUser == null) {
            return;
        }
        // 删除缓存中该用户身份列表信息
        redisService.deleteObject(CacheConstants.getUserIdentifyListKey(sysUser.getUserName()));
    }


    /**
     * 删除用户与部门及部门内角色关联信息
     *
     * @param deptId 用户与部门及部门内角色关联主键
     * @return 结果
     */
    @Override
    public int deleteSysUserDeptRoleByDeptId(Long deptId) {
        List<SysUserDeptRole> sysUserDeptRoleList = selectSysUserDeptRoleListByDeptId(deptId);
        int success = sysUserDeptRoleMapper.deleteSysUserDeptRoleByDeptId(deptId);
        updateUserLoginInfoByUserIdentifyList(sysUserDeptRoleList);
        return success;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertSysUserDeptRoleListByDept(Long deptId, SysUserDeptRoleByDeptInput[] sysUserDeptRoleByDeptInputs) {
        int success = 0;
        for (SysUserDeptRoleByDeptInput sysUserDeptRoleByDeptInput : sysUserDeptRoleByDeptInputs) {
            SysUserDeptRole sysUserDeptRoleInput = sysUserDeptRoleByDeptInput.copyToSysUserDeptRole(deptId);
            selectSysUserById(sysUserDeptRoleInput.getUserId());
            success += insertUserDeptRole(sysUserDeptRoleInput);
        }
        return success;
    }

    private int insertSysUserDeptRoleDatabase(SysUserDeptRole sysUserDeptRoleInput) {
        int success = sysUserDeptRoleMapper.insertSysUserDeptRole(sysUserDeptRoleInput);
        updateUserLoginInfoByUserId(sysUserDeptRoleInput.getUserId());
        return success;
    }

    /**
     * 根据组织类型获取二级组织Id列表
     *
     * @param deptType 组织类型
     * @return 二级组织Id列表
     */
    private List<Long> getSecondaryDeptIds(Integer deptType) {
        if (deptType == null) {
            return null;
        }
        return sysDeptMapper.selectSecondaryDeptIds();
    }

    private final static int OPERATE_ADD = 1;
    private final static int OPERATE_UPDATE = 2;
    private final static int OPERATE_REMOVE = 3;

    /**
     * 更新用户在gitlink上的权限
     *
     * @param operate 操作类型（1：新增；2：更新；3：删除；）
     */
    private void updateUserGitLinkRole(Long userId, Long deptId, Long oldRoleId, Long newRoleId, int operate) {
        SysDept dept = sysDeptMapper.selectDeptById(deptId);
        List<Long> secondaryDeptIds = getSecondaryDeptIds(dept.getDeptType());
        if (secondaryDeptIds == null) {
            return;
        }

        if (!secondaryDeptIds.contains(dept.getDeptId())) {
            if (secondaryDeptIds.contains(dept.getParentId())) {
                switch (dept.getDeptType()) {
                    case CacheConstants.DEPT_TYPE_TSZQ: {
                        //如果用户为三级组织，则将用户加入到专区对应项目中
                        switch (operate) {
                            case OPERATE_ADD: {
                                FeignUtils.getReturnData(remoteCmsService.changeUserRole(
                                        userId
                                        , null
                                        , dept.getDeptId()
                                        , oldRoleId
                                        , newRoleId
                                        , SecurityConstants.INNER));
                                break;
                            }
                            case OPERATE_UPDATE: {
                                // 组织中角色发生变化时，同步更新gitLink仓库分支保护设置
                                FeignUtils.getReturnData(remoteCmsService.changeUserRole(
                                        userId
                                        , dept.getDeptId()
                                        , dept.getDeptId()
                                        , oldRoleId
                                        , newRoleId
                                        , SecurityConstants.INNER));
                                break;
                            }
                            case OPERATE_REMOVE: {
                                //如果用户为三级组织，则将用户移出专区对应项目
                                FeignUtils.getReturnData(remoteCmsService.changeUserRole(
                                        userId
                                        , deptId
                                        , null
                                        , oldRoleId
                                        , newRoleId
                                        , SecurityConstants.INNER));
                                break;
                            }
                        }
                        break;
                    }
                    case CacheConstants.DEPT_TYPE_PMS: {
                        // 更新或移出用户时，需检查角色是否为组织管理员，项目管理中至少保留一位组织管理员
                        if (oldRoleId != null) {
                            SysRole orgAdminRole = sysRoleService.selectRoleByKey(SystemRole.PMS_ORG_ADMIN.getRoleKey());
                            if (orgAdminRole.getRoleId().equals(oldRoleId)) {
                                SysUserDeptRole sysUserDeptRoleSearch = new SysUserDeptRole();
                                sysUserDeptRoleSearch.setDeptId(deptId);
                                sysUserDeptRoleSearch.setRoleId(orgAdminRole.getRoleId());
                                List<SysUserDeptRole> orgAdminUserDeptRoleList =
                                        sysUserDeptRoleMapper.selectSysUserDeptRoleList(sysUserDeptRoleSearch);
                                if (orgAdminUserDeptRoleList.isEmpty()
                                        || (orgAdminUserDeptRoleList.size() == 1 && orgAdminUserDeptRoleList.stream().anyMatch(x -> x.getUserId().equals(userId)))) {
                                    throw new ServiceException("至少需要保留一位组织管理员角色");
                                }
                            }
                        }
                        remotePmsService.changeUserGitlinkRole(
                                userId,
                                deptId,
                                oldRoleId,
                                newRoleId,
                                SecurityConstants.INNER
                                , SecurityUtils.getUserKey()
                        );
                        break;
                    }
                }
            }
        }
    }

    private SysUserDeptRole getSysUserDeptRole(SysUserDeptRole sysUserDeptRoleInput) {
        if (sysUserDeptRoleInput.getUserId() == null || sysUserDeptRoleInput.getRoleId() == null || sysUserDeptRoleInput.getDeptId() == null) {
            throw new ServiceException("用户Id、角色Id和组织Id不能为空");
        }
        SysRole sysRole = sysRoleService.selectRoleById(sysUserDeptRoleInput.getRoleId());
        boolean isExist = sysDeptRoleService.checkDeptHasRole(sysUserDeptRoleInput.getDeptId(), sysRole.getRoleId());
        if (!isExist) {
            SysDept sysDept = sysDeptMapper.selectDeptById(sysUserDeptRoleInput.getDeptId());
            throw new ServiceException("部门下不存在该可选角色" +
                    "(部门名称[" + sysDept.getDeptName() + "]," +
                    "角色名称[" + sysRole.getRoleName() + "])");
        }
        return sysUserDeptRoleMapper.selectSysUserDeptRoleByUserIdAndDeptId(sysUserDeptRoleInput.getUserId(), sysUserDeptRoleInput.getDeptId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateSysUserDeptRoleByDept(Long deptId, SysUserDeptRoleByDeptInput[] sysUserDeptRoleByDeptInputs) {
        SysDept sysDept = sysDeptRoleService.selectSysDeptById(deptId);
        int success = 0;
        for (SysUserDeptRoleByDeptInput sysUserDeptRoleByDeptInput : sysUserDeptRoleByDeptInputs) {
            SysUserDeptRole sysUserDeptRoleInput = sysUserDeptRoleByDeptInput.copyToSysUserDeptRole(deptId);
            SysUserDeptRole oldSysUserDeptRole = getSysUserDeptRole(sysUserDeptRoleInput);
            if (oldSysUserDeptRole == null) {
                SysUser sysUser = selectSysUserById(sysUserDeptRoleInput.getUserId());
                throw new ServiceException("部门下不存在该用户，无法进行更新操作" +
                        "(部门名称[" + sysDept.getDeptName() + "]," +
                        "用户名称[" + sysUser.getUserName() + "])");
            }
            if (!oldSysUserDeptRole.equals(sysUserDeptRoleInput)) {
                success += sysUserDeptRoleMapper.updateSysUserDeptRole(sysUserDeptRoleInput);
                updateUserLoginInfoByUserId(sysUserDeptRoleInput.getUserId());
                updateUserGitLinkRole(
                        sysUserDeptRoleInput.getUserId()
                        , sysUserDeptRoleInput.getDeptId()
                        , oldSysUserDeptRole.getRoleId()
                        , sysUserDeptRoleInput.getRoleId()
                        , OPERATE_UPDATE);
            } else {
                success++;
            }
        }
        return success;
    }

    @Override
    public List<SysUserDeptRole> selectSysUserDeptRoleListByUser(Long userId, Boolean isContainMember, String deptName, String roleName) {
        List<SysUserDeptRole> sysUserDeptRoleList = sysUserDeptRoleMapper.selectSysUserDeptRoleListByUserId(userId, deptName, roleName);
        // 关联需求：https://www.gitlink.org.cn/Gitlink/forgeplus/issues/3520
        if (isContainMember != null && !isContainMember) {
            return sysUserDeptRoleList
                    .stream()
                    .filter(x -> !SystemRole.ZONE_MEMBER.getRoleKey().equals(x.getSysRole().getRoleKey()))
                    .collect(Collectors.toList());
        }
        return sysUserDeptRoleList;
    }

    private void updateSysUserDeptRole(Long userId, Long deptId, Long roleId) {
        SysUserDeptRole sysUserDeptRole = new SysUserDeptRole();
        sysUserDeptRole.setUserId(userId);
        sysUserDeptRole.setDeptId(deptId);
        sysUserDeptRole.setRoleId(roleId);
        updateSysUserDeptRole(sysUserDeptRole);
    }

    private void updateSysUserDeptRole(SysUserDeptRole sysUserDeptRoleInput) {
        SysDept sysDept = sysDeptRoleService.selectSysDeptById(sysUserDeptRoleInput.getDeptId());
        SysUserDeptRole sysUserDeptRole = getSysUserDeptRole(sysUserDeptRoleInput);

        if (sysUserDeptRole == null) {
            SysUser sysUser = sysUserMapper.selectUserById(sysUserDeptRoleInput.getUserId());
            throw new ServiceException("用户下不存在该部门，无法进行更新操作" +
                    "(用户名称[" + sysUser.getUserName() + "]," +
                    "部门名称[" + sysDept.getDeptName() + "])");
        }
        if (!sysUserDeptRole.equals(sysUserDeptRoleInput)) {
            sysUserDeptRoleMapper.updateSysUserDeptRole(sysUserDeptRoleInput);
            updateUserLoginInfoByUserId(sysUserDeptRoleInput.getUserId());
        }
    }

    @Override
    public List<SysUserDeptRole> selectSysUserDeptRoleListByUserName(String userName) {
        return sysUserDeptRoleMapper.selectSysUserDeptRoleListByUserName(userName);
    }

    @Override
    public SysUserDeptRole getFirstSysUserDeptRoleByUserName(String userName) {
        SysUserDeptRole userIdentity = null;
        List<SysUserDeptRole> sysUserDeptRoleList = selectSysUserDeptRoleListByUserName(userName);
        if (!sysUserDeptRoleList.isEmpty()) {
            userIdentity = sysUserDeptRoleList.get(0);
        }
        return userIdentity;
    }

    @Override
    public List<SysUserDeptRole> selectCurrentSysUserDeptRoleList() {
        String currentUsername = SecurityUtils.getUsername();
        return selectSysUserDeptRoleListByUserName(currentUsername);
    }

    @Override
    public int insertGitLinkUserDeptRoleListByDept(Long deptId, GitLinkUserDeptRoleByDeptInput[] gitLinkUserDeptRoleByDeptInputs) {
        int success = 0;
        SysUserDeptRole sysUserDeptRoleInput = new SysUserDeptRole();
        for (GitLinkUserDeptRoleByDeptInput gitLinkUserDeptRoleByDeptInput : gitLinkUserDeptRoleByDeptInputs) {
            selectSysRoleById(gitLinkUserDeptRoleByDeptInput.getRoleId());

            SysUser sysUser = sysUserMapper.selectUserByGitLinkUserId(gitLinkUserDeptRoleByDeptInput.getGitLinkUserId());
            if (sysUser == null) {
                sysUser = sysUserService.createUserByGitLinkUserId(gitLinkUserDeptRoleByDeptInput.getGitLinkUserId());
            }
            sysUserDeptRoleInput.setDeptId(deptId);
            sysUserDeptRoleInput.setRoleId(gitLinkUserDeptRoleByDeptInput.getRoleId());
            sysUserDeptRoleInput.setUserId(sysUser.getUserId());
            success += insertUserDeptRole(sysUserDeptRoleInput);
        }
        return success;
    }

    private int insertUserDeptRole(SysUserDeptRole sysUserDeptRoleInput) {
        int success = 0;
        SysUserDeptRole sysUserDeptRole =
                sysUserDeptRoleMapper.selectUserIdentityByAllStatus(sysUserDeptRoleInput.getDeptId(), sysUserDeptRoleInput.getUserId());
        if (sysUserDeptRole == null) {
            success += insertSysUserDeptRoleDatabase(sysUserDeptRoleInput);
        } else {
            if (sysUserDeptRole.getSysRole() != null && SystemRole.isVirtual(sysUserDeptRole.getSysRole().getRoleKey())) {
                updateSysUserDeptRole(sysUserDeptRoleInput);
            }
            // 已离职的用户重新入职时将状态标记为正常
            if (UserIdentityStatus.QUIT.getState().equals(sysUserDeptRole.getState())) {
                sysUserDeptRoleMapper.updateUserIdentifyListState(sysUserDeptRoleInput.getDeptId(), new Long[]{sysUserDeptRoleInput.getUserId()}, UserIdentityStatus.NORMAL.getState());
                updateSysUserDeptRole(sysUserDeptRoleInput);
            }
            success++;
        }
        updateUserGitLinkRole(
                sysUserDeptRoleInput.getUserId()
                , sysUserDeptRoleInput.getDeptId()
                , null
                , sysUserDeptRoleInput.getRoleId()
                , OPERATE_ADD);
        return success;
    }

    @Override
    public List<SysUserDeptRole> selectSysUserDeptRoleListByDeptId(Long deptId) {
        return sysUserDeptRoleMapper.selectSysUserDeptRoleListByDeptId(deptId, null, null, null, null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertSysUserDeptRole(Long deptId, Long userId, String roleKey) {
        SysUserDeptRoleByDeptInput sysUserDeptRoleByDeptInput = new SysUserDeptRoleByDeptInput();
        sysUserDeptRoleByDeptInput.setUserId(userId);
        SysRole sysRole = sysRoleService.selectRoleByKey(roleKey);
        sysUserDeptRoleByDeptInput.setRoleId(sysRole.getRoleId());
        return insertSysUserDeptRoleListByDept(deptId, new SysUserDeptRoleByDeptInput[]{sysUserDeptRoleByDeptInput}) > 0;
    }

    @Override
    public boolean deleteSysUserDeptRole(Long deptId, Long userId, String roleKey) {
        SysUserDeptRole sysUserDeptRole = new SysUserDeptRole();
        sysUserDeptRole.setDeptId(deptId);
        sysUserDeptRole.setUserId(userId);
        SysUserDeptRole oldUserIdentify = sysUserDeptRoleMapper.selectSysUserDeptRoleByUserIdAndDeptId(userId, deptId);
        updateUserGitLinkRole(userId, deptId, oldUserIdentify.getRoleId(), null, OPERATE_REMOVE);
        SysRole sysRole = sysRoleService.selectRoleByKey(roleKey);
        sysUserDeptRole.setRoleId(sysRole.getRoleId());
        int success = sysUserDeptRoleMapper.deleteSysUserDeptRole(sysUserDeptRole);
        updateUserLoginInfoByUserId(userId);
        return success > 0;
    }

    @Override
    public void initMemberRole() {
        SysRole sysRole = sysRoleService.selectRoleByKey(SystemRole.ZONE_MEMBER.getRoleKey());
        SysUserDeptRole sysUserDeptRoleSearch = new SysUserDeptRole();
        sysUserDeptRoleSearch.setRoleId(sysRole.getRoleId());
        List<SysUserDeptRole> sysUserDeptRoleList = sysUserDeptRoleMapper.selectSysUserDeptRoleList(sysUserDeptRoleSearch);
        for (SysUserDeptRole sysUserDeptRole : sysUserDeptRoleList) {
            if (sysUserDeptRole.getSysDept() != null
                    && sysUserDeptRole.getSysRole() != null
                    && sysUserDeptRole.getSysUser() != null) {
                updateUserGitLinkRole(sysUserDeptRole.getUserId(), sysUserDeptRole.getDeptId(), null, sysUserDeptRole.getRoleId(), OPERATE_ADD);
            }
        }
    }

    @Override
    public List<SysUserDeptRole> selectSysUserDeptRoleListByDept(Long deptId, String search) {
        return sysUserDeptRoleMapper.searchSysUserDeptRoleListByDeptId(deptId, search);
    }

    @Override
    public Boolean checkUserInDeptHasRole(Long deptId, Long userId, String roleKey) {
        return sysUserDeptRoleMapper.countUserDeptRole(deptId, userId, roleKey) > 0;
    }

    @Override
    public GenericsTableDataInfo<JSONObject> selectGitlinkUserList(Long currentDeptId, GitLinkUserSearchVo gitLinkUserSearchVo) {
        List<SysUserDeptRole> sysUserDeptRoleList = selectSysUserDeptRoleListByDeptId(currentDeptId);
        String gitLinkUrl = gitLinkRequestHelper.gitLinkUrl;
        JSONObject result = gitLinkRequestHelper.doGet(
                GitLinkRequestUrl.USERS(gitLinkUserSearchVo.genQueryString())
        );
        JSONArray jsonArray = result.getJSONArray("users");
        if (jsonArray == null) {
            throw new ServiceException("Gitlink用户列表获取失败");
        }
        List<JSONObject> list = jsonArray.toJavaList(JSONObject.class);


        for (JSONObject userObj : list) {
            if (userObj.containsKey("image_url")) {
                String imagePath = userObj.getString("image_url");
                String authorImageUrl = EscapeUtil.removeExtraSlashOfUrl(String.format("%s/%s", gitLinkUrl, imagePath));
                userObj.put("image_url", authorImageUrl);
            }
            SysUserDeptRole userIdentify = sysUserDeptRoleList.stream().filter(x -> {
                if (x.getSysUser() != null) {
                    return x.getSysUser().getGitlinkUserId().equals(userObj.getLong("user_id"));
                }
                return false;
            }).findFirst().orElse(null);
            if (userIdentify != null && userIdentify.getSysRole() != null) {
                userObj.put("isChoose", true);
                userObj.put("currentRole", userIdentify.getSysRole().toSimpleSysRole());
            } else {
                userObj.put("isChoose", false);
            }

        }
        Long size = result.getLong("total_count");
        return new GenericsTableDataInfo<>(list, size);
    }

    @Override
    public void updateUserLoginInfoByRoleId(Long roleId) {
        List<SysUserDeptRole> userIdentifyList = sysUserDeptRoleMapper.selectSysUserDeptRoleListByRoleId(roleId);
        List<Long> userIdList = userIdentifyList.stream().map(SysUserDeptRole::getUserId).distinct().collect(Collectors.toList());
        for (Long userId : userIdList) {
            updateUserLoginInfoByUserId(userId);
        }
    }

    @Override
    public int countUserRoleByRoleId(Long roleId) {
        return sysUserDeptRoleMapper.countUserRoleByRoleId(roleId);
    }

    @Override
    public Boolean checkUserInDeptHasPerms(Long currentDeptId, Long userId, String perms) {
        SysUserDeptRole sysUserDeptRole = sysUserDeptRoleMapper.selectSysUserDeptRoleByUserIdAndDeptId(userId, currentDeptId);
        if (sysUserDeptRole != null && sysUserDeptRole.getSysRole() != null) {
            Set<String> permList = tokenService.getMenuPermissionsByRoleKey(sysUserDeptRole.getSysRole().getRoleKey());
            return permList.contains(perms);
        }
        return false;
    }

    @Override
    public Boolean checkUserInDept(Long currentDeptId, Long userId) {
        SysUserDeptRole sysUserDeptRole = sysUserDeptRoleMapper.selectSysUserDeptRoleByUserIdAndDeptId(userId, currentDeptId);
        return sysUserDeptRole != null;
    }

    @Override
    public void updateUserLoginInfoByDeptId(Long deptId) {
        List<SysUserDeptRole> userIdentifyList = selectSysUserDeptRoleListByDeptId(deptId);
        List<Long> userIdList = userIdentifyList.stream().map(SysUserDeptRole::getUserId).distinct().collect(Collectors.toList());
        for (Long userId : userIdList) {
            updateUserLoginInfoByUserId(userId);
        }
    }

    @Override
    public List<SysUserDeptRole> selectZoneUserIdentityListByUser(Long userId, Boolean isContainMember, String deptName, String roleName) {
        List<SysUserDeptRole> sysUserDeptRoleList = sysUserDeptRoleMapper.selectSysUserDeptRoleListByUserId(userId, deptName, roleName);
        // 仅保留特色专区类型以及无类型组织的身份
        sysUserDeptRoleList = sysUserDeptRoleList.stream().filter(x -> {
            if (x.getSysDept() != null) {
                SysDept sysDept = x.getSysDept();
                return sysDept.getDeptType() == null || Objects.equals(CacheConstants.DEPT_TYPE_TSZQ, sysDept.getDeptType());
            }
            return false;
        }).collect(Collectors.toList());
        // 关联需求：https://www.gitlink.org.cn/Gitlink/forgeplus/issues/3520
        if (isContainMember != null && !isContainMember) {
            return sysUserDeptRoleList
                    .stream()
                    .filter(x -> !SystemRole.ZONE_MEMBER.getRoleKey().equals(x.getSysRole().getRoleKey()))
                    .collect(Collectors.toList());
        }

        return sysUserDeptRoleList;
    }

    @Override
    public SysUserDeptRole getAllStatusUserIdentityByDeptIdAndUserId(Long deptId, Long userId) {
        return sysUserDeptRoleMapper.selectUserIdentityByAllStatus(deptId, userId);
    }

    @Override
    public void deleteSysUserDeptRoleByDeleteUser(Long userId) {
        sysUserDeptRoleMapper.updateUserIdentifyStateByUserId(userId, UserIdentityStatus.DELETE.getState());
    }

    private SysUser selectSysUserById(Long userId) {
        SysUser sysUser = sysUserMapper.selectUserById(userId);
        if (sysUser == null) {
            throw new ServiceException("该用户不存在(用户Id[" + userId + "]");
        }
        return sysUser;
    }

    private void selectSysRoleById(Long roleId) {
        SysRole sysRole = sysRoleService.selectRoleById(roleId);
        if (sysRole == null) {
            throw new ServiceException("该角色不存在(角色Id[" + roleId + "]");
        }
    }
}
