package com.microservices.pms.enterprise.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.constant.CacheConstants;
import com.microservices.common.core.constant.HttpStatus;
import com.microservices.common.core.constant.SecurityConstants;
import com.microservices.common.core.enums.SystemRole;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.PageUtils;
import com.microservices.common.core.utils.html.EscapeUtil;
import com.microservices.common.core.utils.sign.Base64;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
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.pms.common.service.IPmsCommonAsyncService;
import com.microservices.pms.common.service.IPmsCommonService;
import com.microservices.pms.common.service.impl.PmsCommonAsyncServiceImpl;
import com.microservices.pms.enterprise.domain.PmsEnterprise;
import com.microservices.pms.enterprise.domain.vo.*;
import com.microservices.pms.enterprise.mapper.PmsEnterpriseMapper;
import com.microservices.pms.enterprise.service.IPmsEnterpriseService;
import com.microservices.pms.product.domain.PmsProduct;
import com.microservices.pms.product.domain.vo.PmsProductSearchVo;
import com.microservices.pms.product.service.IPmsProductRequirementTagService;
import com.microservices.pms.product.service.IPmsProductService;
import com.microservices.pms.project.domain.PmsProject;
import com.microservices.pms.project.service.IPmsProjectService;
import com.microservices.pms.utils.PmsConstants;
import com.microservices.pms.utils.PmsGitLinkRequestUrl;
import com.microservices.system.api.RemoteDeptService;
import com.microservices.system.api.RemoteUserService;
import com.microservices.system.api.domain.SimpleSysRole;
import com.microservices.system.api.domain.SimpleSysUser;
import com.microservices.system.api.domain.SysUserDeptRole;
import com.microservices.system.api.utils.FeignUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 项目管理企业Service业务层处理
 *
 * @author otto
 * @date 2023-10-10
 */
@Service
public class PmsEnterpriseServiceImpl implements IPmsEnterpriseService {
    private static final Logger logger = LoggerFactory.getLogger(PmsCommonAsyncServiceImpl.class);
    @Autowired
    private PmsEnterpriseMapper pmsEnterpriseMapper;
    @Autowired
    private GitLinkRequestHelper gitLinkRequestHelper;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private RemoteDeptService remoteDeptService;
    @Autowired
    @Lazy
    private IPmsCommonAsyncService commonAsyncService;
    @Autowired
    @Lazy
    private IPmsProductRequirementTagService pmsProductRequirementTagService;
    @Autowired
    @Lazy
    private IPmsProductService pmsProductService;
    @Autowired
    @Lazy
    private IPmsProjectService pmsProjectService;
    @Autowired
    private IPmsCommonService pmsCommonService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private RedisService redisService;
    @Value("${pms.pmsUrl}")
    private String pmsUrl;

    /**
     * 查询项目管理企业
     *
     * @param id 项目管理企业主键
     * @return 项目管理企业
     */
    @Override
    public PmsEnterprise selectPmsEnterpriseById(Long id)
    {
        // 企业信息在项目管理的每次接口请求中都会执行查询，加入到Redis缓存减少数据库查询次数
        String enterpriseRedisKey = CacheConstants.getEnterpriseIdKey(id);
        PmsEnterprise pmsEnterprise;
        if (redisService.hasKey(enterpriseRedisKey)) {
            pmsEnterprise = redisService.getCacheObject(enterpriseRedisKey);
        } else {
            pmsEnterprise = pmsEnterpriseMapper.selectPmsEnterpriseById(id);
            if (pmsEnterprise == null) {
                throw new ServiceException("该企业不存在(企业ID[%s])", id);
            }
            redisService.setCacheObject(enterpriseRedisKey, pmsEnterprise);
        }

        checkEnterpriseIsCurrentEnterprise(pmsEnterprise);
        return pmsEnterprise;
    }

