package org.matrix.actuators.usecase;

import com.alibaba.fastjson.JSON;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.matrix.actuators.Actuator;
import org.matrix.actuators.checkpoint.CheckPointActuator;
import org.matrix.actuators.httpclient.HttpClientActuator;
import org.matrix.actuators.util.ThreadUtil;
import org.matrix.database.entity.TestCase;
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.entity.TestCaseBTO;
import org.matrix.database.entity.TestCaseListDataBto;
import org.matrix.database.entity.TestData;
import org.matrix.database.mapper.TestDataMapper;
import org.matrix.socket.LogQueueRuntime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

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

    private final CheckPointActuator checkPointActuator;

    private final HttpClientActuator httpClientActuator;

    private final String baseJsPath = "syntaxCheck.js";

    @Autowired
    TestDataMapper testDataMapper;

    public CaseActuator(CheckPointActuator checkPointActuator, HttpClientActuator httpClientActuator) {
        this.checkPointActuator = checkPointActuator;
        this.httpClientActuator = httpClientActuator;
    }

    /**
     * 执行测试用例
     */
    public TestCaseExecuteResult executeTestCase(TestCaseBTO testCaseBto, Long envId, Long projectId) {
        try {
            LogQueueRuntime.addNewLog("[用例执行器] 开始执行单条用例数据！！");
            //todo 李迪凡 执行前置动作
            //执行测试用例的本体内容
            HttpResponseDetail baseTestCaseResponseDetail = getHttpResponseDetail(
                    envId,
                    projectId,
                    testCaseBto.getTestCase(),
                    testCaseBto.getTestData());
            //todo 李迪凡 执行测试后动作
            //进行检验
            CheckPointResult checkPointResult = getCheckPointResult(testCaseBto.getTestCase(),
                    testCaseBto.getTestData(),
                    envId,
                    projectId,
                    baseTestCaseResponseDetail);
            ;
            //todo 李迪凡 执行后置动作
            TestCaseExecuteResult testCaseExecuteResult = new TestCaseExecuteResult(baseTestCaseResponseDetail, checkPointResult);
            LogQueueRuntime.addNewLog(JSON.toJSONString(testCaseExecuteResult));
            return testCaseExecuteResult;
        } catch (Exception e) {
            throw e;
        } finally {
            LogQueueRuntime.remove(ThreadUtil.currentThreadId());
        }
    }

    /**
     * todo 执行一条测试用例的多条测试数据
     */
    public List<TestCaseExecuteResult> executeTestCases(TestCaseListDataBto testCaseBto, Long envId, Long projectId) {
        for (int i = 0; i < 100; i++) {
            LogQueueRuntime.addNewLog("[用例执行器] 开始执行用例！！"+i);
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {

            LogQueueRuntime.addNewLog(String.format("[用例执行器] 当前正在执行用例ID: %s 用例名： %s",testCaseBto.getTestCase().getId(),testCaseBto.getTestCase().getName()));
            //todo 李迪凡 执行前置动作
            //执行测试用例的本体内容
            List<HttpResponseDetail> baseTestCaseResponseDetailList = new ArrayList<>();
            for (TestData testData : testCaseBto.getTestDataList()) {
                //向线程中设置当前正在执行的DataId
                LogQueueRuntime.setTestData(testData.getId());
                HttpResponseDetail baseTestCaseResponseDetail = getHttpResponseDetail(
                        envId,
                        projectId,
                        testCaseBto.getTestCase(),
                        testData);
                baseTestCaseResponseDetailList.add(baseTestCaseResponseDetail);
            }
            //将线程中正在执行的DataId清除
            LogQueueRuntime.clearTestData();
            //todo 李迪凡 执行测试后动作

            List<TestCaseExecuteResult> resultList = new ArrayList<>();
            for (int i = 0; i < testCaseBto.getTestDataList().size(); i++) {
                //向线程中设置当前正在执行的DataId
                LogQueueRuntime.setTestData(testCaseBto.getTestDataList().get(i).getId());
                CheckPointResult checkPointResult = getCheckPointResult(testCaseBto.getTestCase(),
                        testCaseBto.getTestDataList().get(i),
                        envId,
                        projectId,
                        baseTestCaseResponseDetailList.get(i));
                TestCaseExecuteResult testCaseExecuteResult = new TestCaseExecuteResult(baseTestCaseResponseDetailList.get(i), checkPointResult);
                resultList.add(testCaseExecuteResult);
                LogQueueRuntime.addNewLog(JSON.toJSONString(testCaseExecuteResult));
            }
            //将线程中正在执行的DataId清除
            LogQueueRuntime.clearTestData();
            //todo 李迪凡 执行后置动作
            return resultList;
        } catch (Exception e) {
            throw e;
        } finally {
            LogQueueRuntime.remove(ThreadUtil.currentThreadId());
        }
    }

    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 null;
    }

    private HttpResponseDetail getHttpResponseDetail(
            Long envId, Long projectId, TestCase testCase, TestData testData) {
        if (testCase.getType().equals(TestCaseTypeEnum.HTTP.getValue())) {
            HttpRequestDetail httpRequestDetail = JSON.parseObject(testData.getDetail(), HttpRequestDetail.class);
            return httpClientActuator.sendHttpRequest(httpRequestDetail, envId, projectId);
        }
        return null;
    }

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


}
