package org.matrix.testNg;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.matrix.BaseBootApplication;
import org.matrix.actuators.checkpoint.CheckPointActuator;
import org.matrix.actuators.checkpoint.CheckPointResult;
import org.matrix.actuators.httpclient.HttpClientActuator;
import org.matrix.actuators.usecase.CaseActuator;
import org.matrix.actuators.usecase.TestCaseExecuteResult;
import org.matrix.database.entity.TestCase;
import org.matrix.database.entity.TestCaseBTO;
import org.matrix.database.entity.TestData;
import org.matrix.database.service.ITestCaseService;
import org.matrix.database.service.ITestDataService;
import org.matrix.exception.GlobalException;
import org.matrix.socket.LogQueueRuntime;
import org.matrix.socket.TestCaseExecuteSocketPool;
import org.matrix.socket.TestExecuteType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.stereotype.Component;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.*;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author mry
 */
@Component
@SpringBootTest(classes = BaseBootApplication.class)

public class TestPigeon extends AbstractTestNGSpringContextTests {

    String sql;
    Long envId;
    Long projectId;

    @Value("${spring.datasource.dynamic.datasource.master.driverClassName}")
    private String driver;

    @Value("${spring.datasource.dynamic.datasource.master.url}")
    private String url;

    @Value("${spring.datasource.dynamic.datasource.master.username}")
    private String username;

    @Value("${spring.datasource.dynamic.datasource.master.password}")
    private String password;

    @Autowired
    private ITestCaseService caseService;

    @Autowired
    private ITestDataService dataService;

    @Autowired
    private CheckPointActuator checkPointActuator;

    @Autowired
    private HttpClientActuator httpClientActuator;

    @Autowired
    private CaseActuator caseActuator;

    @Parameters({"sql", "envId", "projectId"})
    @BeforeClass
    public void beforeClass(String sql, Long envId, Long projectId) {
        this.sql = sql;
        this.envId = envId;
        this.projectId = projectId;
    }

    /**
     * XML中的SQL决定了执行什么用例, 执行多少条用例, SQL的搜索结果为需要测试的测试用例
     */
    @DataProvider(name = "testData")
    private Iterator<Object[]> getData() {
        return new DataProviderForDb(driver, url, username, password, sql);
    }

    @Test(dataProvider = "testData")
    public void test(Map<String, String> data) {
        //todo 黄夏豪 这里的调用接口我改掉了 等我改完了再喊你改
        long caseId = Long.parseLong(data.get("id"));
        TestCase testCase = java.util.Optional.of(caseService.getById(caseId))
                .orElseThrow(() -> new GlobalException(String.format("没有找到id = %d 的TestCase", caseId)));
        List<TestData> testDataList = java.util.Optional.of(dataService.list(Wrappers.lambdaQuery(TestData.class)
                .eq(TestData::getTestCaseId, caseId)))
                .orElseThrow(() -> new GlobalException(String.format("没有找到testCaseId = %d 的TestData", caseId)));
        TestCaseBTO testCaseBTO = new TestCaseBTO();
        testCaseBTO.setTestCase(testCase);
        String unionKey = UUID.randomUUID().toString();
        LogQueueRuntime
                .initTestCaseLog(null
                        , 1L
                        , testCase.getId()
                        , TestExecuteType.TEST_CASE
                        , unionKey
                );
        for (TestData testData : testDataList) {
            testCaseBTO.setTestData(testData);
            TestCaseExecuteResult testCaseExecuteResult = caseActuator.executeTestCase(testCaseBTO, envId, projectId);
            CheckPointResult checkPointResult = testCaseExecuteResult.getCheckPointResult();
            Reporter.log(checkPointResult.toString());
        }
        //将本次产生的数据清除
        TestCaseExecuteSocketPool.remove(Thread.currentThread().getId());
    }

    @AfterMethod
    public void afterMethod(ITestResult result, Object[] objs) {
        System.out.println("正在运行的方法:" + result.getName());
    }

}