    @Override
    public PmsEnterprise selectPmsEnterpriseByIdentifier(String identifier) {
        // 企业信息在项目管理的每次接口请求中都会执行查询，加入到Redis缓存减少数据库查询次数
        String enterpriseRedisKey = CacheConstants.getEnterpriseIdentifierKey(identifier);
        PmsEnterprise pmsEnterprise;
        if (redisService.hasKey(enterpriseRedisKey)) {
            pmsEnterprise = redisService.getCacheObject(enterpriseRedisKey);
        } else {
            pmsEnterprise = pmsEnterpriseMapper.selectPmsEnterpriseByIdentifier(identifier);
            if (pmsEnterprise == null) {
                throw new ServiceException("该企业不存在(企业标识[%s])", identifier);
            }
            redisService.setCacheObject(enterpriseRedisKey, pmsEnterprise);
        }
        if (!checkEnterpriseInitComplete(pmsEnterprise.getGitlinkOrgId())) {
            throw new ServiceException("当前组织初始化未完成，不允许进行操作!");
        }
        pmsEnterprise.setGitlinkUrl(gitLinkRequestHelper.gitLinkUrl);
        checkEnterpriseIsCurrentEnterprise(pmsEnterprise);
        return pmsEnterprise;
    }

    private void clearPmsEnterpriseForRedis(PmsEnterprise pmsEnterprise) {
        redisService.deleteObject(CacheConstants.getEnterpriseIdentifierKey(pmsEnterprise.getEnterpriseIdentifier()));
        redisService.deleteObject(CacheConstants.getEnterpriseIdKey(pmsEnterprise.getId()));
    }

    /**
     * 查询项目管理企业列表
     *
     * @param pmsEnterprise 项目管理企业
     * @return 项目管理企业
     */
    @Override
    public GenericsTableDataInfo<PmsEnterprise> selectMyPmsEnterpriseList(PmsEnterprise pmsEnterprise)
    {
        List<SysUserDeptRole> userIdentifyList = tokenService.getAllUserIdentity(SecurityUtils.getUsername());
        List<Long> deptIdList = userIdentifyList.stream().map(SysUserDeptRole::getDeptId).collect(Collectors.toList());
        if (deptIdList.isEmpty()) {
            return new GenericsTableDataInfo<>();
        }
        return PageUtils.toPage(pmsEnterpriseMapper.selectPmsEnterpriseList(pmsEnterprise, deptIdList));
    }

    /**
     * 新增项目管理企业
     *
     * @param pmsEnterprise 项目管理企业
     * @return 结果
     */
    @Override
    public String insertPmsEnterprise(PmsEnterprise pmsEnterprise)
    {
        throw new ServiceException("当前不支持直接创建企业，请基于Gitlink组织升级为工作台");
//        // 将图片地址转换为base64字符串
//        String base64Image = Base64.imageUrlToBase64(pmsEnterprise.getEnterpriseImage());
//        // 基于企业在Gitlink下创建组织
//        JSONObject jsonObject = (JSONObject) JSON.toJSON(pmsEnterprise.toGitlinkOrganizationInputVo(base64Image));
//        JSONObject createOrganizationRes = gitLinkRequestHelper.doPost(PmsGitLinkRequestUrl.CREATE_ORGANIZATION(), jsonObject);
//        // 设置gitlink组织id
//        pmsEnterprise.setGitlinkOrgId(createOrganizationRes.getLong("id"));
//        return createEnterprise(pmsEnterprise, gitLinkUserToEnterpriseInputVo);
    }

    @Override
    public String createByGitlinkOrgId(Long gitlinkOrgId, List<GitLinkUserToEnterpriseInputVo> gitLinkUserToEnterpriseInputVoList) {
        if (pmsEnterpriseMapper.selectPmsEnterpriseByGitlinkOrgId(gitlinkOrgId) != null) {
            throw new ServiceException("该组织已开通组织工作台，请勿重复开通");
        }
        boolean isContainCurrentUser = gitLinkUserToEnterpriseInputVoList
                .stream()
                .anyMatch(x -> SecurityUtils.getGitlinkUserId() != null && SecurityUtils.getGitlinkUserId().equals(x.getUserId()));
        if (!isContainCurrentUser) {
            throw new ServiceException("开通组织工作台需保留当前操作用户");
        }
        checkGitlinkUserToEnterpriseVoList(gitLinkUserToEnterpriseInputVoList);
        PmsEnterprise pmsEnterprise = getPmsEnterpriseByGitlinkOrgId(gitlinkOrgId);
        return createEnterprise(pmsEnterprise, gitLinkUserToEnterpriseInputVoList);
    }

