package com.ruoyi.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.domain.TestScenario;
import com.ruoyi.domain.TestType;
import com.ruoyi.domain.TestUseCase;
import com.ruoyi.domain.vo.*;
import com.ruoyi.service.ITestScenarioService;
import com.ruoyi.service.ITestTypeService;
import com.ruoyi.service.MatrixService;
import com.ruoyi.service.TestUseCaseService;
import com.ruoyi.web.response.MatrixResponse;
import lombok.Data;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Transactional
@Service
public class MatrixServiceImpl implements MatrixService {

    @Autowired
    private TestUseCaseService testUseCaseService;

    @Autowired
    private ITestScenarioService testScenarioService;

    @Autowired
    private ITestTypeService testTypeService;

    @Override
    public MatrixResponse getMatrix() {

        List<TestUseCase> useCases = testUseCaseService.list();
        List<TestScenario> scenarios = testScenarioService.list();
        List<TestType> types = testTypeService.list();

        MatrixResponse response = new MatrixResponse();
        setHeader(response, types);
        setRows(response, scenarios, types, useCases);

        return response;
    }

    @Override
    public MatrixResponse getMatrixForUrl() throws IOException {

        //以post形式请求接口
        String result= HttpUtil.post("https://10.12.48.78:8090/DescribeScenarioTestTypeList","");
        JSONObject jsonObject = JSONObject.parseObject(result);

        // 获取测试场景列表
        List<ScenarioVO> scenarioList = jsonObject.getList("scenario_list", ScenarioVO.class);
        if (scenarioList != null && scenarioList.size() != 0 ) {
            for (int i = 0; i < scenarioList.size(); i++) {
                scenarioList.get(i).setId((long) i);
            }
        }

        // 获取测试方法列表
        List<TestTypeVO> testTypeList = jsonObject.getList("test_type_list", TestTypeVO.class);
        if (testTypeList != null && testTypeList.size() != 0 ) {
            for (int i = 0; i < testTypeList.size(); i++) {
                testTypeList.get(i).setId((long) i);
            }
        }

        // 获取测试用例
        OkHttpClient client = new OkHttpClient().newBuilder().build();

        MediaType mediaType = MediaType.parse("application/json");

        // 创建请求体
        String request = "{\"offset\": {\n" +
                "    \"offset\": 0,\n" +
                "    \"limit\": 9999\n" +
                "  },\n" +
                "  \"searchFields\":{\n" +
                "    \"name\": \"\",\n" +
                "    \"scenario\":\"\",\n" +
                "    \"method\":\"\"\n" +
                "  }}";
        RequestBody body = RequestBody.create(mediaType, "{\"query\":\"query useCases($offset:OffsetConnectionInput$orderBy:OrderByInput$filter:Map$search:String$searchFields:Map){useCases(offset:$offset orderBy:$orderBy filterFields:$filter search:$search searchFields:$searchFields){nodes{id displayID class name description remediation requirements riskLevel method{name}scenario{name}}totalCount}}\",\"variables\":"+ request +"}");

        Request requestKE = new Request.Builder()
                .url("http://10.12.48.80:8089/api/query")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                // TODO 连接
//                .addHeader("Host", "10.12.48.80:8089")
//                .addHeader("Origin", "http://10.12.48.80:8089")
//                .addHeader("Referer", "http://10.12.48.80:8089/api/graphql/playground")
//                .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")
                .build();

        Response responseR = client.newCall(requestKE).execute();
        String string = responseR.body().string();
        JSONObject jsonO = JSONObject.parseObject(string);

        // 获取测试用例列表
        List<UseCaseVO> caseList = jsonO.getJSONObject("data").getJSONObject("useCases").getList("nodes", UseCaseVO.class);

        MatrixResponse response = new MatrixResponse();
        setHeaderName(response, testTypeList);
        setRowsName(response, scenarioList, testTypeList, caseList);

        return response;
    }

