package com.test.test.service.impl;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.test.common.core.domain.model.*;
import com.test.common.utils.DateUtils;
import com.test.common.utils.JMeterGroupUtil;
import com.test.common.utils.SecurityUtils;
import com.test.common.utils.StringUtils;
import com.test.test.domain.PerformanceTest;
import com.test.test.domain.PerformanceTestCase;
import com.test.test.domain.PerformanceTestCaseReport;
import com.test.test.domain.TestCaseStep;
import com.test.test.domain.qo.ExtractionRule;
import com.test.test.mapper.PerformanceTestCaseMapper;
import com.test.test.mapper.PerformanceTestCaseReportMapper;
import com.test.test.mapper.PerformanceTestMapper;
import com.test.test.service.IPerformanceTestCaseReportService;
import com.test.test.service.ITestCaseStepService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 * 性能测试用例报告Service业务层处理
 *
 * @author test
 * @date 2025-04-14
 */
@Slf4j
@Service
public class PerformanceTestCaseReportServiceImpl implements IPerformanceTestCaseReportService
{
    @Resource
    private PerformanceTestCaseReportMapper performanceTestCaseReportMapper;
    @Resource
    private PerformanceTestCaseMapper performanceTestCaseMapper;
    @Resource
    private PerformanceTestMapper performanceTestMapper;

    @Autowired
    private ITestCaseStepService testCaseStepService;

    @Override
    public Long executePerformanceTestAndReport(Long id, String jmeterHomePath, Integer triggerType) {
        Long sid = System.currentTimeMillis();
        PerformanceTest performanceTest = performanceTestMapper.selectPerformanceTestById(id);
        PerformanceTestCase performanceTestCase = new PerformanceTestCase();
        performanceTestCase.setPerformanceId(id);
        performanceTestCase.setStatus(1);
        List<PerformanceTestCase> relateTestCaseList = performanceTestCaseMapper.selectPerformanceTestCaseList(performanceTestCase);
        for (PerformanceTestCase relateTestCase : relateTestCaseList) {
            JmeterGroupRequest jmeterGroupRequest = new JmeterGroupRequest();
            jmeterGroupRequest.setTestCaseId(relateTestCase.getTestCaseId());
            jmeterGroupRequest.setSid(sid);
            jmeterGroupRequest.setConcurrentThreads(performanceTest.getConcurrentThreads());
            jmeterGroupRequest.setErrorOperType(performanceTest.getErrorOperType());
            jmeterGroupRequest.setExecuteType(performanceTest.getExecuteType());
            jmeterGroupRequest.setRampUpSeconds(performanceTest.getRampUpSeconds());
            Long seconds = performanceTest.getPressureHour() * 3600L + performanceTest.getPressureMinute() * 60L + performanceTest.getPressureSecond() * 1L;
            jmeterGroupRequest.setPressureSecond(seconds);
            jmeterGroupRequest.setLoopCount(performanceTest.getLoopCount());
            jmeterGroupRequest.setRpsStatus(performanceTest.getRpsStatus());
            jmeterGroupRequest.setRpsLimit(performanceTest.getRpsLimit());
            jmeterGroupRequest.setJmeterHomePath(jmeterHomePath);
            List<TestCaseStep> testCaseStepList = testCaseStepService.selectTestCaseStepListByCaseId(relateTestCase.getTestCaseId());
            List<JmeterRequest> jmeterRequestList = dealAddTestCaseHttpStep(testCaseStepList);
            jmeterGroupRequest.setJmeterRequestList(jmeterRequestList);
            Date startTime = new Date();
            JmeterGlobalStatEntity jmeterGlobalStatEntity = JMeterGroupUtil.getJmeterResult(jmeterGroupRequest);
            List<LabelStatsEntity> jmeterResultList = jmeterGlobalStatEntity.getStatsEntityList();
            ErrorTotalStats errorTotalStats = jmeterGlobalStatEntity.getErrorTotalStats();
            Date endTime = new Date();
            Gson gson = new GsonBuilder()
                    .serializeSpecialFloatingPointValues()
                    .create();
            if (!CollectionUtils.isEmpty(jmeterResultList)) {
                LabelStatsEntity lastElement = jmeterResultList.get(jmeterResultList.size() - 1);
                PerformanceTestCaseReport performanceTestCaseReport = new PerformanceTestCaseReport();
                performanceTestCaseReport.setPerformanceId(id);
                performanceTestCaseReport.setTestCaseId(relateTestCase.getTestCaseId());
                performanceTestCaseReport.setSid(sid);
                performanceTestCaseReport.setConcurrentThreads(performanceTest.getConcurrentThreads());
                performanceTestCaseReport.setAverage(lastElement.getAverage());
                performanceTestCaseReport.setTps(String.format(Locale.US, "%.1f", lastElement.getThroughput()));
                performanceTestCaseReport.setStartTime(startTime);
                performanceTestCaseReport.setEndTime(endTime);
                performanceTestCaseReport.setCostTime(endTime.getTime() - startTime.getTime());
                performanceTestCaseReport.setTriggerType(triggerType);
                performanceTestCaseReport.setSummaryReport(gson.toJson(jmeterResultList));
                performanceTestCaseReport.setErrorReport(gson.toJson(errorTotalStats));
                performanceTestCaseReport.setStatus("1");
                LoginUser user = null;
                try {
                    user = SecurityUtils.getLoginUser();
                } catch (Exception e) {}
                if (user != null) {
                    performanceTestCaseReport.setCreateBy(user.getUsername());
                }
                performanceTestCaseReport.setCreateTime(endTime);
                performanceTestCaseReportMapper.insertPerformanceTestCaseReport(performanceTestCaseReport);
            } else {
                log.error(performanceTest.getPerformanceName() + "Jmeter执行性能测试无法获取到汇总报告！！！");
            }

        }
        performanceTest.setStatus("1");
        performanceTest.setUpdateTime(new Date());
        performanceTestMapper.updatePerformanceTest(performanceTest);
        return sid;
    }