    /**
     * 用户升级列表中至少存在一个组织管理员
     *
     * @param gitLinkUserToEnterpriseInputVoList 用户升级列表
     */
    private void checkGitlinkUserToEnterpriseVoList(List<GitLinkUserToEnterpriseInputVo> gitLinkUserToEnterpriseInputVoList) {
        if (gitLinkUserToEnterpriseInputVoList.stream().noneMatch(x -> SystemRole.PMS_ORG_ADMIN.getRoleKey().equals(x.getRoleKey()))) {
            throw new ServiceException("开通组织工作台时至少需要保留一位组织管理员角色");
        }
    }

    private PmsEnterprise getPmsEnterpriseByGitlinkOrgId(Long gitlinkOrgId) {
        GitlinkOrganizationDetailVo gitlinkOrgDetail = gitLinkRequestHelper.doGet(
                PmsGitLinkRequestUrl.GET_OR_PATCH_ORGANIZATION(gitlinkOrgId), GitlinkOrganizationDetailVo.class
        );
        return gitlinkOrgDetail.toPmsEnterprise(gitLinkRequestHelper.gitLinkUrl);
    }

    @Override
    public GenericsTableDataInfo<GitLinkUserToEnterpriseVo> getGitlinkUserList(Long gitlinkOrgId) {
        List<GitLinkUserToEnterpriseVo> gitLinkUserToEnterpriseVoList = new ArrayList<>();
        // 获取Gitlink组织下所有团队
        PmsEnterprise pmsEnterprise = getPmsEnterpriseByGitlinkOrgId(gitlinkOrgId);
        List<GitlinkOrganizationTeamVo> gitlinkOrganizationTeamVoList = pmsCommonService.getAllGitlinkOrgTeams(gitlinkOrgId);
        if (gitlinkOrganizationTeamVoList.isEmpty()) {
            return PageUtils.toPage(gitLinkUserToEnterpriseVoList);
        }
        // 依次获取每个团队下的所有成员
        for (GitlinkOrganizationTeamVo gitlinkOrganizationTeamVo : gitlinkOrganizationTeamVoList) {
            List<GitLinkUserSimpleInfoVo> gitlinkUserList = pmsCommonService.getAllGitlinkUsersByOrgTeam(
                    pmsEnterprise.getEnterpriseIdentifier(), gitlinkOrganizationTeamVo.getId()
            );
            if ("owner".equalsIgnoreCase(gitlinkOrganizationTeamVo.getAuthorize())) {
                boolean currentUserIsOwner = gitlinkUserList.stream().anyMatch(x -> x.getUserId().equals(SecurityUtils.getGitlinkUserId()));
                if (!currentUserIsOwner) {
                    if (SecurityUtils.getLoginUser() != null) {
                        gitlinkUserList.add(new GitLinkUserSimpleInfoVo(SecurityUtils.getLoginUser().getSysUser()));
                    }
                }
            }
            for (GitLinkUserSimpleInfoVo gitLinkUserSimpleInfoVo : gitlinkUserList) {
                if (gitLinkUserSimpleInfoVo.getUserId() == null) {
                    break;
                }
                // 检查成员列表中是否已存在该成员
                GitLinkUserToEnterpriseVo gitLinkUserToEnterpriseVo = gitLinkUserToEnterpriseVoList
                        .stream()
                        .filter(x -> gitLinkUserSimpleInfoVo.getUserId().equals(x.getUserId()))
                        .findFirst()
                        .orElse(null);
                if (gitLinkUserToEnterpriseVo != null) {
                    // 判断当前团队权限是否比已存在成员的权限更大，若拥有更大的权限删除团队中成员并将当前团队成员添加进来
                    if (gitLinkUserToEnterpriseVo.greaterAuth(gitlinkOrganizationTeamVo.getAuthorize())) {
                        gitLinkUserToEnterpriseVoList.removeIf(x -> gitLinkUserSimpleInfoVo.getUserId().equals(x.getUserId()));
                        gitLinkUserToEnterpriseVoList.add(
                                gitLinkUserSimpleInfoVo.toGitLinkUserToEnterpriseInputVo(gitlinkOrganizationTeamVo.getAuthorize()));
                    }
                } else {
                    // 若列表中不存在，则添加该成员
                    gitLinkUserToEnterpriseVoList.add(
                            gitLinkUserSimpleInfoVo.toGitLinkUserToEnterpriseInputVo(gitlinkOrganizationTeamVo.getAuthorize()));
                }
            }
        }
        return PageUtils.toPage(gitLinkUserToEnterpriseVoList);
    }

