package com.friday.tooldriver.service.strategy;

import com.alibaba.fastjson.JSON;
import com.friday.base.common.response.DubboResult;
import com.friday.operation.api.distributor.dto.StandardRpaInput;
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.constant.SupplierEnum;
import com.friday.operation.api.tooldriver.dto.common.DriverBase;
import com.friday.operation.api.tooldriver.dto.rpa.*;
import com.friday.operation.api.tooldriver.service.ICapabilityDriver;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.friday.operation.api.tooldriver.constant.DriverConstant.EMPTY_STRING;
import static com.friday.tooldriver.constants.DriverSystemCode.INVALID_KEY_ERROR;

/**
 * @Author YaoYao
 * @Date Created In 18:29 2022/12/1
 * @Description Rpa能力实现类
 * @Modified By
 */
@Service
@Slf4j
public class CapabilityDriverImpl implements ICapabilityDriver {
    private final Map<String, ICapabilityDriverService> strategyMap = new ConcurrentHashMap<>();

    @Autowired
    public CapabilityDriverImpl(Map<String, ICapabilityDriverService> strategyMap) {
        strategyMap.forEach(this.strategyMap::put);
    }

    @Autowired
    private ITenantManage tenantManage;

    public String getDriverName(String tenantKey) {
        OcTenantFilterDto filter = OcTenantFilterDto.ocTenantFilterBuilder()
                .ocTenantId(Long.parseLong(tenantKey))
                .build();
        DubboResult<ArrayList<OcTenantDetailDto>> result = tenantManage.queryTenantDetail(filter);
        if(!result.success() || CollectionUtils.isEmpty(result.getObject())){
            log.error("根据中控租户键值{}查询失败或结果为空,失败原因:{}", tenantKey, result.getMessage());
            return EMPTY_STRING;
        }
        OcTenantDetailDto ocTenant = result.getObject().get(0);
        return SupplierEnum.RPASupplierEnum.getDriverServiceName(ocTenant.getSupplierEn());
    }