    @Override
    public MatrixResponse getMatrixForUrlPad() throws IOException {
        //以post形式请求接口
        String result= HttpUtil.post("https://10.12.48.78:8090/DescribeScenarioTestTypeList","");
        JSONObject jsonObject = JSONObject.parseObject(result);

        // 获取测试场景列表
        List<ScenarioVO> scenarioList = jsonObject.getList("scenario_list", ScenarioVO.class);
        if (scenarioList != null && scenarioList.size() != 0 ) {
            for (int i = 0; i < scenarioList.size(); i++) {
                scenarioList.get(i).setId((long) i);
            }
        }

        // 获取测试方法列表
        List<TestTypeVO> testTypeList = jsonObject.getList("test_type_list", TestTypeVO.class);
        if (testTypeList != null && testTypeList.size() != 0 ) {
            for (int i = 0; i < testTypeList.size(); i++) {
                testTypeList.get(i).setId((long) i);
            }
        }

        // 获取测试用例
        OkHttpClient client = new OkHttpClient().newBuilder().build();

        MediaType mediaType = MediaType.parse("application/json");

        // 创建请求体
        String request = "{\"offset\": {\n" +
                "    \"offset\": 0,\n" +
                "    \"limit\": 9999\n" +
                "  },\n" +
                "  \"searchFields\":{\n" +
                "    \"name\": \"\",\n" +
                "    \"scenario\":\"\",\n" +
                "    \"method\":\"\"\n" +
                "  }}";
        RequestBody body = RequestBody.create(mediaType, "{\"query\":\"query useCases($offset:OffsetConnectionInput$orderBy:OrderByInput$filter:Map$search:String$searchFields:Map){useCases(offset:$offset orderBy:$orderBy filterFields:$filter search:$search searchFields:$searchFields){nodes{id displayID class name description remediation requirements riskLevel method{name}scenario{name}}totalCount}}\",\"variables\":"+ request +"}");

        Request requestKE = new Request.Builder()
                .url("http://10.12.48.80:8089/api/query")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                // TODO 连接
//                .addHeader("Host", "10.12.48.80:8089")
//                .addHeader("Origin", "http://10.12.48.80:8089")
//                .addHeader("Referer", "http://10.12.48.80:8089/api/graphql/playground")
//                .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")
                .build();

        Response responseR = client.newCall(requestKE).execute();
        String string = responseR.body().string();
        JSONObject jsonO = JSONObject.parseObject(string);

        // 获取测试用例列表
        List<UseCaseVO> caseList = jsonO.getJSONObject("data").getJSONObject("useCases").getList("nodes", UseCaseVO.class);

        MatrixResponse response = new MatrixResponse();
        setHeaderName(response, testTypeList);
        setRowsNamePad(response, scenarioList, testTypeList, caseList);

        return response;
    }

    private void setRowsName(MatrixResponse response, List<ScenarioVO> scenarioList, List<TestTypeVO> testTypeList, List<UseCaseVO> caseList) {

        List<Map<String, Object>> rows = new ArrayList();


        for(ScenarioVO scenario : scenarioList) {

            Map<String, Object> row = new HashMap();
            row.put("name", scenario.getName());

            for(TestTypeVO type : testTypeList) {
                String column = type.getName();
                String columnId = String.valueOf(type.getId());
                String coordinates = scenario.getName() + column;
                String useCase = getUseCaseIdByCoordinatesName(caseList, coordinates);
                row.put(columnId, useCase == null ? "" : useCase);
            }

            rows.add(row);
        }

        response.setRows(rows);
    }

    private void setRowsNamePad(MatrixResponse response, List<ScenarioVO> scenarioList, List<TestTypeVO> testTypeList, List<UseCaseVO> caseList) {

        List<Map<String, Object>> rows = new ArrayList();


        for(ScenarioVO scenario : scenarioList) {

            Map<String, Object> row = new HashMap();
            row.put("name", scenario.getName());

            for(TestTypeVO type : testTypeList) {
                String column = type.getName();
                String columnId = String.valueOf(type.getId());
                String coordinates = scenario.getName() + column;
                String useCase = getUseCaseIdByCoordinatesNamePad(caseList, coordinates);
                row.put(columnId, useCase == null ? "" : useCase);
            }

            rows.add(row);
        }

        response.setRows(rows);
    }

    public String getUseCaseIdByCoordinatesNamePad(List<UseCaseVO> caseList, String coordinates) {

        for(UseCaseVO useCase : caseList) {
            if(useCase.getCoordinates().equals(coordinates)) {
                return useCase.getDisplayID();
            }
        }
        return null;
    }

    public String getUseCaseIdByCoordinatesName(List<UseCaseVO> caseList, String coordinates) {

        for(UseCaseVO useCase : caseList) {
            if(useCase.getCoordinates().equals(coordinates)) {
                return useCase.getId();
            }
        }
        return null;
    }

    private void setHeaderName(MatrixResponse response, List<TestTypeVO> testTypeList) {

        List<MatrixColumnVO> columns = new ArrayList();

        for(TestTypeVO type : testTypeList) {
            MatrixColumnVO column = new MatrixColumnVO(String.valueOf(type.getId()),type.getName());
            columns.add(column);
        }

        response.setHeader(columns);
    }

    private void setHeader(MatrixResponse response, List<TestType> types) {

        List<MatrixColumnVO> columns = new ArrayList();

        for(TestType type : types) {
            MatrixColumnVO column = new MatrixColumnVO(String.valueOf(type.getId()), type.getTestType());
            columns.add(column);
        }

        response.setHeader(columns);

    }

    private void setRows(MatrixResponse response, List<TestScenario> scenarios, List<TestType> types, List<TestUseCase> useCases) {

        List<Map<String, Object>> rows = new ArrayList();


        for(TestScenario scenario : scenarios) {

            Map<String, Object> row = new HashMap();
            row.put("name", scenario.getTestScenario());

            for(TestType type : types) {
                String columnId = String.valueOf(type.getId());
                String coordinates = scenario.getId() + columnId;
                String useCaseId = getUseCaseIdByCoordinates(useCases, coordinates);
                row.put(columnId, useCaseId == null ? "" : useCaseId);
            }

            rows.add(row);
        }

        response.setRows(rows);
    }

    public String getUseCaseIdByCoordinates(List<TestUseCase> useCases, String coordinates) {

        for(TestUseCase useCase : useCases) {
            if(useCase.getCoordinates().equals(coordinates)) {
                return useCase.getCaseId();
            }
        }
        return null;
    }
}