    @Override
    public int deletePmsEnterpriseByIdentifier(String enterpriseIdentifier, String password) {
        PmsEnterprise pmsEnterprise = selectPmsEnterpriseByIdentifier(enterpriseIdentifier);
        // 校验用户密码是否正确
        JSONObject passwordObj = new JSONObject();
        passwordObj.put("password", password);
        gitLinkRequestHelper.doPost(
                PmsGitLinkRequestUrl.CHECK_PASSWORD(SecurityUtils.getUsername()), passwordObj, true
        );
        // 删除企业下所有产品
        PmsProductSearchVo pmsProductSearch = new PmsProductSearchVo();
        pmsProductSearch.setPmsEnterpriseIdentifier(pmsEnterprise.getEnterpriseIdentifier());
        List<PmsProduct> pmsProductList = pmsProductService.selectPmsProductList(pmsProductSearch);
        for (PmsProduct pmsProduct : pmsProductList) {
            pmsProductService.deletePmsProductById(pmsProduct.getId());
        }
        PmsProject pmsProjectSearch = new PmsProject();
        pmsProjectSearch.setPmsEnterpriseId(pmsEnterprise.getId());
        List<PmsProject> pmsProjectList = pmsProjectService.selectPmsProjectList(pmsProjectSearch);
        pmsProjectService.deletePmsProjectByIds(pmsProjectList.stream().map(PmsProject::getId).toArray(Long[]::new));
        // 删除企业对应部门
        remoteDeptService.deleteDeptByDeptId(pmsEnterprise.getDeptId(), SecurityConstants.INNER);
        // 清理redis缓存
        redisService.deleteObject(CacheConstants.getEnterpriseIdKey(pmsEnterprise.getId()));
        redisService.deleteObject(CacheConstants.getEnterpriseIdentifierKey(pmsEnterprise.getEnterpriseIdentifier()));
        return pmsEnterpriseMapper.deletePmsEnterpriseById(pmsEnterprise.getId());
    }

    @Override
    public PmsEnterprise selectPmsEnterpriseByDeptId(Long deptId) {
        return pmsEnterpriseMapper.selectPmsEnterpriseByDeptId(deptId);
    }

