package org.matrix.actuators.usecase;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.lang3.StringUtils;
import org.matrix.actuators.Actuator;
import org.matrix.actuators.checkpoint.CheckPointActuator;
import org.matrix.actuators.datasource.IDataSourceService;
import org.matrix.actuators.httpclient.HttpClientActuator;
import org.matrix.actuators.move.MoveActuator;
import org.matrix.actuators.move.MoveStrategy;
import org.matrix.actuators.util.ThreadUtil;
import org.matrix.config.HttpRequestConfig;
import org.matrix.database.entity.*;
import org.matrix.actuators.checkpoint.CheckPoint;
import org.matrix.actuators.checkpoint.CheckPointResult;
import org.matrix.actuators.httpclient.HttpRequestDetail;
import org.matrix.actuators.httpclient.HttpResponseDetail;
import org.matrix.database.service.IExecutionHistoryService;
import org.matrix.enums.ExecutionHistoryStatus;
import org.matrix.exception.JobOrCaseRunningException;
import org.matrix.exception.GlobalException;
import org.matrix.socket.ExecutionStatusMonitorSocketHandler;
import org.matrix.socket.pool.TestCaseExecuteSocketPool;
import org.matrix.socket.queue.LogQueueRuntime;
import org.matrix.socket.vo.CaseExecuteVo;
import org.matrix.socket.vo.SocketResponseMessage;
import org.matrix.socket.vo.TestExecuteLog;
import org.matrix.util.JsonUtil;
import org.matrix.util.SpringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;

import static org.matrix.enums.ModuleType.CASE_ACTUATOR;
import static org.matrix.enums.ModuleType.HTTP_ACTUATOR;

/**
 * 测试用例执行器
 *
 * @author huangxiahao
 */
@Component
public class CaseActuator implements Actuator {

    final
    HttpRequestConfig httpRequestConfig;

    final
    IDataSourceService dataSourceService;

    private final CheckPointActuator checkPointActuator;

    private final HttpClientActuator httpClientActuator;

    private final IExecutionHistoryService executionHistoryService;

    private final ExecutionStatusMonitorSocketHandler executionStatusMonitorSocketHandler;

    public CaseActuator(CheckPointActuator checkPointActuator, HttpClientActuator httpClientActuator, IExecutionHistoryService executionHistoryService, ExecutionStatusMonitorSocketHandler executionStatusMonitorSocketHandler, IDataSourceService dataSourceService, HttpRequestConfig httpRequestConfig) {
        this.checkPointActuator = checkPointActuator;
        this.httpClientActuator = httpClientActuator;
        this.executionHistoryService = executionHistoryService;
        this.executionStatusMonitorSocketHandler = executionStatusMonitorSocketHandler;
        this.dataSourceService = dataSourceService;
        this.httpRequestConfig = httpRequestConfig;
    }


