package com.test.common.utils;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.PathNotFoundException;
import com.test.common.core.domain.model.*;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.gui.ArgumentsPanel;
import org.apache.jmeter.control.GenericController;
import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.control.gui.LogicControllerGui;
import org.apache.jmeter.control.gui.LoopControlPanel;
import org.apache.jmeter.control.gui.TestPlanGui;
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.extractor.json.jsonpath.JSONPostProcessor;
import org.apache.jmeter.extractor.json.jsonpath.gui.JSONPostProcessorGui;
import org.apache.jmeter.protocol.http.control.Header;
import org.apache.jmeter.protocol.http.control.HeaderManager;
import org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui;
import org.apache.jmeter.protocol.http.gui.HeaderPanel;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.apache.jmeter.reporters.ResultCollector;
import org.apache.jmeter.reporters.Summariser;
import org.apache.jmeter.samplers.SampleSaveConfiguration;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testbeans.gui.TestBeanGUI;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestPlan;
import org.apache.jmeter.testelement.property.*;
import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jmeter.threads.gui.ThreadGroupGui;
import org.apache.jmeter.timers.ConstantThroughputTimer;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author liangdaliang
 * @Description：JMeterter线程组工具类
 * @date 2025-04-14 17:44
 */
public class JMeterGroupUtil {

    private static final Logger logger = LoggerFactory.getLogger(JMeterGroupUtil.class);

