package com.friday.tooldriver.service.executor;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.friday.base.common.response.DubboResult;
import com.friday.operation.api.executor.dto.executor.ExecutorDto;
import com.friday.operation.api.executor.dto.executor.ExecutorFilter;
import com.friday.operation.api.executor.dto.executor.RelatedTaskRelease;
import com.friday.operation.api.executor.dto.executor.TaskRelease;
import com.friday.operation.api.executor.dto.module.ModuleRegisterDto;
import com.friday.operation.api.executor.service.IDynamicModuleService;
import com.friday.operation.api.tooldriver.dto.rpa.ProgramProcessReleaseDto;
import com.friday.tooldriver.exception.DriverBusinessException;
import com.friday.tooldriver.mapper.executor.ExecutorMapper;
import com.friday.tooldriver.mapper.taieoc.ProgramProcessReleaseMapper;
import com.friday.tooldriver.po.executor.ExecutorPo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

import static com.friday.operation.api.executor.constant.ExecutorState.OFFLINE;

/**
 * @Author YaoYao
 * @Date Created In 11:27 2023/3/21
 * @Description 执行器管理
 * @Modified By
 */
@Slf4j
@Service
public class ExecutorManager {
    @Autowired(required = false)
    private IDynamicModuleService dynamicModuleService;
    @Autowired
    private ExecutorMapper executorMapper;
    @Autowired
    private ProgramProcessReleaseMapper releaseMapper;

    public ExecutorDto registerExecutor(ExecutorDto executor) {
        //创建执行器时调用
        ExecutorPo executorPo = ExecutorPo.builder()
                .ocTenantKey(Integer.parseInt(executor.getTenantKey()))
                .ip(executor.getIp())
                .user(executor.getUser())
                .state(OFFLINE.getState())
                .build();
        executorMapper.insertExecutor(executorPo);
        return executorPo.transferToExecutorDto();
    }

    public void deleteExecutor(Integer key){
        executorMapper.deleteExecutorById(key);
    }

    public void syncExecutorState() {
        List<ExecutorPo> executors = executorMapper.selectAllExecutors();
    }

    public void releaseRelatedTask(RelatedTaskRelease release) throws DriverBusinessException {
        if(StringUtils.isAnyEmpty(release.getGroupKey(), release.getModule(), release.getVersion())){
            throw new DriverBusinessException("缺少必填入参");
        }
        //查询流程是否发布
        ProgramProcessReleaseDto releasedProcess = releaseMapper.selectReleaseDto(Integer.parseInt(release.getGroupKey()), release.getModule(), release.getVersion());
        if(Objects.isNull(releasedProcess)){
            throw new DriverBusinessException("未找到已发布的程序任务");
        }
        //查询关联服务发布机器配置表 发布关联服务到配置好的执行器群
        ModuleRegisterDto register = ModuleRegisterDto.builder()
                .fileKey(releasedProcess.getProcessFileKey())
                .module(release.getModule())
                .version(release.getVersion())
                .build();
        //根据executorIP调用注册模块方法
        List<ExecutorPo> executors = executorMapper.selectAllRelatedServiceExecutors();
        for(int i = 0; i < executors.size(); i++){
            DubboResult result = dynamicModuleService.registerModule(register);
            if(!result.success()){
                this.rollbackRelatedTaskRelease(executors.subList(0, i), release);
                throw new DriverBusinessException(result.getMessage());
            }
        }
    }

    private void rollbackRelatedTaskRelease(List<ExecutorPo> releasedExecutors, RelatedTaskRelease release){
        for(ExecutorPo executor : releasedExecutors){
            //根据executorIP调用注销模块方法
            dynamicModuleService.removeModule(release.getModule(), release.getVersion());
        }
    }

    public void removeRelateTaskRelease(String moduleName, String version) throws DriverBusinessException {
        List<ExecutorPo> executors = executorMapper.selectAllRelatedServiceExecutors();
        for(ExecutorPo executor : executors){
            //根据executorIP调用注销模块方法
            DubboResult result = dynamicModuleService.removeModule(moduleName, version);
            if(!result.success()){
                throw new DriverBusinessException("注销模块失败" + result.getMessage());
            }
        }
    }

    public DubboResult releaseTask(TaskRelease release) {
        //查询流程是否发布
        ProgramProcessReleaseDto releasedProcess = releaseMapper.selectReleaseDto(Integer.parseInt(release.getGroupKey()), release.getModule(), release.getVersion());
        if(Objects.isNull(releasedProcess)){
            return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "未找到已发布的程序任务");
        }
        //发布程序任务到指定执行器 非程序执行器不动作
        List<ExecutorPo> executors = executorMapper.selectAllRelatedServiceExecutors();
        List<ExecutorPo> filtered = executors.stream().filter(e -> e.getIp().equals(release.getExecutorIP()) && e.getUser().equals(release.getExecutorUser())).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(filtered)){
            return DubboResult.newSuccess();
        }
        return dynamicModuleService.registerModule(ModuleRegisterDto.builder()
                .fileKey(releasedProcess.getProcessFileKey())
                .module(release.getModule())
                .version(release.getVersion())
                .build());
    }

    public void removeTaskRelease(TaskRelease release) throws DriverBusinessException {
        //根据executorIP调用注销模块方法
        DubboResult result = dynamicModuleService.removeModule(release.getModule(), release.getVersion());
        if(!result.success()){
            throw new DriverBusinessException("注销模块失败" + result.getMessage());
        }
    }

    public List<ExecutorDto> queryExecutors(ExecutorFilter filter) {
        List<ExecutorPo> executors = executorMapper.selectExecutors(filter);
        return executors.stream().map(ExecutorPo::transferToExecutorDto).collect(Collectors.toList());
    }
}
