package com.friday.tooldriver.service.rpa.supplier;

import com.alibaba.fastjson.JSON;
import com.friday.tooldriver.dto.uipath.common.*;
import com.friday.tooldriver.dto.uipath.request.*;
import com.friday.tooldriver.dto.uipath.response.*;
import com.friday.tooldriver.util.OkHttpService;
import com.friday.tooldriver.util.TaieHttpResponse;
import com.google.common.collect.Lists;
import com.friday.base.common.response.DubboResult;
import com.friday.operation.api.keepalive.dto.taieoc.OcTenantDetailDto;
import com.friday.operation.api.keepalive.dto.taieoc.OcTenantFilterDto;
import com.friday.operation.api.keepalive.service.taieoc.ITenantManage;
import com.friday.operation.api.tooldriver.dto.common.DriverBase;
import com.friday.operation.api.tooldriver.dto.rpa.FileInfoDto;
import com.friday.operation.api.tooldriver.dto.rpa.JobFilter;
import com.friday.operation.api.tooldriver.dto.rpa.RobotFilter;
import com.friday.tooldriver.constants.uipath.FilterOperation;
import com.friday.tooldriver.constants.uipath.OrderByEnum;
import com.friday.tooldriver.constants.uipath.UIPathApiEnum;
import com.friday.tooldriver.dto.uipath.common.*;
import com.friday.tooldriver.dto.uipath.request.*;
import com.friday.tooldriver.dto.uipath.response.*;
import com.friday.tooldriver.exception.DriverBusinessException;
import com.friday.tooldriver.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.friday.operation.api.tooldriver.constant.DriverConstant.*;
import static com.friday.tooldriver.constants.DriverSystemCode.UIPATH_RESPONSE_DATA_ERROR;
import static com.friday.tooldriver.constants.uipath.UIPathApiEnum.*;

/**
 * @Author YaoYao
 * @Date Created In 09:47 2022/12/20
 * @Description UIPATH服务类
 * @Modified By GW
 */
@Slf4j
@Service
public class UIPATHService{

    @Autowired
    private OkHttpService okHttpService;
    @Autowired(required = false)
    private RedissonClient redissonClient;
    @Autowired
    private ITenantManage tenantManage;

    @Value("${uipath.package.file.path}")
    private String uiPathPkgFilePath;