    /**
     * @param projectId 项目ID
     * @param envId     环境ID
     *                  执行测试用例，这个方法对内使用，由其他执行器调用
     */
    public TestDataExecuteResult executeTestCase(TestCaseBTO testCaseBto, Long envId, Long projectId) {
        LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, "开始执行用例！！");
        LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, String.format("当前正在执行用例ID: %s 用例名： %s", testCaseBto.getTestCase().getId(), testCaseBto.getTestCase().getName()));
        //执行前置动作
        LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, "[用例执行器] 开始执行前置动作！！");
        executeMove(testCaseBto.getTestCase().getMoveBefore()
                , envId, projectId, null, MoveStrategy.PRE_MOVE);
        LocalDateTime dataStartTime = LocalDateTime.now();
        //执行测试用例的本体内容
        HttpResponseDetail baseTestCaseResponseDetail = executionCaseDetail(
                envId,
                projectId,
                testCaseBto.getTestCase(),
                testCaseBto.getTestData());
        //执行中置动作
        executeMove(testCaseBto.getTestCase().getMoveAfterTest()
                , envId, projectId, baseTestCaseResponseDetail.getResponseBody(), MoveStrategy.MID_MOVE);
        //进行检验
        CheckPointResult checkPointResult = getCheckPointResult(testCaseBto.getTestCase(),
                testCaseBto.getTestData(),
                envId,
                projectId,
                baseTestCaseResponseDetail);
        //执行后置动作
        executeMove(testCaseBto.getTestCase().getMoveAfterCase()
                , envId, projectId, baseTestCaseResponseDetail.getResponseBody(), MoveStrategy.AFT_MOVE);
        TestDataExecuteResult testDataExecuteResult = new TestDataExecuteResult(
                dataStartTime,
                LocalDateTime.now(),
                true,
                testCaseBto.getTestCase().getId(),
                testCaseBto.getTestData().getId(),
                baseTestCaseResponseDetail,
                checkPointResult);
        LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, "[用例执行器] 本次用例执行结果" + JsonUtil.toJsonPretty(testDataExecuteResult));
        return testDataExecuteResult;
    }


    /**
     * 执行一条测试用例的多条测试数据
     */
    public List<TestDataExecuteResult> executeTestCases(TestCaseListDataBto testCaseBto, Long envId, Long projectId) {
        LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, "[用例执行器] 开始执行用例！！");
        List<TestDataExecuteResult> resultList = new ArrayList<>();
        LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, String.format("[用例执行器] 当前正在执行用例ID: %s 用例名： %s", testCaseBto.getTestCase().getId(), testCaseBto.getTestCase().getName()));
        //执行前置动作
        LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, "[用例执行器] 开始执行前置动作！！");
        executeMove(testCaseBto.getTestCase().getMoveBefore()
                , envId, projectId, null, MoveStrategy.PRE_MOVE);
        //执行测试用例的本体内容
        for (TestData testData : testCaseBto.getTestDataList()) {
            LocalDateTime dataStartTime = LocalDateTime.now();
            //向线程中设置当前正在执行的DataId
            LogQueueRuntime.setTestData(testData.getId());
            //try catch 一下避免发生错误后导致循环进行不下去
            try {
                changeExecutionHistoryStatus(ExecutionHistoryStatus.RUN);
                LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, "[用例执行器] 开始执行数据组ID：" + testData.getId());
                HttpResponseDetail baseTestCaseResponseDetail = executionCaseDetail(
                        envId,
                        projectId,
                        testCaseBto.getTestCase(),
                        testData);
                LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, "[用例执行器] 即将开始执行中置动作");
                //执行中置动作
                executeMove(testCaseBto.getTestCase().getMoveAfterTest()
                        , envId, projectId, baseTestCaseResponseDetail.getResponseBody(), MoveStrategy.MID_MOVE);
                CheckPointResult checkPointResult = getCheckPointResult(testCaseBto.getTestCase(),
                        testData,
                        envId,
                        projectId,
                        baseTestCaseResponseDetail);
                TestDataExecuteResult testDataExecuteResult = new TestDataExecuteResult(
                        dataStartTime,
                        LocalDateTime.now(),
                        checkPointResult.getFailNum() == null || checkPointResult.getFailNum() <= 0,
                        testCaseBto.getTestCase().getId(),
                        testData.getId(),
                        baseTestCaseResponseDetail,
                        checkPointResult
                );
                resultList.add(testDataExecuteResult);
                LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, "[用例执行器] 用例执行详情：" + JsonUtil.toJsonPretty(testDataExecuteResult));
                LogQueueRuntime.addNewLog(getClass(),CASE_ACTUATOR,"[用例执行器] 检查点结果: " + JsonUtil.toJsonPretty(testDataExecuteResult.getCheckPointResult()));
                //执行后置动作
                executeMove(testCaseBto.getTestCase().getMoveAfterCase()
                        , envId, projectId, baseTestCaseResponseDetail.getResponseBody(), MoveStrategy.AFT_MOVE);
                if (checkPointResult.getFailNum()>0){
                    changeExecutionHistoryStatus(ExecutionHistoryStatus.ERROR);
                }else {
                    changeExecutionHistoryStatus(ExecutionHistoryStatus.FINISH);
                }
            } catch (Exception e) {
                dataSourceService.switchMainDataSource();
                e.printStackTrace();
                TestDataExecuteResult testDataExecuteResult = new TestDataExecuteResult(
                        dataStartTime,
                        LocalDateTime.now(),
                        false,
                        testCaseBto.getTestCase().getId(),
                        testData.getId(),
                        null,
                        null
                );
                resultList.add(testDataExecuteResult);
                changeExecutionHistoryStatus(ExecutionHistoryStatus.ERROR);
                LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, String.format("[用例执行器] 执行数据组ID：%s 数据组名称：%s 产生错误：%s", testData.getId(), testData.getName(), e.getMessage()));
            } finally {
                //将线程中正在执行的DataId清除
                LogQueueRuntime.clearTestData();
            }
        }
        return resultList;
    }

    /**
     * 调用动作
     *
     * @param moveString     用例中的moveId组 例如 1,2,3,4
     * @param envId          环境id
     * @param projectId      项目id
     * @param caseResultData 测试用例执行后保留下的结果集,该参数在前置策略中可以为null,在中间/后置策略中必须要提供合理的结果集对象
     * @param strategy       动作的策略，即是前置/中间/后置,具体查看{@link MoveStrategy}
     */
    private void executeMove(String moveString, Long envId, Long projectId, String caseResultData, MoveStrategy strategy) {
        String[] moveIds = StringUtils.isEmpty(moveString) ? new String[]{} : moveString.split(",");
        for (String moveId : moveIds) {
            if (!StringUtils.isEmpty(moveId)) {
                getMoveActuator().runMove(
                        Long.valueOf(moveId),
                        envId,
                        projectId,
                        caseResultData,
                        strategy
                );
            }

        }
    }

    /**
     * 清空动作的变量吃
     */
    private void clearMoveData() {
        getMoveActuator().clearMoveRes();
    }

    private CheckPointResult getCheckPointResult(TestCase testCase
            , TestData testData
            , Long envId
            , Long projectId
            , HttpResponseDetail baseTestCaseResponseDetail) {
        if (testCase.getType().equals(TestCaseTypeEnum.HTTP.getValue())) {
            return
                    checkPointActuator.httpCheck(
                            baseTestCaseResponseDetail,
                            getCheckPointEntity(testData),
                            envId,
                            projectId
                    );
        }
        return new CheckPointResult();
    }

    /**
     * 根据Case的Detail进行Case的核心部分执行
     *
     * @param envId 环境ID
     * @param projectId 项目ID
     * @param testCase 测试用例
     * @param testData 测试数据
     * @return 执行后的返回值
     */
    private HttpResponseDetail executionCaseDetail(
            Long envId, Long projectId, TestCase testCase, TestData testData) {
        if (testCase.getType().equals(TestCaseTypeEnum.HTTP.getValue())) {

            HttpRequestDetail httpRequestDetail = JSON.parseObject(testData.getDetail(), HttpRequestDetail.class);
            if (httpRequestDetail == null || httpRequestDetail.getMethod() == null || httpRequestDetail.getRequestType() == null) {
                throw new GlobalException("HTTP请求发送失败，测试数据组中不存在请求数据");
            }
            LogQueueRuntime.addNewLog(this.getClass(), HTTP_ACTUATOR, "[HTTP执行器] 开始准备发送HTTP请求");
            HttpResponseDetail httpResponseDetail = httpClientActuator.sendHttpRequest(httpRequestDetail, envId, projectId);
            String responseBody = httpResponseDetail.getResponseBody();
            if (StringUtils.isEmpty(responseBody)){
                LogQueueRuntime.addNewLog(this.getClass(), HTTP_ACTUATOR, "[HTTP执行器] 本次请求结果为空");
            }else {
                LogQueueRuntime.addNewLog(this.getClass(), HTTP_ACTUATOR, String.format("[HTTP执行器] 本次请求结果：%s",JsonUtil.toJsonPretty(JSONObject.parse(responseBody))));
            }
            return httpResponseDetail;

        } else {
            throw new GlobalException("不支持当前测试用例的类型");
        }
    }

    private CheckPoint getCheckPointEntity(TestData testData) {
        CheckPoint checkPoint = new CheckPoint();
        checkPoint.setUseExceptionCheck(testData.getAbnormalCheckpoint() != 0);
        checkPoint.setUseNullCheck(testData.getNoEmptyCheckpoint() != 0);
        checkPoint.setContainCheckPoint(testData.getContainCheckpoint());
        checkPoint.setNoContainCheckPoint(testData.getNoContainCheckpoint());
        checkPoint.setJsonPathCheckPoint(testData.getJsonpathCheckpoint());
        return checkPoint;
    }

    private static MoveActuator getMoveActuator() {
        return SpringUtils.getBean("moveActuator");
    }

    /**
     * @param caseExecuteVo 执行所需要的详细信息
     * @param session       如果是从socket运行并希望获取实时日志请从这里运行
     *                      外界如果执行测试用例的话请走这个接口,执行TestCase，并控制运行态日志池，进行日志的生成。
     */
    public RunCaseResult runTestCase(WebSocketSession session, CaseExecuteVo caseExecuteVo) {
        String uniqueKey = UUID.randomUUID().toString();
        caseExecuteVo.setUniqueKey(uniqueKey);
        RunCaseResult runCaseResult = new RunCaseResult();
        runCaseResult.setStartTime(LocalDateTime.now());
        runCaseResult.setJobId(caseExecuteVo.getJobId());
        runCaseResult.setUniqueKey(uniqueKey);
        Long currentThreadId = ThreadUtil.currentThreadId();
        try {
            if (session != null && session.isOpen()) {
                session.sendMessage(new TextMessage(SocketResponseMessage.success(JSONObject.toJSONString(caseExecuteVo))));
            }
            //将websocketSession 加入到socket池子中
            TestCaseExecuteSocketPool.add(currentThreadId, session);
            List<TestCaseListDataBto> testCaseListDataBtoList = caseExecuteVo.getTestCaseListDataBtoList();
            for (TestCaseListDataBto caseListDataBto : testCaseListDataBtoList) {
                Long caseProjectId = caseListDataBto.getTestCase().getProjectId();
                if (!caseExecuteVo.getProjectId().equals(caseProjectId)) {
                    throw new GlobalException("本次执行中，存在非相同项目的测试用例");
                }
            }

            boolean hasInit = false;
            for (TestCaseListDataBto testCaseListDataBto : testCaseListDataBtoList) {
                LocalDateTime caseStartTime = LocalDateTime.now();
                try {
                    LogQueueRuntime
                            .initTestCaseLog(
                                    caseExecuteVo.getJobId(),
                                    caseExecuteVo.getUserId()
                                    , testCaseListDataBto.getTestCase().getId()
                                    , caseExecuteVo.getType()
                                    , uniqueKey
                            );
                    if (!hasInit) {
                        //建立执行历史（ExecutionHistory）
                        insertExecutionHistory(uniqueKey, caseExecuteVo);
                        hasInit = true;
                    }
                    //执行测试用例
                    if (testCaseListDataBto.getTestDataList() != null && testCaseListDataBto.getTestDataList().size() > 0) {
                        List<TestDataExecuteResult> resultList =
                                executeTestCases(testCaseListDataBto, caseExecuteVo.getEnvId(), caseExecuteVo.getProjectId());
                        long count = resultList.stream().filter(e -> !e.getExecutionStatus()).count();
                        TestCaseReport testCaseReport = new TestCaseReport(
                                caseStartTime,
                                LocalDateTime.now(),
                                testCaseListDataBto.getTestCase().getId(),
                                testCaseListDataBto.getTestCase().getName(),
                                TestCaseTypeEnum.getTypeByValue(testCaseListDataBto.getTestCase().getType()).toString(),
                                testCaseListDataBto.getTestCase().getDetail(),
                                testCaseListDataBto.getTestCase().getDes(),
                                testCaseListDataBto.getTestCase().getMoveBefore(),
                                testCaseListDataBto.getTestCase().getMoveAfterTest(),
                                testCaseListDataBto.getTestCase().getMoveAfterCase(),
                                count <= 0,
                                resultList
                        );
                        runCaseResult.getCaseReports().add(testCaseReport);
                    }
                } catch (JobOrCaseRunningException runningException) {
                    //如果发生这个错误，说明用例或者任务，被重复执行了
                    if (session != null && session.isOpen()) {
                        session.sendMessage(new TextMessage(SocketResponseMessage.fail("-1.-1.-1.-1." + runningException.getMessage())));
                    }
                    break;
                } catch (Exception e) {
                    e.printStackTrace();
                    TestCaseReport testCaseReport = new TestCaseReport(
                            caseStartTime,
                            LocalDateTime.now(),
                            testCaseListDataBto.getTestCase().getId(),
                            testCaseListDataBto.getTestCase().getName(),
                            Objects.requireNonNull(TestCaseTypeEnum.getTypeByValue(testCaseListDataBto.getTestCase().getType())).toString(),
                            testCaseListDataBto.getTestCase().getDetail(),
                            testCaseListDataBto.getTestCase().getDes(),
                            testCaseListDataBto.getTestCase().getMoveBefore(),
                            testCaseListDataBto.getTestCase().getMoveAfterTest(),
                            testCaseListDataBto.getTestCase().getMoveAfterCase(),
                            false,
                            null
                    );
                    runCaseResult.getCaseReports().add(testCaseReport);
                    LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, String.format("[用例执行器] 产生错误：%s", e.getMessage()));
                }finally {
                    //将线程中的浏览器清除掉
                    httpRequestConfig.clear();
                    //将动作池子清理掉
                    clearMoveData();
                }
            }
        } catch (GlobalException | IOException e) {
            e.printStackTrace();
            try {
                if (session != null && session.isOpen()) {
                    TestExecuteLog currentTestExecute = LogQueueRuntime.getCurrentTestExecute(ThreadUtil.currentThreadId());
                    if (currentTestExecute != null) {
                        LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, e.getMessage());
                    } else {
                        //这里加-1.-1.-1是用来表明这里发出去的数据是不属于任何执行中的用例的
                        session.sendMessage(new TextMessage(SocketResponseMessage.success(String.format("-1.-1.-1.-1.%s", e.getMessage()))));
                    }
                }
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        } finally {
            runCaseResult.setEndTime(LocalDateTime.now());
            //将数据库中的执行历史状态设置为完成
            endExecutionHistory();
            //将本次产生的数据清除
            TestCaseExecuteSocketPool.remove(currentThreadId);
            //将本次产生的日志从执行状态设为停止状态
            LogQueueRuntime.remove(currentThreadId);
        }
        return runCaseResult;
    }

    public void insertExecutionHistory(String uniqueKey, CaseExecuteVo caseExecuteVo) {
        List<TestCaseListDataBto> testCaseListDataBtoList = caseExecuteVo.getTestCaseListDataBtoList();
        Long firstExecutionKey = getExecutionKey(caseExecuteVo);
        List<ExecutionHistory> executionHistories = new ArrayList<>();
        for (TestCaseListDataBto testCaseListDataBto : testCaseListDataBtoList) {
            List<TestData> testDataList = testCaseListDataBto.getTestDataList();
            TestCase testCase = testCaseListDataBto.getTestCase();
            for (int i = 0; i < testDataList.size(); i++) {
                ExecutionHistory executionHistory = new ExecutionHistory();
                executionHistory.setJobId(caseExecuteVo.getJobId());
                executionHistory.setUserId(caseExecuteVo.getUserId());
                executionHistory.setCaseId(testCase.getId());
                executionHistory.setDataId(testDataList.get(i).getId());
                executionHistory.setUniqueKey(uniqueKey);
                executionHistory.setExecutionKey(firstExecutionKey);
                executionHistory.setCaseExecuteVoString(JSONObject.toJSONString(caseExecuteVo));
                if (i == 0) {
                    executionHistory.setStartTime(LocalDateTime.now());
                }
                executionHistories.add(executionHistory);
            }
        }
        Long lastExecutionKey = getExecutionKey(caseExecuteVo);
        if (!lastExecutionKey.equals(firstExecutionKey)) {
            insertExecutionHistory(uniqueKey, caseExecuteVo);
        }
        executionHistoryService.saveBatch(executionHistories);
    }

    /**
     * 根据userId,jobId,caseId 往前查一个执行号 并且+1 ，如果jobId等于-1 则根据 userId,jobId,caseId 查否则根据 userId,jobId
     *
     * @return 新的执行号
     */
    private Long getExecutionKey(CaseExecuteVo caseExecuteVo) {
        LambdaQueryWrapper<ExecutionHistory> executionHistoryLambdaQueryWrapper = Wrappers.lambdaQuery(ExecutionHistory.class);
        executionHistoryLambdaQueryWrapper.eq(ExecutionHistory::getUserId, caseExecuteVo.getUserId());
        executionHistoryLambdaQueryWrapper.eq(ExecutionHistory::getJobId, caseExecuteVo.getJobId());
        executionHistoryLambdaQueryWrapper.orderByDesc(ExecutionHistory::getId);
        executionHistoryLambdaQueryWrapper.last("limit 1");
        if (caseExecuteVo.getJobId() == -1L) {
            TestCaseListDataBto testCaseListDataBto = caseExecuteVo.getTestCaseListDataBtoList().get(0);
            if (testCaseListDataBto != null) {
                executionHistoryLambdaQueryWrapper.eq(ExecutionHistory::getCaseId, testCaseListDataBto.getTestCase().getId());
            }
        }
        ExecutionHistory one = executionHistoryService.getOne(executionHistoryLambdaQueryWrapper);
        if (one != null && one.getExecutionKey() != null) {
            return one.getExecutionKey() + 1L;
        } else {
            return 1L;
        }

    }

    public void changeExecutionHistoryStatus(
            ExecutionHistoryStatus executionHistoryStatus) {
        TestExecuteLog currentTestExecute = LogQueueRuntime.getCurrentTestExecute(ThreadUtil.currentThreadId());
        if (currentTestExecute != null) {
            ExecutionHistory executionHistory = new ExecutionHistory();
            if (executionHistoryStatus.equals(ExecutionHistoryStatus.RUN)) {
                executionHistory.setStartTime(LocalDateTime.now());
            } else if (executionHistoryStatus.equals(ExecutionHistoryStatus.FINISH) || executionHistoryStatus.equals(ExecutionHistoryStatus.ERROR)) {
                executionHistory.setEndTime(LocalDateTime.now());
            }
            executionHistory.setStatus(executionHistoryStatus);
            executionHistoryService.update(executionHistory, Wrappers
                    .lambdaUpdate(ExecutionHistory.class)
                    .eq(ExecutionHistory::getJobId, currentTestExecute.getTestJobId())
                    .eq(ExecutionHistory::getCaseId, currentTestExecute.getTestCaseId())
                    .eq(ExecutionHistory::getDataId, currentTestExecute.getTestDataId())
                    .eq(ExecutionHistory::getUniqueKey, currentTestExecute.getUniqueKey())
                    .eq(ExecutionHistory::getUserId, currentTestExecute.getUserId())
            );
            //发送执行状态
            try {
                executionStatusMonitorSocketHandler.sendOverviewCurrentStatus(currentTestExecute.getUniqueKey());
                executionStatusMonitorSocketHandler.sendDetailCurrentStatus(
                        currentTestExecute.getUserId(),
                        currentTestExecute.getTestJobId(),
                        currentTestExecute.getTestCaseId(),
                        currentTestExecute.getTestDataId(),
                        currentTestExecute.getUniqueKey(),
                        executionHistoryStatus);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }


    /**
     * 将所有还未完成的执行历史设置为ERROR
     */
    public void endExecutionHistory() {
        TestExecuteLog currentTestExecute = LogQueueRuntime.getCurrentTestExecute(ThreadUtil.currentThreadId());
        if (currentTestExecute != null) {
            LambdaUpdateWrapper<ExecutionHistory> wrapper = Wrappers
                    .lambdaUpdate(ExecutionHistory.class)
                    .eq(ExecutionHistory::getUniqueKey, currentTestExecute.getUniqueKey())
                    .eq(ExecutionHistory::getUserId, currentTestExecute.getUserId())
                    .ne(ExecutionHistory::getStatus, ExecutionHistoryStatus.FINISH);
            ExecutionHistory executionHistory = new ExecutionHistory();
            executionHistory.setStatus(ExecutionHistoryStatus.ERROR);
            executionHistory.setEndTime(LocalDateTime.now());
            List<ExecutionHistory> list = executionHistoryService.list(wrapper);
            executionHistoryService.update(executionHistory, wrapper);
            try {
                executionStatusMonitorSocketHandler.sendOverviewCurrentStatus(currentTestExecute.getUniqueKey());
                for (ExecutionHistory history : list) {
                    executionStatusMonitorSocketHandler.sendDetailCurrentStatus(
                            history.getUserId(),
                            history.getJobId(),
                            history.getCaseId(),
                            history.getDataId(),
                            history.getUniqueKey(),
                            ExecutionHistoryStatus.ERROR);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