    private String createEnterprise(PmsEnterprise pmsEnterpriseInput, List<GitLinkUserToEnterpriseInputVo> gitLinkUserToEnterpriseInputVoList) {
        // 当前会话中忽略数据权限校验
        SecurityUtils.setIgnoreDataScopeCheck();
        checkPmsEnterprise(pmsEnterpriseInput);
        try {
            increaseOpenEnterpriseProcessCount(pmsEnterpriseInput.getGitlinkOrgId());
            // 先创建组织Id为0的企业
            pmsEnterpriseInput.setDeptId(0L);
            pmsEnterpriseInput.setCreateBy(SecurityUtils.getUsername());
            pmsEnterpriseInput.setCreateTime(DateUtils.getNowDate());
            pmsEnterpriseMapper.insertPmsEnterprise(pmsEnterpriseInput);
            // 基于企业信息在若依下新建部门
            Long deptId = FeignUtils.getReturnData(remoteDeptService.addDeptByPmsEnterprise(pmsEnterpriseInput.getEnterpriseName(), SecurityConstants.INNER));
            pmsEnterpriseInput.setDeptId(deptId);
            pmsEnterpriseMapper.updatePmsEnterprise(pmsEnterpriseInput);

            clearPmsEnterpriseForRedis(pmsEnterpriseInput);
            commonAsyncService.syncGitlinkOrganizationUserToPmsEnterprise(pmsEnterpriseInput.getId(), gitLinkUserToEnterpriseInputVoList);
            commonAsyncService.syncInitPmsEnterpriseData(pmsEnterpriseInput.getId(), SecurityUtils.getGitlinkUserId());
            pmsProductRequirementTagService.insertDefaultPmsProductRequirementTag(pmsEnterpriseInput.getId());
            return pmsEnterpriseInput.getEnterpriseIdentifier();
        } catch (Exception e) {
            // 先删除对应企业
            pmsEnterpriseMapper.deletePmsEnterpriseById(pmsEnterpriseInput.getId());
            // 删除已创建的部门
            remoteDeptService.deleteDeptByPmsEnterprise(pmsEnterpriseInput.getEnterpriseName(), SecurityConstants.INNER);
            logger.error("新增企业时发生异常：{}", e.getMessage());
            throw new ServiceException("新增企业失败：%s", e.getMessage());
        } finally {
            decreaseOpenEnterpriseProcessCount(pmsEnterpriseInput.getGitlinkOrgId());
        }
    }

    private void checkPmsEnterprise(PmsEnterprise pmsEnterpriseInput) {
        PmsEnterprise pmsEnterpriseByName = pmsEnterpriseMapper.selectPmsEnterpriseByName(pmsEnterpriseInput.getEnterpriseName());
        if (pmsEnterpriseByName != null) {
            throw new ServiceException("该企业名称已存在(企业名称[%s])", pmsEnterpriseInput.getEnterpriseName());
        }
        PmsEnterprise pmsEnterpriseByIdentifier = pmsEnterpriseMapper.selectPmsEnterpriseByIdentifier(pmsEnterpriseInput.getEnterpriseIdentifier());
        if (pmsEnterpriseByIdentifier != null) {
            throw new ServiceException("该企业标识已存在(企业标识[%s])", pmsEnterpriseInput.getEnterpriseIdentifier());
        }
    }