    /**
     * 新增http步骤测试接口到待性能测试列表
     * @param testCaseStepList
     * @return
     */
    private List<JmeterRequest> dealAddTestCaseHttpStep(List<TestCaseStep> testCaseStepList) {
        List<JmeterRequest> jmeterRequestList = new ArrayList<>();
        for (TestCaseStep testCaseStep : testCaseStepList) {
            if (testCaseStep.getType() == 1L) {
                // http接口处理
                JmeterRequest jmeterRequest = doHttpRequestTestAdd(testCaseStep);
                if (jmeterRequest != null) {
                    jmeterRequestList.add(jmeterRequest);
                    log.info("用例步骤Http接口:{}新增待性能测试列表成功！", testCaseStep.getName());
                }
            }
        }
        return jmeterRequestList;
    }

    /**
     * 处理http接口测试新增
     * @param testCaseStep
     * @return JmeterRequest
     */
    private JmeterRequest doHttpRequestTestAdd(TestCaseStep testCaseStep) {
        String url = testCaseStep.getRequestUrl();
        String method = testCaseStep.getRequestMethod().toUpperCase();
        if (!method.equals("GET") && !method.equals("POST")) {
            log.error("不支持的请求方式：{}", method);
            return null;
        }
        if (!url.startsWith("http")) {
            String apiProtocol = testCaseStep.getApiProtocol();
            String appendUrl = apiProtocol + "://" + testCaseStep.getApiHost();
            if (testCaseStep.getApiPort() != null) {
                url = appendUrl + ":" + testCaseStep.getApiPort() + url;
            } else {
                url = appendUrl + url;
            }
        }
        JmeterRequest jmeterRequest = new JmeterRequest();
        jmeterRequest.setTestCaseName(testCaseStep.getName());
        jmeterRequest.setUrl(url);
        jmeterRequest.setPort(testCaseStep.getApiPort());
        jmeterRequest.setMethod(testCaseStep.getRequestMethod());
        jmeterRequest.setRequestBody(testCaseStep.getRequestBody());
        jmeterRequest.setRequestParams(testCaseStep.getRequestParams());
        jmeterRequest.setRequestHeader(testCaseStep.getRequestHeader());
        // Json提取表达式
        String assignment = testCaseStep.getAssignment();
        if (!StringUtils.isEmpty(assignment) && !"[]".equals(assignment)) {
            Gson gson = new Gson();
            Type ruleListType = new TypeToken<List<ExtractionRule>>() {}.getType();
            List<ExtractionRule> rules = gson.fromJson(assignment, ruleListType);
            if (!CollectionUtils.isEmpty(rules)) {
                List<String> extractionRuleList = new ArrayList<>();
                for (ExtractionRule rule : rules) {
                    extractionRuleList.add(rule.getName() + "," + rule.getPath());
                    jmeterRequest.setExtractionRuleList(extractionRuleList);
                }
            }
        }
        log.info("getRequestHeader:{}", jmeterRequest.getRequestHeader());
        return jmeterRequest;
    }

    /**
     * 查询性能测试用例报告
     *
     * @param id 性能测试用例报告主键
     * @return 性能测试用例报告
     */
    @Override
    public PerformanceTestCaseReport selectPerformanceTestCaseReportById(Long id)
    {
        return performanceTestCaseReportMapper.selectPerformanceTestCaseReportById(id);
    }

    /**
     * 查询性能测试用例报告列表
     *
     * @param performanceTestCaseReport 性能测试用例报告
     * @return 性能测试用例报告
     */
    @Override
    public List<PerformanceTestCaseReport> selectPerformanceTestCaseReportList(PerformanceTestCaseReport performanceTestCaseReport)
    {
        return performanceTestCaseReportMapper.selectPerformanceTestCaseReportList(performanceTestCaseReport);
    }

    /**
     * 新增性能测试用例报告
     *
     * @param performanceTestCaseReport 性能测试用例报告
     * @return 结果
     */
    @Override
    public int insertPerformanceTestCaseReport(PerformanceTestCaseReport performanceTestCaseReport)
    {
        performanceTestCaseReport.setCreateTime(DateUtils.getNowDate());
        return performanceTestCaseReportMapper.insertPerformanceTestCaseReport(performanceTestCaseReport);
    }

    /**
     * 修改性能测试用例报告
     *
     * @param performanceTestCaseReport 性能测试用例报告
     * @return 结果
     */
    @Override
    public int updatePerformanceTestCaseReport(PerformanceTestCaseReport performanceTestCaseReport)
    {
        performanceTestCaseReport.setUpdateTime(DateUtils.getNowDate());
        return performanceTestCaseReportMapper.updatePerformanceTestCaseReport(performanceTestCaseReport);
    }

    /**
     * 批量删除性能测试用例报告
     *
     * @param ids 需要删除的性能测试用例报告主键
     * @return 结果
     */
    @Override
    public int deletePerformanceTestCaseReportByIds(Long[] ids)
    {
        return performanceTestCaseReportMapper.deletePerformanceTestCaseReportByIds(ids);
    }

    /**
     * 删除性能测试用例报告信息
     *
     * @param id 性能测试用例报告主键
     * @return 结果
     */
    @Override
    public int deletePerformanceTestCaseReportById(Long id)
    {
        return performanceTestCaseReportMapper.deletePerformanceTestCaseReportById(id);
    }
}