    @Override
    public DubboResult<TenantDto> createTenant(DriverBase driverBase, TenantDto tenant) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).createTenant(driverBase, tenant);
    }

    @Override
    public DubboResult<ArrayList<TenantDto>> queryTenants(DriverBase driverBase, TenantSelectFilter filter) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryTenants(driverBase, filter);
    }

    @Override
    public DubboResult<TenantDto> queryTenantByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryTenantByKey(driverBase, key);
    }

    @Override
    public DubboResult deleteTenantByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).deleteTenantByKey(driverBase, key);
    }

    @Override
    public DubboResult updateTenantByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).updateTenantByKey(driverBase, key);
    }

    @Override
    public DubboResult activateTenantByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).activateTenantByKey(driverBase, key);
    }

    @Override
    public DubboResult<GroupDto> createGroup(DriverBase driverBase, GroupDto group) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).createGroup(driverBase, group);
    }

    @Override
    public DubboResult<ArrayList<GroupDto>> queryGroups(DriverBase driverBase, GroupFilter filter) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryGroups(driverBase, filter);
    }

    @Override
    public DubboResult<GroupDto> queryGroupByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryGroupByKey(driverBase, key);
    }

    @Override
    public DubboResult deleteGroupByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).deleteGroupByKey(driverBase, key);
    }

    @Override
    public DubboResult<CodePackageDto> uploadPackage(DriverBase driverBase, CodePackageDto pkg) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).uploadPackage(driverBase, pkg);
    }

    @Override
    public DubboResult deletePackageByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).deletePackageByKey(driverBase, key);
    }

    @Override
    public DubboResult<ArrayList<CodePackageDto>> queryPackages(DriverBase driverBase, CodePackageFilter filter) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryPackages(driverBase, filter);
    }

    @Override
    public DubboResult<CodePackageDto> queryPackageByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryPackageByKey(driverBase, key);
    }

    @Override
    public DubboResult<FileInfoDto> downloadPackageByKey(DriverBase driverBase, String key, String fileName) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).downloadPackageByKey(driverBase, key, fileName);
    }

    @Override
    public DubboResult<ReleaseDto> releaseProcess(DriverBase driverBase, ReleaseDto release) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).releaseProcess(driverBase, release);
    }

    @Override
    public DubboResult deleteProcessReleaseByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).deleteProcessReleaseByKey(driverBase, key);
    }

    @Override
    public DubboResult<ArrayList<ReleaseDto>> queryProcessReleases(DriverBase driverBase, ReleaseFilter filter) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryProcessReleases(driverBase, filter);
    }

    @Override
    public DubboResult<ReleaseDto> queryProcessReleaseByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryProcessReleaseByKey(driverBase, key);
    }

    @Override
    public DubboResult<RobotDto> createRobot(DriverBase driverBase, RobotDto robot) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).createRobot(driverBase, robot);
    }

    @Override
    public DubboResult deleteRobotByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).deleteRobotByKey(driverBase, key);
    }

    @Override
    public DubboResult<ArrayList<RobotDto>> queryRobots(DriverBase driverBase, RobotFilter filter) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryRobots(driverBase, filter);
    }

    @Override
    public DubboResult<RobotDto> queryRobotByKey(DriverBase driverBase, String key) {
        if(StringUtils.isEmpty(key)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryRobotByKey(driverBase, key);
    }

    @Override
    public DubboResult assignRobotToGroup(DriverBase driverBase, String robotKey, String groupKey) {
        if(StringUtils.isAnyEmpty(robotKey, groupKey)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).assignRobotToGroup(driverBase, robotKey, groupKey);
    }

    @Override
    public DubboResult removeRobotFromGroup(DriverBase driverBase, String robotKey, String groupKey) {
        if(StringUtils.isAnyEmpty(robotKey, groupKey)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).removeRobotFromGroup(driverBase, robotKey, groupKey);
    }

    @Override
    public DubboResult enableLicense(DriverBase driverBase, LicenseDto license) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).enableLicense(driverBase, license);
    }

    @Override
    public DubboResult disableLicense(DriverBase driverBase, LicenseDto license) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).disableLicense(driverBase, license);
    }

    @Override
    public DubboResult<Integer> availableLicenseNum(DriverBase driverBase, String licenseType) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).availableLicenseNum(driverBase, licenseType);
    }

    @Override
    public DubboResult<JobDto> startJob(DriverBase driverBase, StartJobDto start) {
        if(StringUtils.isNotEmpty(start.getInputArguments())) {
            try {
                JSON.parseObject(start.getInputArguments(), StandardRpaInput.class);
            } catch (Exception e){
                return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "不支持的启动入参格式");
            }
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).startJob(driverBase, start);
    }

    @Override
    public DubboResult<JobDto> restartJob(DriverBase driverBase, String jobId) {
        if(StringUtils.isEmpty(jobId)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).restartJob(driverBase, jobId);
    }

    @Override
    public DubboResult pauseJob(DriverBase driverBase, String jobId) {
        if(StringUtils.isEmpty(jobId)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).pauseJob(driverBase, jobId);
    }

    @Override
    public DubboResult resumeJob(DriverBase driverBase, String jobId) {
        if(StringUtils.isEmpty(jobId)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).resumeJob(driverBase, jobId);
    }

    @Override
    public DubboResult stopJob(DriverBase driverBase, String jobId) {
        if(StringUtils.isEmpty(jobId)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).stopJob(driverBase, jobId);
    }

    @Override
    public DubboResult stopJobs(DriverBase driverBase, List<String> jobIdList) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).stopJobs(driverBase, jobIdList);
    }

    @Override
    public DubboResult<ArrayList<JobDto>> queryJobs(DriverBase driverBase, JobFilter filter) {
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryJobs(driverBase, filter);
    }

    @Override
    public DubboResult<JobDto> queryJobByKey(DriverBase driverBase, String jobId) {
        if(StringUtils.isEmpty(jobId)){
            return DubboResult.newFailure(INVALID_KEY_ERROR.getCode(), INVALID_KEY_ERROR.getMessage());
        }
        return strategyMap.get(getDriverName(driverBase.getTenantKey())).queryJobByKey(driverBase, jobId);
    }
}