    /**
     * 修改项目管理企业
     *
     * @param pmsEnterpriseUpdate 项目管理企业
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updatePmsEnterprise(PmsEnterprise pmsEnterpriseUpdate)
    {
        PmsEnterprise oldPmsEnterprise = selectPmsEnterpriseByIdentifier(pmsEnterpriseUpdate.getEnterpriseIdentifier());
        clearPmsEnterpriseForRedis(oldPmsEnterprise);
        if (pmsEnterpriseUpdate.getEnterpriseName() != null && !pmsEnterpriseUpdate.getEnterpriseName().equals(oldPmsEnterprise.getEnterpriseName())) {
            PmsEnterprise pmsEnterpriseByName = pmsEnterpriseMapper.selectPmsEnterpriseByName(pmsEnterpriseUpdate.getEnterpriseName());
            if (pmsEnterpriseByName != null) {
                throw new ServiceException("该企业名称已存在(企业名称[%s])", pmsEnterpriseUpdate.getEnterpriseName());
            }
            // 更新部门名称
            remoteDeptService.updateDeptNameByDeptId(oldPmsEnterprise.getDeptId(), pmsEnterpriseUpdate.getEnterpriseName(), SecurityConstants.INNER);
        }
        String base64Image = null;
        if (pmsEnterpriseUpdate.getEnterpriseImage() != null && !pmsEnterpriseUpdate.getEnterpriseImage().equals(oldPmsEnterprise.getEnterpriseImage())) {
            base64Image = Base64.imageUrlToBase64(pmsEnterpriseUpdate.getEnterpriseImage());
        }

        JSONObject updateJsonObj = (JSONObject) JSON.toJSON(oldPmsEnterprise.toGitlinkOrganizationUpdateVo(pmsEnterpriseUpdate, base64Image));
        // 更新gitlink组织信息
        gitLinkRequestHelper.doPatch(
                PmsGitLinkRequestUrl.GET_OR_PATCH_ORGANIZATION(
                        oldPmsEnterprise.getGitlinkOrgId()), updateJsonObj);
        pmsEnterpriseUpdate.setId(oldPmsEnterprise.getId());
        pmsEnterpriseUpdate.setUpdateBy(SecurityUtils.getUsername());
        pmsEnterpriseUpdate.setUpdateTime(DateUtils.getNowDate());
        return pmsEnterpriseMapper.updatePmsEnterprise(pmsEnterpriseUpdate);
    }

    /**
     * 删除项目管理企业信息
     *
     * @param id       项目管理企业主键
     * @param password 用户密码
     * @return 结果
     */
    @Override
    public int deletePmsEnterpriseById(Long id, String password)
    {
        PmsEnterprise pmsEnterprise = selectPmsEnterpriseById(id);
        clearPmsEnterpriseForRedis(pmsEnterprise);
        // 删除gitlink下组织，同时校验用户密码是否正确
        gitLinkRequestHelper.doDelete(
                PmsGitLinkRequestUrl.DELETE_ORGANIZATION(pmsEnterprise.getGitlinkOrgId(), password)
        );
        // 删除企业下所有产品
        PmsProductSearchVo pmsProductSearch = new PmsProductSearchVo();
        pmsProductSearch.setPmsEnterpriseIdentifier(pmsEnterprise.getEnterpriseIdentifier());
        List<PmsProduct> pmsProductList = pmsProductService.selectPmsProductList(pmsProductSearch);
        for (PmsProduct pmsProduct : pmsProductList) {
            pmsProductService.deletePmsProductById(pmsProduct.getId());
        }
        // 删除企业对应部门
        remoteDeptService.deleteDeptByDeptId(pmsEnterprise.getDeptId(), SecurityConstants.INNER);
        return pmsEnterpriseMapper.deletePmsEnterpriseById(id);
    }

    private void checkEnterpriseIsCurrentEnterprise(PmsEnterprise pmsEnterprise) {
        // 校验操作的是否为当前访问的企业
        if (!SecurityUtils.isAdmin() && !SecurityUtils.checkCurrentDeptId(pmsEnterprise.getDeptId())) {
            PmsEnterprise currentpmsEnterprise = selectPmsEnterpriseByDeptId(SecurityUtils.getDeptId());
            if (currentpmsEnterprise == null) {
                throw new ServiceException(HttpStatus.FORBIDDEN, "当前用户无权限访问该企业(用户名[%s])"
                        , SecurityUtils.getUsername());
            }
            throw new ServiceException(HttpStatus.FORBIDDEN, "当前用户无权限访问该企业(用户名[%s],当前访问企业名称[%s])"
                    , SecurityUtils.getUsername(), currentpmsEnterprise.getEnterpriseName());
        }
    }

    /**
     * 检查用户是否在企业中
     * @param enterpriseId 企业ID
     * @param userId 用户Id
     */
    @Override
    public boolean checkUserInEnterprise(Long enterpriseId, Long userId) {
//        PmsEnterprise pmsEnterprise=selectPmsEnterpriseById(enterpriseId);
//        Boolean isExist = FeignUtils.getReturnData(
//                remoteDeptService.checkUserInDept(pmsEnterprise.getDeptId(), userId, SecurityConstants.INNER)
//        );
//        return isExist != null && isExist;
        //TODO: 由于成员可能会被移出企业，所以暂不校验用户是否在企业中
        return true;
    }

    @Override
    public GenericsTableDataInfo<SimpleSysUser> getUserListByEnterpriseIdentifier(String enterpriseIdentifier, String search, Integer pageNum, Integer pageSize) {
        PmsEnterprise pmsEnterprise = pmsEnterpriseMapper.selectPmsEnterpriseByIdentifier(enterpriseIdentifier);
        return getUserListByEnterprise(pmsEnterprise, search, pageNum, pageSize);
    }