    /**
     * 验证信息
     */
    public String authenticate(DriverBase driverBase) throws DriverBusinessException {
        OcTenantDetailDto ocTenantInfo = getOcTenantInfo(driverBase);
        LoginRequestDto login = LoginRequestDto.builder()
                .tenancyName(ocTenantInfo.getOcTenant())
                .usernameOrEmailAddress(ocTenantInfo.getOcTenantUser())
                .password(ocTenantInfo.getOcTenantPassword())
                .build();
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, false);
            UiPathOriginResult<LoginResponseDto> loginResult = this.doRequest(getOcBaseUrl(driverBase), AUTHENTICATE, headerMap, JSON.toJSONString(login), null);
            if(loginResult.success()){
                return loginResult.getObject().getResult();
            }
            throw new DriverBusinessException("获取UIPATH登录token失败:" + loginResult.getMessage());
        } catch (Exception e){
            log.error(AUTHENTICATE.getSystemCode().getMessage(), e);
            throw new DriverBusinessException("获取UIPATH登录token异常:" + e.getMessage());
        }
    }

    /**
     * 获取中控租户相关信息
     */
    public OcTenantDetailDto getOcTenantInfo(DriverBase driverBase) throws DriverBusinessException {
        OcTenantFilterDto filter = OcTenantFilterDto.ocTenantFilterBuilder()
                .ocTenantId(Long.parseLong(driverBase.getTenantKey()))
                .build();
        DubboResult<ArrayList<OcTenantDetailDto>> result = tenantManage.queryTenantDetail(filter);
        if(!result.success() || CollectionUtils.isEmpty(result.getObject())){
            log.error(AUTHENTICATE.getSystemCode().getMessage(), result.getMessage() + "或根据中控信息查询结果为空");
            throw new DriverBusinessException("查询到的中控租户信息为空:" + JSON.toJSONString(driverBase));
        }
        return result.getObject().get(0);
    }

    /**
     * 创建文件夹
     */
    public DubboResult<FolderDto> createFolder(DriverBase driverBase, FolderDto folder){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<FolderDto> result = this.doRequest(getOcBaseUrl(driverBase), CREATE_FOLDER, headerMap, JSON.toJSONString(folder), null);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(CREATE_FOLDER.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(CREATE_FOLDER.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(CREATE_FOLDER.getSystemCode().getCode(), CREATE_FOLDER.getSystemCode().getMessage());
        }
    }

    /**
     * 批量查询文件夹
     */
    public DubboResult<ArrayList<FolderDto>> queryFolders(DriverBase driverBase, FolderDto folder){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<ODataResponseDto<FolderDto>> result = this.doRequest(getOcBaseUrl(driverBase), GET_FOLDERS, headerMap, null, null);
            if(result.success()){
                return DubboResult.newSuccess(Lists.newArrayList(result.getObject().getValue()));
            } else {
                return DubboResult.newFailure(GET_FOLDERS.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_FOLDERS.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_FOLDERS.getSystemCode().getCode(), GET_FOLDERS.getSystemCode().getMessage());
        }
    }

    /**
     * 查询单个文件夹
     */
    public DubboResult<FolderDto> queryFolderById(DriverBase driverBase, String folderId){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(folderId).build();
            UiPathOriginResult<FolderDto> result = this.doRequest(getOcBaseUrl(driverBase), GET_FOLDER, headerMap, null, urlParam);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(GET_FOLDER.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_FOLDER.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_FOLDER.getSystemCode().getCode(), GET_FOLDER.getSystemCode().getMessage());
        }
    }

    /**
     * 删除单个文件夹
     */
    public DubboResult deleteFolderById(DriverBase driverBase, String folderId){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(folderId).build();
            UiPathOriginResult<String> result = this.doRequest(getOcBaseUrl(driverBase), DELETE_FOLDER, headerMap, "", urlParam);
            if(result.success()){
                return DubboResult.newSuccess();
            } else {
                return DubboResult.newFailure(DELETE_FOLDER.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(DELETE_FOLDER.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(DELETE_FOLDER.getSystemCode().getCode(), DELETE_FOLDER.getSystemCode().getMessage());
        }
    }

    /**
     * 上传代码包
     */
    public DubboResult<String> uploadPackage(DriverBase driverBase, File file){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<ODataResponseDto<BulkItemDto>> result = this.doFormRequest(getOcBaseUrl(driverBase), UPLOAD_PACKAGE, headerMap, UIPATH_FORM_FILE_KEY, file, null);
            if(result.success()){
                String body = result.getObject().getValue().get(0).getBody();
                ProcessPackageDto packageInfo = JSON.parseObject(body, ProcessPackageDto.class);
                return DubboResult.newSuccess(String.join(":", packageInfo.getId(), packageInfo.getVersion()));
            } else {
                return DubboResult.newFailure(UPLOAD_PACKAGE.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(UPLOAD_PACKAGE.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(UPLOAD_PACKAGE.getSystemCode().getCode(), UPLOAD_PACKAGE.getSystemCode().getMessage());
        }
    }

    /**
     * 删除代码包
     */
    public DubboResult deletePackageByKey(DriverBase driverBase, String key){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(key).build();
            UiPathOriginResult<String> result = this.doRequest(getOcBaseUrl(driverBase), DELETE_PACKAGE, headerMap, "", urlParam);
            if(result.success()){
                return DubboResult.newSuccess();
            } else {
                return DubboResult.newFailure(DELETE_PACKAGE.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(DELETE_PACKAGE.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(DELETE_PACKAGE.getSystemCode().getCode(), DELETE_PACKAGE.getSystemCode().getMessage());
        }
    }

    /**
     * 下载代码包
     */
    public DubboResult<FileInfoDto> downloadPackageByKey(DriverBase driverBase, String key, String fileName){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(key).build();
            UiPathOriginResult<String> result = this.doDownloadRequest(getOcBaseUrl(driverBase), DOWNLOAD_PACKAGE, headerMap, null, urlParam, uiPathPkgFilePath, fileName);
            if(result.success()){
                return DubboResult.newSuccess(FileInfoDto.builder().path(uiPathPkgFilePath + fileName).fileName(fileName).build());
            } else {
                return DubboResult.newFailure(DOWNLOAD_PACKAGE.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(DOWNLOAD_PACKAGE.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(DOWNLOAD_PACKAGE.getSystemCode().getCode(), DOWNLOAD_PACKAGE.getSystemCode().getMessage());
        }
    }

    /**
     * 发布流程
     */
    public DubboResult<ProcessReleaseDto> releaseProcess(DriverBase driverBase, ProcessReleaseDto release){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<ProcessReleaseDto> result = this.doRequest(getOcBaseUrl(driverBase), RELEASE_PROCESS, headerMap, JSON.toJSONString(release), null);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(RELEASE_PROCESS.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(RELEASE_PROCESS.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(RELEASE_PROCESS.getSystemCode().getCode(), RELEASE_PROCESS.getSystemCode().getMessage());
        }
    }

    /**
     * 再发布流程
     */
    public DubboResult releaseProcessToSpecificVersion(DriverBase driverBase, ProcessReleaseDto release){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(String.valueOf(release.getId())).build();
            UiPathOriginResult<String> result = this.doRequest(getOcBaseUrl(driverBase), RELEASE_PROCESS_TO_SPECIFIC_VERSION, headerMap, JSON.toJSONString(release), urlParam);
            if(result.success()){
                return DubboResult.newSuccess();
            } else {
                return DubboResult.newFailure(RELEASE_PROCESS_TO_SPECIFIC_VERSION.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(RELEASE_PROCESS_TO_SPECIFIC_VERSION.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(RELEASE_PROCESS_TO_SPECIFIC_VERSION.getSystemCode().getCode(), RELEASE_PROCESS_TO_SPECIFIC_VERSION.getSystemCode().getMessage());
        }
    }

    /**
     * 根据流程名获取流程版本
     */
    public DubboResult<ArrayList<ProcessResponseDto>> getProcessVersionsByName(DriverBase driverBase, String processName){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(processName).build();
            UiPathOriginResult<ODataResponseDto<ProcessResponseDto>> result = this.doRequest(getOcBaseUrl(driverBase), GET_PROCESS_VERSION, headerMap, "", urlParam);
            if(result.success()){
                List<ProcessResponseDto> processes = result.getObject().getValue();
                return DubboResult.newSuccess(((ArrayList<ProcessResponseDto>) processes));
            } else {
                return DubboResult.newFailure(GET_PROCESS_VERSION.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_PROCESS_VERSION.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_PROCESS_VERSION.getSystemCode().getCode(), GET_PROCESS_VERSION.getSystemCode().getMessage());
        }
    }


    /**
     * 删除流程
     */
    public DubboResult deleteReleaseByKey(DriverBase driverBase, String key){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(key).build();
            UiPathOriginResult<String> result = this.doRequest(getOcBaseUrl(driverBase), DELETE_RELEASE, headerMap, "", urlParam);
            if(result.success()){
                return DubboResult.newSuccess();
            } else {
                return DubboResult.newFailure(DELETE_RELEASE.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(DELETE_RELEASE.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(DELETE_RELEASE.getSystemCode().getCode(), DELETE_RELEASE.getSystemCode().getMessage());
        }
    }

    /**
     * 查询单个流程
     */
    public DubboResult<ProcessReleaseDto> queryReleaseByKey(DriverBase driverBase, String key){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(key).build();
            UiPathOriginResult<ProcessReleaseDto> result = this.doRequest(getOcBaseUrl(driverBase), GET_RELEASE, headerMap, "", urlParam);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(GET_RELEASE.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_RELEASE.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_RELEASE.getSystemCode().getCode(), GET_RELEASE.getSystemCode().getMessage());
        }
    }

    /**
     * 创建全局用户
     */
    @Deprecated
    public DubboResult<IdentityUserResponseDto> addIdentityUser(DriverBase driverBase, IdentityUserRequestDto user){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<IdentityUserResponseDto> result = this.doRequest(getOcBaseUrl(driverBase), IDENTITY_ADD_USER, headerMap, JSON.toJSONString(user), null);
            if(result.success() && result.getObject().isSucceeded()){
                return DubboResult.newSuccess(result.getObject());
            } else if(result.success() && !result.getObject().isSucceeded()){
                return DubboResult.newFailure(IDENTITY_ADD_USER.getSystemCode().getCode(), String.join(",", result.getObject().getErrors()));
            } else{
                return DubboResult.newFailure(IDENTITY_ADD_USER.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(IDENTITY_ADD_USER.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(IDENTITY_ADD_USER.getSystemCode().getCode(), IDENTITY_ADD_USER.getSystemCode().getMessage());
        }
    }

    /**
     * 创建用户
     */
    public DubboResult<UserResponseDto> addUser(DriverBase driverBase, UserRequestDto user){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<UserResponseDto> result = this.doRequest(getOcBaseUrl(driverBase), ADD_USER, headerMap, JSON.toJSONString(user), null);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(ADD_USER.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(ADD_USER.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(ADD_USER.getSystemCode().getCode(), ADD_USER.getSystemCode().getMessage());
        }
    }

    /**
     * 用户放进文件夹
     */
    public DubboResult assignUserToFolder(DriverBase driverBase, FoldersAssignUserParametersDto assign){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<String> result = this.doRequest(getOcBaseUrl(driverBase), ASSIGN_USER, headerMap, JSON.toJSONString(assign), null);
            if(result.success()){
                return DubboResult.newSuccess();
            } else {
                return DubboResult.newFailure(ASSIGN_USER.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(ASSIGN_USER.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(ASSIGN_USER.getSystemCode().getCode(), ASSIGN_USER.getSystemCode().getMessage());
        }
    }

    /**
     * 用户移出文件夹
     */
    public DubboResult removeUserFromFolder(DriverBase driverBase, RemoveUserDto user, String folderId){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(folderId).build();
            UiPathOriginResult<String> result = this.doRequest(getOcBaseUrl(driverBase), REMOVE_USER, headerMap, JSON.toJSONString(user), urlParam);
            if(result.success()){
                return DubboResult.newSuccess();
            } else {
                return DubboResult.newFailure(REMOVE_USER.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(REMOVE_USER.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(REMOVE_USER.getSystemCode().getCode(), REMOVE_USER.getSystemCode().getMessage());
        }
    }

    /**
     * 模板放进文件夹
     */
    public DubboResult assignTemplateToFolder(DriverBase driverBase, FoldersUpdateMachinesToFolderAssociationsParametersDto associations){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<String> result = this.doRequest(getOcBaseUrl(driverBase), ASSIGN_TEMPLATE, headerMap, JSON.toJSONString(associations), null);
            if(result.success()){
                return DubboResult.newSuccess();
            } else {
                return DubboResult.newFailure(ASSIGN_TEMPLATE.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(ASSIGN_TEMPLATE.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(ASSIGN_TEMPLATE.getSystemCode().getCode(), ASSIGN_TEMPLATE.getSystemCode().getMessage());
        }
    }

    /**
     * 删除用户
     */
    public DubboResult deleteUserByKey(DriverBase driverBase, String key){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(key).build();
            UiPathOriginResult<String> result = this.doRequest(getOcBaseUrl(driverBase), DELETE_USER, headerMap, "", urlParam);
            if(result.success()){
                return DubboResult.newSuccess();
            } else {
                return DubboResult.newFailure(DELETE_USER.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(DELETE_USER.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(DELETE_USER.getSystemCode().getCode(), DELETE_USER.getSystemCode().getMessage());
        }
    }

    /**
     * 根据Key查询用户
     */
    public DubboResult<UserResponseDto> queryUserByKey(DriverBase driverBase, String key){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(key).build();
            UiPathOriginResult<UserResponseDto> result = this.doRequest(getOcBaseUrl(driverBase), GET_USER, headerMap, null, urlParam);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(GET_USER.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_USER.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_USER.getSystemCode().getCode(), GET_USER.getSystemCode().getMessage());
        }
    }

    /**
     * 根据Key更新用户(更新前台许可)
     */
    public DubboResult<UserResponseDto> updateUserByKey(DriverBase driverBase, String key, UserRequestDto user){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(key).build();
            UiPathOriginResult<UserResponseDto> result = this.doRequest(getOcBaseUrl(driverBase), UPDATE_USER, headerMap, JSON.toJSONString(user), urlParam);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(UPDATE_USER.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(UPDATE_USER.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(UPDATE_USER.getSystemCode().getCode(), UPDATE_USER.getSystemCode().getMessage());
        }
    }

    /**
     * 批量查询用户
     */
    public DubboResult<ArrayList<UserResponseDto>> queryUsers(DriverBase driverBase, RobotFilter filter){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<ODataResponseDto<UserResponseDto>> result = this.doRequest(getOcBaseUrl(driverBase), GET_USERS, headerMap, null, null);
            if(result.success()){
                List<UserResponseDto> users = result.getObject().getValue();
                return DubboResult.newSuccess(((ArrayList<UserResponseDto>) users));
            } else {
                return DubboResult.newFailure(GET_USERS.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_USERS.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_USERS.getSystemCode().getCode(), GET_USERS.getSystemCode().getMessage());
        }
    }

    /**
     * 根据条件查询用户会话（机器状态、许可状态）
     */
    public DubboResult<ArrayList<SessionResponseDto>> getSessions(DriverBase driverBase, RobotFilter filter){
        try {
            UiPathUrlParam urlParam = null;
            if(StringUtils.isNotEmpty(filter.getUserName())){
                urlParam = UiPathUrlParam.builder()
                        .filter(getSessionUrlFilter(filter))
                        .expand(ExpandEntity.builder()
                                .value("Robot($expand=License,User)")
                                .build())
                        .orderBy(OrderByEntity.builder()
                                .key("Robot/User/UserName")
                                .orderBy(OrderByEnum.asc)
                                .build())
                        .build();
            }
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<ODataResponseDto<SessionResponseDto>> result = this.doRequest(getOcBaseUrl(driverBase), GET_GLOBAL_SESSIONS, headerMap, null, urlParam);
            if(result.success()){
                List<SessionResponseDto> sessions = result.getObject().getValue();
                return DubboResult.newSuccess(((ArrayList<SessionResponseDto>) sessions));
            } else {
                return DubboResult.newFailure(GET_GLOBAL_SESSIONS.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_GLOBAL_SESSIONS.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_GLOBAL_SESSIONS.getSystemCode().getCode(), GET_GLOBAL_SESSIONS.getSystemCode().getMessage());
        }
    }

    private FilterEntity getSessionUrlFilter(RobotFilter filter){
        FilterEntity filter1 = FilterEntity.builder()
                .left(FilterEntity.Entity.builder()
                        .valueString("Robot/User/UserName")
                        .group(false)
                        .build())
                .operations(FilterOperation.ComparisonOperators.Equal)
                .right(FilterEntity.Entity.builder()
                        .valueString("\'" + filter.getUserName() + "\'")
                        .group(false)
                        .build())
                .build();
        FilterEntity filter2 = FilterEntity.builder()
                .left(FilterEntity.Entity.builder()
                        .valueString("MachineId")
                        .group(false)
                        .build())
                .operations(FilterOperation.ComparisonOperators.NotEqual)
                .right(FilterEntity.Entity.builder()
                        .valueString("null")
                        .group(false)
                        .build())
                .build();
        return FilterEntity.builder()
                .left(FilterEntity.Entity.builder()
                        .valueEntity(filter1)
                        .group(false)
                        .build())
                .operations(FilterOperation.LogicalOperators.LogicalAnd)
                .right(FilterEntity.Entity.builder()
                        .valueEntity(filter2)
                        .group(false)
                        .build())
                .build();
    }

    /**
     * 根据ID查询Machine信息
     */
    public DubboResult<MachineDto> queryMachineByKey(DriverBase driverBase, String key){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(key).build();
            UiPathOriginResult<MachineDto> result = this.doRequest(getOcBaseUrl(driverBase), GET_MACHINE, headerMap, null, urlParam);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(GET_MACHINE.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_MACHINE.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_MACHINE.getSystemCode().getCode(), GET_MACHINE.getSystemCode().getMessage());
        }
    }

    /**
     * 查询运行时许可
     */
    public DubboResult<ArrayList<LicensesRuntimeResponseDto>> getLicensesRuntime(DriverBase driverBase, String robotType){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(robotType).build();
            UiPathOriginResult<ODataResponseDto<LicensesRuntimeResponseDto>> result = this.doRequest(getOcBaseUrl(driverBase), GET_LICENSES_RUNTIME, headerMap, null, urlParam);
            if(result.success()){
                List<LicensesRuntimeResponseDto> sessions = result.getObject().getValue();
                return DubboResult.newSuccess(((ArrayList<LicensesRuntimeResponseDto>) sessions));
            } else {
                return DubboResult.newFailure(GET_LICENSES_RUNTIME.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_LICENSES_RUNTIME.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_LICENSES_RUNTIME.getSystemCode().getCode(), GET_LICENSES_RUNTIME.getSystemCode().getMessage());
        }
    }

    /**
     * 后台分配许可
     */
    public DubboResult toggleEnable(DriverBase driverBase, String machineName, ToggleEnabledRequestDto toggleRequest){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(machineName).build();
            UiPathOriginResult<String> result = this.doRequest(getOcBaseUrl(driverBase), LICENSES_RUNTIME_TOGGLE, headerMap, JSON.toJSONString(toggleRequest), urlParam);
            if(result.success()){
                return DubboResult.newSuccess();
            } else {
                return DubboResult.newFailure(LICENSES_RUNTIME_TOGGLE.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(LICENSES_RUNTIME_TOGGLE.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(LICENSES_RUNTIME_TOGGLE.getSystemCode().getCode(), LICENSES_RUNTIME_TOGGLE.getSystemCode().getMessage());
        }
    }

    /**
     * 获取许可数量分布
     */
    public DubboResult<LicenseNumDto> getLicense(DriverBase driverBase){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<LicenseNumDto> result = this.doRequest(getOcBaseUrl(driverBase), GET_LICENSES, headerMap, null, null);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(GET_LICENSES.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_LICENSES.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_LICENSES.getSystemCode().getCode(), GET_LICENSES.getSystemCode().getMessage());
        }
    }

    /**
     * 启动任务
     */
    public DubboResult<JobResponseDto> startJob(DriverBase driverBase, JobStartInfoRequestDto start){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<ODataResponseDto<JobResponseDto>> result = this.doRequest(getOcBaseUrl(driverBase), START_JOB, headerMap, JSON.toJSONString(start), null);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject().getValue().get(0));
            } else {
                return DubboResult.newFailure(START_JOB.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(START_JOB.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(START_JOB.getSystemCode().getCode(), START_JOB.getSystemCode().getMessage());
        }
    }

    /**
     * 查询运行时机器会话
     */
    public DubboResult<ArrayList<MachineSessionRuntimeDto>> getRuntimeMachineSessions(DriverBase driverBase, String hostMachineName){
        try {
            UiPathUrlParam urlParam = null;
            if(StringUtils.isNotEmpty(hostMachineName)){
                urlParam = UiPathUrlParam.builder()
                        .filter(getRuntimeMachineUrlFilter(hostMachineName))
                        .build();
            }
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<ODataResponseDto<MachineSessionRuntimeDto>> result = this.doRequest(getOcBaseUrl(driverBase), GET_MACHINE_SESSION_RUNTIME, headerMap, null, urlParam);
            if(result.success()){
                return DubboResult.newSuccess((ArrayList<MachineSessionRuntimeDto>)result.getObject().getValue());
            } else {
                return DubboResult.newFailure(GET_MACHINE_SESSION_RUNTIME.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_MACHINE_SESSION_RUNTIME.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_MACHINE_SESSION_RUNTIME.getSystemCode().getCode(), GET_MACHINE_SESSION_RUNTIME.getSystemCode().getMessage());
        }
    }

    private FilterEntity getRuntimeMachineUrlFilter(String hostMachineName){
        return FilterEntity.builder()
                .left(FilterEntity.Entity.builder()
                        .valueString("HostMachineName")
                        .group(false)
                        .build())
                .operations(FilterOperation.ComparisonOperators.Equal)
                .right(FilterEntity.Entity.builder()
                        .valueString("\'" + hostMachineName + "\'")
                        .group(false)
                        .build())
                .build();
    }

    /**
     * 重启任务
     */
    public DubboResult<JobResponseDto> restartJob(DriverBase driverBase, RestartJobRequestDto restart){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<JobResponseDto> result = this.doRequest(getOcBaseUrl(driverBase), RESTART_JOB, headerMap, JSON.toJSONString(restart), null);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(RESTART_JOB.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(RESTART_JOB.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(RESTART_JOB.getSystemCode().getCode(), RESTART_JOB.getSystemCode().getMessage());
        }
    }

    /**
     * 恢复任务
     */
    public DubboResult<JobResponseDto> resumeJob(DriverBase driverBase, ResumeJobRequestDto resume){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<JobResponseDto> result = this.doRequest(getOcBaseUrl(driverBase), RESUME_JOB, headerMap, JSON.toJSONString(resume), null);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(RESUME_JOB.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(RESUME_JOB.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(RESUME_JOB.getSystemCode().getCode(), RESUME_JOB.getSystemCode().getMessage());
        }
    }

    /**
     * 暂停/终止单个任务
     */
    public DubboResult stopJobByKey(DriverBase driverBase, String jobKey, StopJobRequestDto stopJobReq){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder().id(jobKey).build();
            UiPathOriginResult<String> result = this.doRequest(getOcBaseUrl(driverBase), STOP_JOB, headerMap, JSON.toJSONString(stopJobReq), urlParam);
            if(result.success()){
                return DubboResult.newSuccess();
            } else {
                return DubboResult.newFailure(STOP_JOB.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(STOP_JOB.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(STOP_JOB.getSystemCode().getCode(), STOP_JOB.getSystemCode().getMessage());
        }
    }

    /**
     * 批量暂停/终止任务
     */
    public DubboResult stopJobs(DriverBase driverBase, StopJobRequestDto stopJobsReq){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<String> result = this.doRequest(getOcBaseUrl(driverBase), STOP_JOBS, headerMap, JSON.toJSONString(stopJobsReq), null);
            if(result.success()){
                return DubboResult.newSuccess();
            } else {
                return DubboResult.newFailure(STOP_JOBS.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(STOP_JOBS.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(STOP_JOBS.getSystemCode().getCode(), STOP_JOBS.getSystemCode().getMessage());
        }
    }

    /**
     * 查询单个任务
     */
    public DubboResult<JobResponseDto> queryJobByKey(DriverBase driverBase, String key){
        try {
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathUrlParam urlParam = UiPathUrlParam.builder()
                    .id(key)
                    .expand(ExpandEntity.builder()
                            .value("Robot")
                            .build())
                    .build();
            UiPathOriginResult<JobResponseDto> result = this.doRequest(getOcBaseUrl(driverBase), GET_JOB, headerMap, null, urlParam);
            if(result.success()){
                return DubboResult.newSuccess(result.getObject());
            } else {
                return DubboResult.newFailure(GET_JOB.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_JOB.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_JOB.getSystemCode().getCode(), GET_JOB.getSystemCode().getMessage());
        }
    }

    /**
     * 批量查询任务
     */
    public DubboResult<ArrayList<JobResponseDto>> queryJobs(DriverBase driverBase, JobFilter filter){
        try {
            UiPathUrlParam urlParam = null;
            if(StringUtils.isNotEmpty(filter.getState())){
                urlParam = UiPathUrlParam.builder()
                        .filter(getJobUrlFilter(filter))
                        .expand(ExpandEntity.builder()
                                .value("Robot")
                                .build())
                        .orderBy(OrderByEntity.builder()
                                .key("Id")
                                .orderBy(OrderByEnum.asc)
                                .build())
                        .build();
            }
            Map<String, Object> headerMap = this.getHeaderMap(driverBase, true);
            UiPathOriginResult<ODataResponseDto<JobResponseDto>> result = this.doRequest(getOcBaseUrl(driverBase), GET_JOBS, headerMap, null, urlParam);
            if(result.success()){
                return DubboResult.newSuccess((ArrayList<JobResponseDto>)result.getObject().getValue());
            } else {
                return DubboResult.newFailure(GET_JOBS.getSystemCode().getCode(), result.getMessage());
            }
        } catch (Exception e){
            log.error(GET_JOBS.getSystemCode().getMessage(), e);
            return DubboResult.newFailure(GET_JOBS.getSystemCode().getCode(), GET_JOBS.getSystemCode().getMessage());
        }
    }

    private FilterEntity getJobUrlFilter(JobFilter filter){
        return FilterEntity.builder()
                .left(FilterEntity.Entity.builder()
                        .valueString("State")
                        .group(false)
                        .build())
                .operations(FilterOperation.ComparisonOperators.Equal)
                .right(FilterEntity.Entity.builder()
                        .valueString("\'" + JobResponseDto.createFromJobState(filter.getState()) + "\'")
                        .group(false)
                        .build())
                .build();
    }

    //非form-data请求
    private UiPathOriginResult doRequest(String baseUrl, UIPathApiEnum api, Map<String, Object> headers, String requestBody, UiPathUrlParam pathUrlParam){
        String url = api.getUrl(baseUrl, pathUrlParam);
        TaieHttpResponse response = okHttpService.doRequest(api.getHttpMethod(), url, headers, requestBody);
        return getResponseInGeneric(api, response);
    }

    //同步下载请求
    private UiPathOriginResult doDownloadRequest(String baseUrl, UIPathApiEnum api, Map<String, Object> headers, String requestBody, UiPathUrlParam pathUrlParam, String destFileDir, String destFileName){
        String url = api.getUrl(baseUrl, pathUrlParam);
        TaieHttpResponse response = okHttpService.syncDownload(url, headers, destFileDir, destFileName);
        return getResponseInGeneric(api, response);
    }

    //form-data请求
    private UiPathOriginResult doFormRequest(String baseUrl, UIPathApiEnum api, Map<String, Object> headers, String fileKey, File file, UiPathUrlParam pathUrlParam){
        String url = api.getUrl(baseUrl, pathUrlParam);
        TaieHttpResponse response = okHttpService.doFormRequest(api.getHttpMethod(), url, headers, file, fileKey);
        return getResponseInGeneric(api, response);
    }

    private UiPathOriginResult getResponseInGeneric(UIPathApiEnum api, TaieHttpResponse response) {
        UiPathOriginResult rst = UiPathOriginResult.builder()
                .success(response.success())
                .retCode(response.getHttpRetCode())
                .build();
        try {
            if(response.success()){
                if(Objects.nonNull(api.getResponseClass())){
                    if(api.getResponseClass().equals(String.class)){
                        rst.setObject(response.getResult());
                    } else {
                        rst.setObject(JSON.parseObject(response.getResult(), api.getResponseClass()));
                    }
                } else if (Objects.nonNull(api.getResponseTypeReference())) {
                    rst.setObject(JSON.parseObject(response.getResult(), api.getResponseTypeReference()));
                }
            } else if(StringUtils.isNotEmpty(response.getResult())){
                FailResponse err = JSON.parseObject(response.getResult(), FailResponse.class);
                rst.setMessage(err.getMessage());
            }
        } catch (Exception e){
            rst.setSuccess(false);
            rst.setMessage(UIPATH_RESPONSE_DATA_ERROR.toString(api.name(), response.getResult()));
        }
        return rst;
    }

    private Map<String, Object> getHeaderMap(DriverBase driverBase, boolean needToken) throws DriverBusinessException {
        Map<String, Object> headers = new HashMap<>();
        if(StringUtils.isNotEmpty(driverBase.getGroupKey())){
            headers.put(UIPATH_ORG_UNIT_KEY, driverBase.getGroupKey());
        }
        if(needToken){
            String token = this.getTenantToken(driverBase);
            if(token.startsWith(AUTH_PREFIX)){
                headers.put(AUTH_KEY, token);
            }else {
                headers.put(AUTH_KEY, AUTH_PREFIX + token);
            }
        }
        return headers;
    }

    private String getTenantToken(DriverBase driverBase) throws DriverBusinessException {
        RMap<String, String> tenantTokenMap = this.redissonClient.getMap(UiPathTenantTokenCache);
        String tenantToken;
        if (!tenantTokenMap.containsKey(driverBase.getTenantKey())) {
            tenantToken = this.authenticate(driverBase);
            tenantTokenMap.put(driverBase.getTenantKey(), tenantToken);
            tenantTokenMap.expire(UiPathTenantTokenCacheExpiration, TimeUnit.MINUTES);
        } else{
            tenantToken = tenantTokenMap.get(driverBase.getTenantKey());
        }
        return tenantToken;
    }

    private String getOcBaseUrl(DriverBase driverBase) throws DriverBusinessException {
        RMap<String, String> baseUrlMap = this.redissonClient.getMap(UiPathOcBaseUrlCache);
        String baseUrl;
        if (!baseUrlMap.containsKey(driverBase.getTenantKey())) {
            OcTenantDetailDto ocTenantInfo = getOcTenantInfo(driverBase);
            baseUrl = ocTenantInfo.getOcIp();
            baseUrlMap.put(driverBase.getTenantKey(), baseUrl);
            baseUrlMap.expire(UiPathOcBaseUrlCacheExpiration, TimeUnit.DAYS);
        } else{
            baseUrl = baseUrlMap.get(driverBase.getTenantKey());
        }
        return baseUrl;
    }

}