    /**
     * 生成jmeter测试执行计划并获取执行结果
     * @param jmeterGroupRequest
     * @return
     */
    public static JmeterGlobalStatEntity getJmeterResult(JmeterGroupRequest jmeterGroupRequest) {
        Long id = jmeterGroupRequest.getTestCaseId();
        Integer concurrentThreads = jmeterGroupRequest.getConcurrentThreads();
        Integer loopCount = jmeterGroupRequest.getLoopCount();
        Integer errorOperType = jmeterGroupRequest.getErrorOperType();
        Integer executeType = jmeterGroupRequest.getExecuteType();
        Integer rampUpSeconds = jmeterGroupRequest.getRampUpSeconds();
        Long pressureSecond = jmeterGroupRequest.getPressureSecond();
        Integer rpsStatus = jmeterGroupRequest.getRpsStatus();
        Integer rpsLimit = jmeterGroupRequest.getRpsLimit();
        String jmeterHomePath = jmeterGroupRequest.getJmeterHomePath();
        JmeterGlobalStatEntity result = null;
        try {
            // 1. 初始化 JMeter
            JMeterUtils.loadJMeterProperties(jmeterHomePath + "/bin/jmeter.properties");
            JMeterUtils.setJMeterHome(jmeterHomePath);
            JMeterUtils.initLocale();

            // 2. 创建测试计划
            TestPlan testPlan = createTestPlan("Dynamic Test Plan");

            // 3. 创建线程组
            org.apache.jmeter.threads.ThreadGroup threadGroup = createThreadGroup(concurrentThreads, loopCount, errorOperType, executeType, rampUpSeconds, pressureSecond);

            // 4. 获取结果：如汇总报告、查看结果树
            String replayLogPath = jmeterHomePath + "/p_replay_result"+ id +".log";
            String summaryReportPath = jmeterHomePath + "/p_summary_report"+ id +".log";
            List<ResultCollector> resultCollector = getResultCollector(replayLogPath, summaryReportPath);

            // 5. 构建测试树，新增每个用例下的http请求节点
            HashTree firstTreeTestPlan = new HashTree();
            HashTree secondHashTree = new HashTree();
            HashTree thirdHashTree = new HashTree();

            // 6. 获取设置吞吐量
            ConstantThroughputTimer constantThroughputTimer = null;
            thirdHashTree.add(resultCollector);

            if (rpsStatus != null && rpsStatus == 1) {
                constantThroughputTimer = getConstantThroughputTimer(rpsLimit);
                thirdHashTree.add(constantThroughputTimer);
            }
            HashTree threadGroupHashTree = secondHashTree.add(threadGroup);
            GenericController simpleController = new GenericController();
            simpleController.setName("简单顺序逻辑控制器");
            simpleController.setProperty(TestElement.TEST_CLASS, GenericController.class.getName());
            simpleController.setProperty(TestElement.GUI_CLASS, LogicControllerGui.class.getName());
            HashTree simpleControllerTree = threadGroupHashTree.add(simpleController);
            dealHttpHashTreeWithRequestList(simpleControllerTree, jmeterGroupRequest.getJmeterRequestList());
            secondHashTree.add(threadGroup, thirdHashTree);
            firstTreeTestPlan.add(testPlan, secondHashTree);

            // 7. 保存测试计划为 JMX 文件
            File jmxFile = new File(jmeterHomePath + "/p_dynamic_test_plan"+ id +".jmx");
            SaveService.saveTree(firstTreeTestPlan, new FileOutputStream(jmxFile));

            // 8. 运行 JMeter 测试
            File resultFile = new File(jmeterHomePath + "/p_summary_report"+ id +".log");
            if (resultFile.exists()) {
                resultFile.delete();
            }
            StandardJMeterEngine jmeter = new StandardJMeterEngine();
            jmeter.configure(firstTreeTestPlan);
            jmeter.run();
            while (jmeter.isActive()) {
                System.out.println("JMeter isActive！");
                Thread.sleep(1000); // 每隔 1 秒检查一次
            }
            // 9. 获取响应结果
            result = getResultMessageFromFile(jmeterHomePath + "/p_summary_report"+ id +".log");
//            if (result != null) {
//                result.put("requestHeader", requestHeaderJson);
//                result.put("requestBody", requestBody);
//            }

            System.out.println("JMeter 测试执行完成！");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 处理线程组下新增每个用例下的http请求节点
     * @param thirdHashTree
     * @param requestList
     */
    private static void dealHttpHashTreeWithRequestList(HashTree thirdHashTree, List<JmeterRequest> requestList) {
        for (JmeterRequest jmeterRequest : requestList) {
            try {
                HashTree fourHashTree = new HashTree();
                // 创建 HTTP 请求
                String url = jmeterRequest.getUrl();
                int port = jmeterRequest.getPort();
                String method = jmeterRequest.getMethod().toUpperCase();
                String requestBody = jmeterRequest.getRequestBody();
                String requestParams = jmeterRequest.getRequestParams();
                Map<String, String> requestParamsMap = convertJsonStringToMap(requestParams);
                String requestHeader = jmeterRequest.getRequestHeader();
                HTTPSamplerProxy httpSampler = null;
                if ("POST".equals(method)) {
                    httpSampler = createPostHttpSampler(
                            jmeterRequest.getTestCaseName(),
                            url, // 请求地址
                            port,
                            requestBody, // 请求体
                            requestParamsMap // 查询参数
                    );
                } else {
                    httpSampler = createGetHttpSampler(
                            jmeterRequest.getTestCaseName(),
                            url, // 请求地址
                            port,
                            requestParamsMap // 查询参数
                    );
                }
                // 创建请求头管理器
                Map<String, String> headerMap = new HashMap<>();
                if (!StringUtils.isEmpty(requestHeader) && !requestHeader.equals("[]")) {
                    Gson gson = new Gson();
                    // 定义类型
                    Type type = new TypeToken<List<Map<String, String>>>() {
                    }.getType();
                    // 解析 JSON 数组
                    List<Map<String, String>> headerList = null;
                    try {
                        headerList = gson.fromJson(requestHeader, type);
                        // 将 List<Map<String, String>> 转换为 Map<String, String>
                        for (Map<String, String> entry : headerList) {
                            String key = entry.get("key");
                            String value = entry.get("value");
                            headerMap.put(key, value);
                        }
                    } catch (Exception e) {
                        logger.error("requestHeader gson.fromJson异常！requestHeader：" + requestHeader, e);
                    }
                }
                HeaderManager headerManager = createHeaderManager(headerMap);
                List<String> extractionRuleList = jmeterRequest.getExtractionRuleList();
                if (headerManager != null) {
                    fourHashTree.add(headerManager);
                    createJsonPostProcessor(extractionRuleList, fourHashTree);
                    thirdHashTree.add(httpSampler, fourHashTree);
                } else {
                    createJsonPostProcessor(extractionRuleList, fourHashTree);
                    if (fourHashTree.isEmpty()) {
                        thirdHashTree.add(httpSampler);
                    } else {
                        thirdHashTree.add(httpSampler, fourHashTree);
                    }
                }

            } catch (Exception e) {
                String info = "url:" + jmeterRequest.getUrl() + ", port:" + jmeterRequest.getPort();
                logger.error(info + " dealHttpHashTreeWithRequest异常", e);
            }
        }
    }

    /**
     * 创建Json参数提取
     * @param extractionRuleList
     * @param fourHashTree
     * @return
     */
    private static void createJsonPostProcessor(List<String> extractionRuleList, HashTree fourHashTree) {
        if (extractionRuleList != null) {
            for (String extractionRule : extractionRuleList) {
                String[] array = extractionRule.split(",");
                JSONPostProcessor jsonExtractor = new JSONPostProcessor();
                jsonExtractor.setName("提取" + array[0]);
                jsonExtractor.setProperty(TestElement.TEST_CLASS, JSONPostProcessor.class.getName());
                jsonExtractor.setProperty(TestElement.GUI_CLASS, JSONPostProcessorGui.class.getName());
                jsonExtractor.setEnabled(true);
                if (array[1].startsWith("$")) {
                    jsonExtractor.setJsonPathExpressions(array[1]); // JSONPath 表达式
                } else {
                    jsonExtractor.setJsonPathExpressions("$." + array[1]); // JSONPath 表达式
                }
                jsonExtractor.setMatchNumbers("1"); // 0表示随机，1表示第一个
                jsonExtractor.setRefNames(array[0]); // 存储变量名
                jsonExtractor.setDefaultValues("");
                fourHashTree.add(jsonExtractor);
            }
        }
    }

    /**
     * 创建测试计划
     * @param name
     * @return
     */
    private static TestPlan createTestPlan(String name) {
        TestPlan testPlan = new TestPlan(name);
        testPlan.setProperty(TestElement.TEST_CLASS, TestPlan.class.getName());
        testPlan.setProperty(TestElement.GUI_CLASS, TestPlanGui.class.getName());
        testPlan.setUserDefinedVariables((Arguments) new ArgumentsPanel().createTestElement());
        return testPlan;
    }

    /**
     * 创建线程组
     * @param numThreads
     * @param loops
     * @param errorOperType
     * @param executeType
     * @param rampUpSeconds
     * @param pressureSecond
     * @return
     */
    private static org.apache.jmeter.threads.ThreadGroup createThreadGroup(Integer numThreads, Integer loops, Integer errorOperType, Integer executeType, Integer rampUpSeconds, Long pressureSecond) {
        org.apache.jmeter.threads.ThreadGroup threadGroup = new org.apache.jmeter.threads.ThreadGroup();
        threadGroup.setName("Thread Group");
        threadGroup.setNumThreads(numThreads);
        threadGroup.setRampUp(rampUpSeconds);
        threadGroup.setDelay(0);
        if (executeType == 1) {
            threadGroup.setDuration(pressureSecond);
            threadGroup.setProperty(new TestElementProperty(ThreadGroup.MAIN_CONTROLLER, createLoopController(-1)));
            threadGroup.setProperty(new BooleanProperty(ThreadGroup.IS_SAME_USER_ON_NEXT_ITERATION, true));
            threadGroup.setScheduler(true);
        } else {
            threadGroup.setScheduler(false);
            threadGroup.setProperty(new TestElementProperty(ThreadGroup.MAIN_CONTROLLER, createLoopController(loops)));
        }
        if (errorOperType == 1) {
            threadGroup.setProperty(new StringProperty(ThreadGroup.ON_SAMPLE_ERROR, "continue"));
        } else if (errorOperType == 2) {
            threadGroup.setProperty(new StringProperty(ThreadGroup.ON_SAMPLE_ERROR, "startnextloop"));
        } else if (errorOperType == 3) {
            threadGroup.setProperty(new StringProperty(ThreadGroup.ON_SAMPLE_ERROR, "stopthread"));
        } else if (errorOperType == 4) {
            threadGroup.setProperty(new StringProperty(ThreadGroup.ON_SAMPLE_ERROR, "stoptest"));
        } else if (errorOperType == 5) {
            threadGroup.setProperty(new StringProperty(ThreadGroup.ON_SAMPLE_ERROR, "stoptestnow"));
        }
        threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
        threadGroup.setProperty(TestElement.GUI_CLASS, ThreadGroupGui.class.getName());
        threadGroup.setProperty(new BooleanProperty(TestElement.ENABLED, true));
        return threadGroup;
    }

    /**
     * 创建轮询控制器
     * @return
     */
    private static LoopController createLoopController(Integer loops) {
        LoopController loopController = new LoopController();
        loopController.setContinueForever(false);
        loopController.setProperty(new StringProperty(TestElement.GUI_CLASS, LoopControlPanel.class.getName()));
        loopController.setProperty(new StringProperty(TestElement.TEST_CLASS, LoopController.class.getName()));
        loopController.setProperty(new StringProperty(TestElement.NAME, "循环控制器"));
        loopController.setProperty(new BooleanProperty(TestElement.ENABLED, true));
        loopController.setProperty(new IntegerProperty(LoopController.LOOPS, loops));
        return loopController;
    }

    /**
     * 创建get请求方式
     * @param testCaseName
     * @param urlString
     * @param port
     * @param requestParams
     * @return
     * @throws MalformedURLException
     */
    private static HTTPSamplerProxy createGetHttpSampler(String testCaseName, String urlString, int port, Map<String, String> requestParams) throws MalformedURLException {
        URL url = new URL(urlString);
        // 提取域名（不包括端口号）
        String domain = url.getHost();
        // 提取路径（不包括查询参数和片段标识符）
        String path = url.getPath();
        HTTPSamplerProxy httpSampler = new HTTPSamplerProxy();
        httpSampler.setName(testCaseName);
        httpSampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
        httpSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
        httpSampler.setDomain(domain); // 提取域名
        if (requestParams != null) {
            path += "?";
            path += mapToQueryString(requestParams);
        }
        httpSampler.setPath(path); // 提取路径
        httpSampler.setPort(port);
        httpSampler.setMethod("GET");
        httpSampler.setConnectTimeout("5000");
        httpSampler.setUseKeepAlive(true);

        return httpSampler;
    }

    /**
     * 构建get请求查询参数
     * @param params
     * @return
     */
    public static String mapToQueryString(Map<String, String> params) {
        StringBuilder queryString = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (!queryString.isEmpty()) {
                queryString.append("&");
            }
            // 对键和值进行 URL 编码
            String encodedKey = URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8);
            String encodedValue = URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8);
            queryString.append(encodedKey).append("=").append(encodedValue);
        }
        return queryString.toString();
    }

    /**
     * 转换[{"key":"authorization","value":"tttt"},{"key":"name","value":"123"}]为Map结构
     * @param jsonString
     * @return
     */
    private static Map<String, String> convertJsonStringToMap(String jsonString) {
        if (StringUtils.isEmpty(jsonString) || jsonString.equals("[]")) {
            return null;
        }
        Gson gson = new Gson();
        // 定义类型，用于告诉Gson我们期望的结果类型是一个包含键值对的对象列表
        Type listType = new TypeToken<List<Map<String, String>>>(){}.getType();

        // 将JSON字符串转换为List<Map<String, String>>
        List<Map<String, String>> keyValuePairs = null;
        try {
//            jsonString = jsonString.replaceAll(", \\[\\{\\}]", "");
//            jsonString = jsonString.replaceAll(",\\[\\{\\}]", "");
            keyValuePairs = gson.fromJson(jsonString, listType);
        } catch (Exception e) {
            logger.error("gson.fromJson发生异常！jsonString：" + jsonString, e);
            return null;
        }

        // 创建一个新的Map<String, String>用于存储结果
        Map<String, String> resultMap = new HashMap<>();
        for (Map<String, String> pair : keyValuePairs) {
            // 确保每个map都有"key"和"value"两个字段
            if (pair.containsKey("key") && pair.containsKey("value")) {
                resultMap.put(pair.get("key"), pair.get("value"));
            }
        }

        return resultMap;
    }

    /**
     * 创建post请求方式
     * @param testCaseName
     * @param urlString
     * @param port
     * @param requestBody
     * @param requestParams
     * @return
     * @throws MalformedURLException
     */
    private static HTTPSamplerProxy createPostHttpSampler(String testCaseName, String urlString, int port, String requestBody, Map<String, String> requestParams) throws MalformedURLException {
        URL url = new URL(urlString);
        // 提取域名（不包括端口号）
        String domain = url.getHost();
        // 提取路径（不包括查询参数和片段标识符）
        String path = url.getPath();
//        int portTest = url.getPort();
        HTTPSamplerProxy httpSampler = new HTTPSamplerProxy();
        httpSampler.setName(testCaseName);
        httpSampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
        httpSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
        httpSampler.setDomain(domain);
        if (requestParams != null) {
            path += "?";
            path += mapToQueryString(requestParams);
        }
        httpSampler.setPath(path);
        httpSampler.setPort(port);
        httpSampler.setMethod("POST");
        httpSampler.setConnectTimeout("5000");
        httpSampler.setUseKeepAlive(true);

        // 设置请求体
        httpSampler.setPostBodyRaw(true); // 使用原始请求体
        httpSampler.addNonEncodedArgument("", requestBody, "");

        return httpSampler;
    }

    /**
     * 创建http请求头管理器
     * @param headerMap
     * @return
     */
    private static HeaderManager createHeaderManager(Map<String, String> headerMap) {
        if (headerMap == null || headerMap.isEmpty()) {
            return null;
        }
        HeaderManager headerManager = new HeaderManager();
        headerManager.setName("HTTP Header Manager");
        headerManager.setProperty(TestElement.TEST_CLASS, HeaderManager.class.getName());
        headerManager.setProperty(TestElement.GUI_CLASS, HeaderPanel.class.getName());

        // 添加默认 Content-Type 请求头
//        if (!headerMap.containsKey("Content-Type")) {
//            Header contentTypeHeader = new Header();
//            contentTypeHeader.setName("Content-Type");
//            contentTypeHeader.setValue("application/json; charset=UTF-8");
//            headerManager.add(contentTypeHeader);
//        }

        // 遍历 headerMap，动态添加请求头
        for (Map.Entry<String, String> entry : headerMap.entrySet()) {
            Header header = new Header();
            header.setName(entry.getKey()); // 请求头名称
            header.setValue(entry.getValue()); // 请求头值
            headerManager.add(header);
        }

        return headerManager;
    }

    /***
     * 监听结果树
     * @param replayLogPath  将结果保存到文件中，这个是文件的路径
     * @param summaryReportPath  将汇总报告保存到文件中，这个是文件的路径
     * @return
     */
    private static List<ResultCollector> getResultCollector(String replayLogPath, String summaryReportPath) {
        // 察看结果数
        List<ResultCollector> resultCollectors = new ArrayList<>();
//        Summariser summariser = new Summariser("速度");
//        ResultCollector resultCollector = new ResultCollector(summariser);
//        resultCollector.setProperty(new BooleanProperty("ResultCollector.error_logging", false));
//        resultCollector.setProperty(new ObjectProperty("saveConfig", getSampleSaveConfig()));
//        resultCollector.setProperty(new StringProperty("TestElement.gui_class", "org.apache.jmeter.visualizers.ViewResultsFullVisualizer"));
//        resultCollector.setProperty(new StringProperty("TestElement.name", "察看结果树"));
//        resultCollector.setProperty(new StringProperty("TestElement.enabled", "true"));
//        resultCollector.setProperty(new StringProperty("filename", replayLogPath));
//        resultCollectors.add(resultCollector);

        // 结果汇总
        Summariser summariser = new Summariser("汇总报告");
        ResultCollector resultTotalCollector = new ResultCollector(summariser);
        resultTotalCollector.setProperty(new BooleanProperty("ResultCollector.error_logging", false));
        resultTotalCollector.setProperty(new ObjectProperty("saveConfig", getSampleSaveConfig()));
        resultTotalCollector.setProperty(new StringProperty("TestElement.gui_class", "org.apache.jmeter.visualizers.SummaryReport"));
        resultTotalCollector.setProperty(new StringProperty("TestElement.name", "汇总报告"));
        resultTotalCollector.setProperty(new StringProperty("TestElement.enabled", "true"));
        resultTotalCollector.setProperty(new StringProperty("filename", summaryReportPath));
        resultCollectors.add(resultTotalCollector);

        return resultCollectors;
    }

    /**
     * 配置采样结果信息
     * @return
     */
    private static SampleSaveConfiguration getSampleSaveConfig() {
        SampleSaveConfiguration sampleSaveConfiguration = new SampleSaveConfiguration();
        sampleSaveConfiguration.setTime(true);
        sampleSaveConfiguration.setLatency(true);
        sampleSaveConfiguration.setTimestamp(true);
        sampleSaveConfiguration.setSuccess(true);
        sampleSaveConfiguration.setLabel(true);
        sampleSaveConfiguration.setCode(true);
        sampleSaveConfiguration.setMessage(true);
        sampleSaveConfiguration.setThreadName(true);
        sampleSaveConfiguration.setDataType(true);
        sampleSaveConfiguration.setEncoding(true);
        sampleSaveConfiguration.setAssertions(true);
        sampleSaveConfiguration.setSubresults(true);
        sampleSaveConfiguration.setResponseData(false);
        sampleSaveConfiguration.setSamplerData(true);
        sampleSaveConfiguration.setAsXml(true);
        sampleSaveConfiguration.setFieldNames(true);
        sampleSaveConfiguration.setResponseHeaders(false);
        sampleSaveConfiguration.setRequestHeaders(false);
        sampleSaveConfiguration.setAssertionResultsFailureMessage(true);
        //sampleSaveConfiguration.setsserAtionsResultsToSave(0); assertionsResultsToSave
        sampleSaveConfiguration.setBytes(true);
        sampleSaveConfiguration.setSentBytes(true);
        sampleSaveConfiguration.setUrl(true);
        sampleSaveConfiguration.setThreadCounts(true);
        sampleSaveConfiguration.setIdleTime(true);
        sampleSaveConfiguration.setConnectTime(true);
        return sampleSaveConfiguration;
    }



    /***
     * 限制QPS设置
     * @param throughputTimer
     * @return
     */
    private static ConstantThroughputTimer getConstantThroughputTimer(int throughputTimer) {
        ConstantThroughputTimer constantThroughputTimer = new ConstantThroughputTimer();
        constantThroughputTimer.setEnabled(true);
        constantThroughputTimer.setName("常数吞吐量定时器");
        constantThroughputTimer.setProperty(TestElement.TEST_CLASS, ConstantThroughputTimer.class.getName());
        constantThroughputTimer.setProperty(TestElement.GUI_CLASS, TestBeanGUI.class.getName());
        constantThroughputTimer.setCalcMode(ConstantThroughputTimer.Mode.AllActiveThreads.ordinal());

        constantThroughputTimer.setProperty(new IntegerProperty("calcMode", ConstantThroughputTimer.Mode.AllActiveThreads.ordinal()));
        DoubleProperty doubleProperty = new DoubleProperty();
        doubleProperty.setName("throughput");
        doubleProperty.setValue(throughputTimer * 60f);
        constantThroughputTimer.setProperty(doubleProperty);
        return constantThroughputTimer;
    }

    /**
     * 从结果文件读取响应内容
     * @param filePath
     * @return
     */
    private static JmeterGlobalStatEntity getResultMessageFromFile(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            return null;
        }
        List<LabelStatsEntity> statsEntityList = new ArrayList<>();
        try {
            // 1. 创建DocumentBuilderFactory对象
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 2. 创建DocumentBuilder对象
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 3. 解析XML文件，获取Document对象
            Document document = builder.parse(new File(filePath));
            // 4. 获取所有<httpSample>节点
            NodeList httpSampleList = document.getElementsByTagName("httpSample");
            // 初始化统计变量
            Map<String, LabelStats> labelStatsMap = new LinkedHashMap<>();
            List<HttpSample> samples = new ArrayList<>();
//            long startTime = Long.MAX_VALUE;
//            long endTime = Long.MIN_VALUE;
            long totalRequests = 0;
            long failedRequests = 0;
            long totalResponseTime = 0;
            long totalMinResponseTime = Long.MAX_VALUE;
            long totalMaxResponseTime = Long.MIN_VALUE;
            long totalTimeMillis = 0;
            for (int i = 0; i < httpSampleList.getLength(); i++) {
                Node httpSampleNode = httpSampleList.item(i);
                if (httpSampleNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element httpSampleElement = (Element) httpSampleNode;
                    // 提取字段
                    String label = httpSampleElement.getAttribute("lb");
                    boolean success = Boolean.parseBoolean(httpSampleElement.getAttribute("s"));
                    long responseTime = Long.parseLong(httpSampleElement.getAttribute("t"));
                    long lt = Long.parseLong(httpSampleElement.getAttribute("lt"));
                    long ct = Long.parseLong(httpSampleElement.getAttribute("ct"));
                    totalTimeMillis += responseTime + lt + ct;
//                    long timestamp = Long.parseLong(httpSampleElement.getAttribute("ts"));
                    long receivedBytes = Long.parseLong(httpSampleElement.getAttribute("by"));
                    long sentBytes = Long.parseLong(httpSampleElement.getAttribute("sby"));
                    String responseCode = httpSampleElement.getAttribute("rc");
                    samples.add(new HttpSample(label, success, responseCode));

                    // 更新全局统计
                    totalRequests++;
                    totalResponseTime += responseTime;
                    totalMinResponseTime = Math.min(totalMinResponseTime, responseTime);
                    totalMaxResponseTime = Math.max(totalMaxResponseTime, responseTime);
                    if (!success) {
                        failedRequests++;
                    }
//                    startTime = Math.min(startTime, timestamp);
//                    endTime = Math.max(endTime, timestamp);
                    // 更新按标签的统计
                    LabelStats stats = labelStatsMap.getOrDefault(label, new LabelStats());
                    stats.totalRequests++;
                    stats.totalResponseTime += responseTime;
                    stats.minResponseTime = Math.min(stats.minResponseTime, responseTime);
                    stats.maxResponseTime = Math.max(stats.maxResponseTime, responseTime);
                    stats.receivedBytes += receivedBytes;
                    stats.sentBytes += sentBytes;
                    if (!success) {
                        stats.failedRequests++;
                    }
                    labelStatsMap.put(label, stats);
                }
            }
            // 计算总时长（秒）
            double totalTimeInSeconds = totalTimeMillis / 1000.0;
//            double totalTimeInSeconds2 = (endTime - startTime) / 1000.0;

            // 输出汇总报告
            for (Map.Entry<String, LabelStats> entry : labelStatsMap.entrySet()) {
                String label = entry.getKey();
                LabelStats stats = entry.getValue();

                // 计算指标
                long average = stats.totalResponseTime / stats.totalRequests;
                double errorRate = (stats.failedRequests / (double) stats.totalRequests) * 100;
                double throughput = stats.totalRequests / totalTimeInSeconds;
                double receivedKBPerSec = (stats.receivedBytes / 1024.0) / totalTimeInSeconds;
                double sentKBPerSec = (stats.sentBytes / 1024.0) / totalTimeInSeconds;
                LabelStatsEntity labelStatsEntity = new LabelStatsEntity();
                labelStatsEntity.setLabel(label);
                labelStatsEntity.setSamples(stats.totalRequests);
                labelStatsEntity.setAverage(average);
                labelStatsEntity.setMin(stats.minResponseTime);
                labelStatsEntity.setMax(stats.maxResponseTime);
                labelStatsEntity.setErrorRate(errorRate);
                labelStatsEntity.setThroughput(throughput);
                labelStatsEntity.setReceivedKBPerSec(receivedKBPerSec);
                labelStatsEntity.setSentKBPerSec(sentKBPerSec);
                statsEntityList.add(labelStatsEntity);
            }

            // 输出全局汇总
            long globalResponseAverage = totalResponseTime / totalRequests;
            double globalErrorRate = (failedRequests / (double) totalRequests) * 100;
            double globalThroughput = totalRequests / totalTimeInSeconds;
            double globalReceivedKBPerSec = labelStatsMap.values().stream()
                    .mapToLong(stats -> stats.receivedBytes)
                    .sum() / 1024.0 / totalTimeInSeconds;
            double globalSentKBPerSec = labelStatsMap.values().stream()
                    .mapToLong(stats -> stats.sentBytes)
                    .sum() / 1024.0 / totalTimeInSeconds;

            LabelStatsEntity labelStatsEntity = new LabelStatsEntity();
            labelStatsEntity.setLabel("TOTAL");
            labelStatsEntity.setSamples(totalRequests);
            labelStatsEntity.setAverage(globalResponseAverage);
            labelStatsEntity.setMin(totalMinResponseTime);
            labelStatsEntity.setMax(totalMaxResponseTime);
            labelStatsEntity.setErrorRate(globalErrorRate);
            labelStatsEntity.setThroughput(globalThroughput);
            labelStatsEntity.setReceivedKBPerSec(globalReceivedKBPerSec);
            labelStatsEntity.setSentKBPerSec(globalSentKBPerSec);
            statsEntityList.add(labelStatsEntity);

            // 错误报告汇总
            HttpSampleAnalyzer analyzer = new HttpSampleAnalyzer(samples);
            List<ErrorCodeStat> errorCodeStatList = analyzer.analyzeErrorCodes();
            List<InterfaceErrorStat> top5InterfaceErrorStatList = analyzer.getTop5ErrorInterfaces();
            List<InterfaceErrorDetail> interfaceErrorDetailList = analyzer.getInterfaceErrorDetails();
            ErrorTotalStats errorTotalStats = new ErrorTotalStats();
            errorTotalStats.setErrorCodeStatList(errorCodeStatList);
            errorTotalStats.setTop5InterfaceErrorStatList(top5InterfaceErrorStatList);
            errorTotalStats.setInterfaceErrorDetailList(interfaceErrorDetailList);

            JmeterGlobalStatEntity globalStatEntity = new JmeterGlobalStatEntity();
            globalStatEntity.setStatsEntityList(statsEntityList);
            globalStatEntity.setErrorTotalStats(errorTotalStats);
            return globalStatEntity;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    static class LabelStats {
        long totalRequests = 0;
        long totalResponseTime = 0;
        long minResponseTime = Long.MAX_VALUE;
        long maxResponseTime = Long.MIN_VALUE;
        int failedRequests = 0;
        long receivedBytes = 0;
        long sentBytes = 0;
    }

    /**
     * 从响应头中读取Map信息结构
     * @param responseHeader
     * @return
     */
    public static Map<String, String> parseHeaders(String responseHeader) {
        Map<String, String> headerMap = new HashMap<>();
        if (responseHeader == null) {
            return headerMap;
        }
        // 按行拆分
        String[] lines = responseHeader.split("\n");
        // 遍历每一行
        for (String line : lines) {
            // 忽略空行和 HTTP 状态行
            if (line.trim().isEmpty() || line.startsWith("HTTP/")) {
                continue;
            }
            // 按冒号拆分键值对
            int colonIndex = line.indexOf(":");
            if (colonIndex > 0) {
                String key = line.substring(0, colonIndex).trim();
                String value = line.substring(colonIndex + 1).trim();
                headerMap.put(key, value);
            }
        }
        return headerMap;
    }

    /**
     * 根据 JSONPath 表达式从 JSON 中提取字段值
     *
     * @param json       JSON 字符串
     * @param expression JSONPath 表达式
     * @return 字段值，如果字段不存在则返回 null
     */
    public static String extractFieldValue(String json, String expression) {
        try {
            Object result = JsonPath.read(json, expression);
            return result != null ? result.toString() : null;
        } catch (PathNotFoundException e) {
            // 如果字段不存在，返回 null
            return null;
        }
    }

    public static void main(String[] args) {
//        String s = "[{\"key\":\"authorization\",\"value\":\"Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjhkZTZlMWYzLTU0YjMtNGM5MC05YTczLTA0NDkxYmE2NTZlNiJ9.oepUXspCPm6Gjjz3pXbs4O87p3ByemxxhRh5HXUFGK2x-lDb2uxdSRfITiE9LeDYQQNTD6UPYKPda2PWLyAUoA\"},[{\"key\":\"\",\"value\":\"\"}]]";
//        s = s.replaceAll(",\\s*\\[\\{\"key\":\"\",\"value\":\"\"\\}]", "");
//        Gson gson = new Gson();
//        // 定义类型
//        Type type = new TypeToken<List<Map<String, String>>>() {}.getType();
//        gson.fromJson(s, type);
        String paramJson = "{\"md5Value\":\"value1\",\"fileName\":\"value2\"}";
        paramJson = "{\"name\":\"John\",\"city\":\"New York\",\"age\":30}";
        String requestHeader = "{\"Content-Type\":\"application/json; charset=UTF-8\",\"Authorization\":\"Bearer token123\"}";
        String jmeterHomePath = "D:/apache-jmeter-5.4.3";
//        String result = getJmeterResult("http://127.0.0.1:3000/api/items/add", 3000, "POST", paramJson, requestHeader, jmeterHomePath);
//        getJmeterResult(123L, "http://127.0.0.1:3000/api/items/user", 3000, "GET", paramJson, requestHeader, jmeterHomePath);
//        System.out.println(result);
    }
}