    @Override
    public GenericsTableDataInfo<SimpleSysUser> getUserListById(Long enterpriseId, String search, Integer pageNum, Integer pageSize) {
        PmsEnterprise pmsEnterprise = pmsEnterpriseMapper.selectPmsEnterpriseById(enterpriseId);
        return getUserListByEnterprise(pmsEnterprise, search, pageNum, pageSize);
    }

    private GenericsTableDataInfo<SimpleSysUser> getUserListByEnterprise(PmsEnterprise pmsEnterprise, String search, Integer pageNum, Integer pageSize) {
        GenericsTableDataInfo<SysUserDeptRole> userIdentifierTable = FeignUtils.getReturnData(
                remoteUserService.searchUserIdentifierListByDept(pmsEnterprise.getDeptId(), search, pageNum, pageSize, SecurityConstants.INNER)
        );
        if (userIdentifierTable == null) {
            return new GenericsTableDataInfo<>();
        }
        List<SimpleSysUser> userList = new ArrayList<>();
        for (SysUserDeptRole userIdentifier : userIdentifierTable.getRows()) {
            userList.add(userIdentifier.getSysUser().toSimpleSysUser(gitLinkRequestHelper.gitLinkUrl));
        }
        return PageUtils.toPage(userList, userIdentifierTable.getTotal());
    }

    /**
     * 切换用户在Gitlink下权限（原为空新不为空代表新增、原不为空新为空代表删除、原与新均不为空且不相同代表切换）
     *
     * @param userId    用户id
     * @param oldRoleId 原角色Id
     * @param newRoleId 新角色Id
     * @return 结果
     */
    public Boolean changeUserGitlinkRole(Long userId, Long deptId, Long oldRoleId, Long newRoleId) {
        commonAsyncService.syncChangeUserGitlinkRole(userId, deptId, oldRoleId, newRoleId);
        return true;
    }

    @Override
    public Long initGitlinkOrgAdminTeam(String enterpriseIdentifier) {
        GitlinkOrganizationTeamInputVo gitlinkOrganizationTeamInputVo = new GitlinkOrganizationTeamInputVo();
        gitlinkOrganizationTeamInputVo.setName(PmsConstants.GITLINK_ORGANIZATION_TEAM_ADMIN);
        gitlinkOrganizationTeamInputVo.setNickname("项目管理员团队");
        gitlinkOrganizationTeamInputVo.setAuthorize("admin");
        gitlinkOrganizationTeamInputVo.setDescription("成员可以拉取和推送到团队项目同时可以添加协作者");
        JSONObject resObj = gitLinkRequestHelper.doPost(
                PmsGitLinkRequestUrl.CREATE_ORGANIZATION_TEAM(enterpriseIdentifier), JSONObject.from(gitlinkOrganizationTeamInputVo));
        return resObj.getLong("id");
    }

    @Override
    public Long initGitlinkOrgWriteTeam(String enterpriseIdentifier) {
        GitlinkOrganizationTeamInputVo gitlinkOrganizationTeamInputVo = new GitlinkOrganizationTeamInputVo();
        gitlinkOrganizationTeamInputVo.setName(PmsConstants.GITLINK_ORGANIZATION_TEAM_WRITE);
        gitlinkOrganizationTeamInputVo.setNickname("普通成员团队");
        gitlinkOrganizationTeamInputVo.setAuthorize("write");
        gitlinkOrganizationTeamInputVo.setDescription("成员可以查看和推送提交到团队项目");
        JSONObject resObj = gitLinkRequestHelper.doPost(
                PmsGitLinkRequestUrl.CREATE_ORGANIZATION_TEAM(enterpriseIdentifier), JSONObject.from(gitlinkOrganizationTeamInputVo));
        return resObj.getLong("id");
    }

    @Override
    public GenericsTableDataInfo<SimpleSysUser> getUserListByPerms(String enterpriseIdentifier, String search, String perms) {
        PmsEnterprise pmsEnterprise = selectPmsEnterpriseByIdentifier(enterpriseIdentifier);
        GenericsTableDataInfo<SysUserDeptRole> userIdentifierTable = FeignUtils.getReturnData(
                remoteUserService.searchUserIdentifierListByDept(pmsEnterprise.getDeptId(), search, null, null, SecurityConstants.INNER)
        );
        if (userIdentifierTable == null) {
            return new GenericsTableDataInfo<>();
        }
        List<SimpleSysUser> userList = new ArrayList<>();
        for (SysUserDeptRole userIdentifier : userIdentifierTable.getRows()) {
            Boolean hasPerms = FeignUtils.getReturnData(
                    remoteDeptService.checkUserInDeptHasPerms(
                            pmsEnterprise.getDeptId()
                            , userIdentifier.getUserId()
                            , perms
                            , SecurityConstants.INNER)
            );
            if (hasPerms != null && hasPerms) {
                userList.add(userIdentifier.getSysUser().toSimpleSysUser(gitLinkRequestHelper.gitLinkUrl));
            }
        }
        return PageUtils.toPage(userList);
    }

    @Override
    public GenericsTableDataInfo<SimpleSysRole> getRoleList() {
        List<SimpleSysRole> simpleSysRoleList = new ArrayList<>();
        simpleSysRoleList.add(new SimpleSysRole(SystemRole.PMS_ORG_ADMIN));
        simpleSysRoleList.add(new SimpleSysRole(SystemRole.PMS_PROJECT_MANAGER));
        simpleSysRoleList.add(new SimpleSysRole(SystemRole.PMS_USER));
        return PageUtils.toPage(simpleSysRoleList);

    }

    @Override
    public WorkbenchUrlDataVo getWorkbenchUrl(Long gitlinkOrgId) {
        WorkbenchUrlDataVo workbenchUrlDataVo = new WorkbenchUrlDataVo();
        PmsEnterprise pmsEnterprise = pmsEnterpriseMapper.selectPmsEnterpriseByGitlinkOrgId(gitlinkOrgId);
        if (pmsEnterprise != null) {
            workbenchUrlDataVo.setIsOpen(true);
            if (!checkEnterpriseInitComplete(gitlinkOrgId)) {
                workbenchUrlDataVo.setUrl(null);
            } else {
                workbenchUrlDataVo.setUrl(EscapeUtil.removeExtraSlashOfUrl(String.format("%s/%s", pmsUrl, pmsEnterprise.getEnterpriseIdentifier())));
            }
            return workbenchUrlDataVo;
        }
        return workbenchUrlDataVo;
    }

    /**
     * 开通组织工作台存在多个异步流程，每个异步流程增加一个数量
     *
     * @param gitlinkOrgId gitlink组织Id
     */
    @Override
    public void increaseOpenEnterpriseProcessCount(Long gitlinkOrgId) {
        String redisKey = CacheConstants.getGitlinkOrgIdOpenEnterpriseKey(gitlinkOrgId);
        if (redisService.hasKey(redisKey)) {
            Integer processCount = redisService.getCacheObject(redisKey);
            processCount++;
            redisService.setCacheObject(
                    redisKey
                    , processCount
                    , 1L
                    , TimeUnit.HOURS);
        } else {
            redisService.setCacheObject(
                    redisKey
                    , 1
                    , 1L
                    , TimeUnit.HOURS);
        }
    }

    /**
     * 通组织工作台存在多个异步流程，每处理完异步流程减少一个数量
     *
     * @param gitlinkOrgId gitlink组织Id
     */
    @Override
    public void decreaseOpenEnterpriseProcessCount(Long gitlinkOrgId) {
        String redisKey = CacheConstants.getGitlinkOrgIdOpenEnterpriseKey(gitlinkOrgId);
        if (redisService.hasKey(redisKey)) {
            Integer processCount = redisService.getCacheObject(redisKey);
            if (processCount <= 1) {
                redisService.deleteObject(redisKey);
            } else {
                processCount--;
                redisService.setCacheObject(
                        redisKey
                        , processCount
                        , 1L
                        , TimeUnit.HOURS);
            }
        }
    }

    private Boolean checkEnterpriseInitComplete(Long gitlinkOrgId) {
        return !redisService.hasKey(CacheConstants.getGitlinkOrgIdOpenEnterpriseKey(gitlinkOrgId));
    }
}
