package cd.casic.ci.process.process.service.report.impl;

import cd.casic.ci.process.dto.req.report.ReportAssetTaskReq;
import cd.casic.ci.process.dto.req.report.ReportDeleteReq;
import cd.casic.ci.process.dto.req.report.ReportInfoQueryReq;
import cd.casic.ci.process.dto.resp.report.*;
import cd.casic.ci.process.engine.context.ConstantContextHolder;
import cd.casic.ci.process.process.converter.PipReportInfoConverter;
import cd.casic.ci.process.process.dao.pipeline.PipTaskDao;
import cd.casic.ci.process.process.dao.pipeline.PipelineDao;
import cd.casic.ci.process.process.dao.report.ReportInfoDao;
import cd.casic.ci.process.process.dataObject.base.BaseIdPageReq;
import cd.casic.ci.process.process.dataObject.base.BaseIdReq;
import cd.casic.ci.process.process.dataObject.pipeline.PipPipeline;
import cd.casic.ci.process.process.dataObject.report.PipReportInfo;
import cd.casic.ci.process.process.dataObject.task.PipTask;
import cd.casic.ci.process.process.service.report.ReportService;
import cd.casic.ci.process.util.WebFrameworkUtils;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import cd.casic.framework.commons.pojo.PageResult;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

import static cd.casic.ci.process.engine.worker.base.HttpWorker.getRestTemplateWithoutSANCheck;

/**
 * @author HopeLi
 * @version v1.0
 * @ClassName TargetVersionServiceImpl
 * @Date: 2025/5/17 15:20
 * @Description:
 */
@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Resource
    private ReportInfoDao reportInfoDao;

    @Resource
    private PipTaskDao pipTaskDao;

    @Resource
    private PipelineDao pipelineDao;

    public static final String PATH = "/openapi/v1/asset/report/downLoadReport/batch";

    @Override
    public PageResult<ReportResp> findReportList(BaseIdPageReq req) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        RestTemplate restTemplate = getRestTemplateWithoutSANCheck();
        String reportFindUrl = ConstantContextHolder.getScaIp() + "/openapi/v1/asset/report/list";
        String body = buildFindRequestBody(req);
        HttpHeaders headers = createHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);

        log.info("报告分页查询接口:" + reportFindUrl);
        JSONObject response = restTemplate.postForObject(reportFindUrl, requestEntity, JSONObject.class);
        String message = response.getString("message");
        if (message.equals("success")) {
            List<ReportResp> respList = new ArrayList<>();
            log.info("===============报告分页查询接口成功=================");
            JSONObject data = response.getJSONObject("data");
            setReportFindResp(data,response.getString("xmTraceId"),respList);

            PageResult<ReportResp> pageResult = new PageResult<>(respList,data.getLong("total"),data.getLong("pageNum"),data.getLong("pageSize"));
            return pageResult;

        } else {
            log.error("===============报告分页查询接口失败=================");
            return new PageResult<>();
        }
    }



    @Override
    public ReportResp deleteReport(ReportDeleteReq req) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        RestTemplate restTemplate = getRestTemplateWithoutSANCheck();
        String reportDeleteUrl = ConstantContextHolder.getScaIp() + "/openapi/v1/asset/report/delete";
        String body = buildDeleteRequestBody(req);
        HttpHeaders headers = createHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);

        log.info("报告删除接口:" + reportDeleteUrl);
        JSONObject response = restTemplate.postForObject(reportDeleteUrl, requestEntity, JSONObject.class);
        String message = response.getString("message");
        if (message.equals("success")) {
            ReportResp reportResp = new ReportResp();
            log.info("===============报告删除接口成功=================");
            JSONObject data = response.getJSONObject("data");
            setReportDeleteResp(data,response.getString("xmTraceId"),reportResp);

            return reportResp;

        } else {
            log.error("===============报告删除接口失败=================");
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"删除报告失败");
        }
    }



    @Override
    public ResponseEntity<String> downLoadReport(BaseIdReq req) throws Exception {
        RestTemplate restTemplate = getRestTemplateWithoutSANCheck();
        String reportDeleteUrl = ConstantContextHolder.getScaIp() + PATH;
        String body = buildDownloadRequestBody(req);
        HttpHeaders headers = createHeaders();
        restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter());
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);

        log.info("报告下载接口:" + reportDeleteUrl);
        ResponseEntity<byte[]> responseEntity = restTemplate.postForEntity(reportDeleteUrl, requestEntity, byte[].class);

        if (responseEntity.getStatusCode() == HttpStatus.OK && responseEntity.hasBody()) {
            log.info("===============报告下载接口成功=================");

            byte[] responseBody = responseEntity.getBody();
            String base64ResponseBody = Base64.getEncoder().encodeToString(responseBody);
            // 构建返回给前端的 ResponseEntity<byte[]>
            // 返回MIME类型:ml-citation{ref="5" data="citationList"}
            Optional<FileType> detect = detect(responseBody);
            FileType fileType = detect.get();
            System.out.println(fileType.extension);
            // 可选：转换为扩展名
            return ResponseEntity.ok()
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=report."+fileType.extension)
                    .body(base64ResponseBody);
        }else {
            log.error("===============报告下载接口失败=================");
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "删除报告失败");
        }
    }

    @Override
    public ReportResp assetReportTask(ReportAssetTaskReq req) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        if (ObjectUtils.isEmpty(req.getScaTaskId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"任务ID不能为空");
        }
        RestTemplate restTemplate = getRestTemplateWithoutSANCheck();
        String reportDeleteUrl = ConstantContextHolder.getScaIp() + "/openapi/v1/asset/report/task";
        String body = buildAssetRequestBody(req);
        HttpHeaders headers = createHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);

        log.info("根据任务ID列表生成检测报告:" + reportDeleteUrl);
        JSONObject response = restTemplate.postForObject(reportDeleteUrl, requestEntity, JSONObject.class);
        String message = response.getString("message");
        ReportResp reportResp = new ReportResp();
        if (message.equals("success")) {
            log.info("===============根据任务ID列表生成检测报告成功=================");
            setReportAssetResp(response.getString("xmTraceId"),response.getInteger("data"),reportResp);

            return reportResp;

        } else {
            reportResp.setMessage(message);
            log.error("===============根据任务ID列表生成检测报告失败=================");
            return reportResp;
        }
    }

    @Override
    public ReportTaskResp findByScaTaskId(String taskId) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        RestTemplate restTemplate = getRestTemplateWithoutSANCheck();
        String reportFindTaskUrl = ConstantContextHolder.getScaIp() + "/openapi/v1/task/{taskId}";

        // 构建带有查询参数的 URL
        String urlWithParams = UriComponentsBuilder.fromHttpUrl(reportFindTaskUrl).buildAndExpand(taskId).toUriString();

        HttpHeaders headers = createHeaders();

        HttpEntity<Void> requestEntity = new HttpEntity<>(headers);

        log.info("根据taskId查询报告接口（GET）: " + urlWithParams);
        ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.exchange(urlWithParams, HttpMethod.GET,requestEntity,JSONObject.class);

        if (ObjectUtils.isEmpty(jsonObjectResponseEntity.getBody())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"查询报告失败");
        }

        JSONObject response = jsonObjectResponseEntity.getBody();

        String message = response.getString("message");
        if ("success".equals(message)) {
            ReportTaskResp taskResp = new ReportTaskResp();
            log.info("===============根据taskId查询报告接口成功=================");
            JSONObject data = response.getJSONObject("data");
            setFindReportTaskResp(data, response.getString("xmTraceId"), taskResp);
            return taskResp;
        } else {
            log.error("===============根据taskId查询报告接口失败=================");
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "根据taskId查询报告失败");
        }
    }

    @Override
    public void createVulListByScaTaskId(BaseIdReq req) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        if (ObjectUtils.isEmpty(req.getTaskId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"任务ID不能为空");
        }
        if (ObjectUtils.isEmpty(req.getScaTaskId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"scaTaskId不能为空");
        }

        RestTemplate restTemplate = getRestTemplateWithoutSANCheck();
        String reportDeleteUrl = ConstantContextHolder.getScaIp() + "/openapi/v1/task/vul/list";
        JSONObject json = new JSONObject();
        json.put("taskId", Integer.parseInt(req.getScaTaskId()));
        String body = json.toJSONString();

        HttpHeaders headers = createHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);

        log.info("根据任务ID查询漏洞列表:" + reportDeleteUrl);
        JSONObject response = restTemplate.postForObject(reportDeleteUrl, requestEntity, JSONObject.class);
        String message = response.getString("message");
        if (message.equals("success")) {
            log.info("===============根据任务ID查询漏洞列表成功=================");
            JSONObject data = response.getJSONObject("data");

            //映射到报告信息表中去，做存储操作
            List<PipReportInfo> infoList = setReportInfoToCreate(data,req.getScaTaskId(),req.getTaskId());

            if (!CollectionUtils.isEmpty(infoList)){
                reportInfoDao.insertBatch(infoList);
            }
        } else {
            log.error("===============根据任务ID查询漏洞列表失败，新增报告信息失败=================");
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"新增报告信息失败");
        }
    }

    @Override
    public ReportInfoConsoleSumResp findInfoConsoleSum() {
        ReportInfoConsoleSumResp resp = new ReportInfoConsoleSumResp();
        List<PipReportInfo> infoList = reportInfoDao.selectList(new QueryWrapper<>());

        if (!CollectionUtils.isEmpty(infoList)){
            //根据日期进行过滤计算
            List<PipReportInfo> todayReportInfoList = infoList.stream().filter(info -> info.getCreateTime().toLocalDate().isEqual(LocalDate.now())).toList();
            //今日新增总数量
            resp.setNewlyIncreasedRiskCount(todayReportInfoList.size());

            List<PipReportInfo> highRickReportInfoLIst = todayReportInfoList.stream().filter(info -> 2 == info.getSecurityLevelId()).toList();
            //今日高危新增总数量
            resp.setNewlyIncreasedHighRiskSum(highRickReportInfoLIst.size());

            //总漏洞数量
            resp.setRiskCount(infoList.size());

            //总高危漏洞数量
            List<PipReportInfo> highRickReportSum = infoList.stream().filter(info -> 2 == info.getSecurityLevelId()).toList();
            resp.setHighRiskSum(highRickReportSum.size());
        }
        return resp;
    }

    @Override
    public List<ReportInfoConsoleResp> findInfoConsole(ReportInfoQueryReq query) {
        List<ReportInfoConsoleResp> respList = new ArrayList<>();

        QueryWrapper<PipReportInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("creator", Objects.requireNonNull(WebFrameworkUtils.getLoginUserId()).toString());
        List<PipReportInfo> infoList = reportInfoDao.selectList(wrapper);

        if (CollectionUtils.isEmpty(infoList)){
            return new ArrayList<>();
        }

        List<String> distinctTaskIds = infoList.stream().map(PipReportInfo::getTaskId).distinct().toList();

        //根据taskId查询对应的流水线信息名称
        // 1.查询PipTask列表
        List<PipTask> taskList = pipTaskDao.selectList(new QueryWrapper<PipTask>().in("id", distinctTaskIds));

        // 2.转换taskList为id:taskName的map
        Map<String, String> taskIdToNameMap = taskList.stream()
                .collect(Collectors.toMap(
                        PipTask::getId,
                        PipTask::getTaskName,
                        (existing, replacement) -> existing
                ));

        // 3.提取pipelineId列表
        Set<String> pipelineIdSet = taskList.stream()
                .map(PipTask::getPipelineId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        // 4.查询PipPipeline列表并转成map: pipelineId -> pipelineName
        Map<String, String> pipelineMap = pipelineDao.selectList(
                        new QueryWrapper<PipPipeline>().in("id", pipelineIdSet))
                .stream()
                .collect(Collectors.toMap(
                        PipPipeline::getId,
                        PipPipeline::getName,
                        (existing, replacement) -> existing // 遇到重复 key 保留第一个
                ));

        // 5.构建taskId -> pipelineName映射
        Map<String, String> taskMap = taskList.stream()
                .collect(Collectors.toMap(
                        PipTask::getId,
                        task -> pipelineMap.getOrDefault(task.getPipelineId(), "数据错误")
                ));

        // 6.根据pipelineName+taskName统计漏洞信息
        taskMap.forEach((taskId, pipelineName) -> {
            ReportInfoConsoleResp resp = new ReportInfoConsoleResp();
            resp.setPipelineName(pipelineName);
            resp.setTaskId(taskId);
            resp.setTaskName(taskIdToNameMap.get(taskId));

            //计算高中低危的总数量
            List<PipReportInfo> nowTaskReportInfo = infoList.stream().filter(info -> taskId.equals(info.getTaskId())).toList();
            resp.setHighRiskCount(nowTaskReportInfo.stream().filter(info -> 2 == info.getSecurityLevelId()).toList().size());
            resp.setPoorRiskCount(nowTaskReportInfo.stream().filter(info -> 3 == info.getSecurityLevelId()).toList().size());
            resp.setLowRiskCount(nowTaskReportInfo.stream().filter(info -> 4 == info.getSecurityLevelId()).toList().size());
            resp.setRiskCount(nowTaskReportInfo.size());
            respList.add(resp);
        });

        return respList;
    }

    @Override
    public PageResult<ReportInfoResp> findReportInfo(ReportInfoQueryReq query) {
        QueryWrapper<PipReportInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("taskId", query.getTaskId());
        Page<PipReportInfo> pipReportInfoPage = reportInfoDao.selectPage(new Page<>(query.getPageNo(), query.getPageSize()), wrapper);
        if (ObjectUtils.isEmpty(pipReportInfoPage)){
            return new PageResult<>();
        }

        if (CollectionUtils.isEmpty(pipReportInfoPage.getRecords())){
            return new PageResult<>();
        }

        List<ReportInfoResp> respList = PipReportInfoConverter.INSTANCE.toRespList(pipReportInfoPage.getRecords());
        return new PageResult<>(respList,pipReportInfoPage.getTotal(),pipReportInfoPage.getCurrent(),pipReportInfoPage.getSize());
    }


    private HttpHeaders createHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.add("OpenApiUserToken", ConstantContextHolder.getScaToken());
        return headers;
    }

    private String buildFindRequestBody(BaseIdPageReq req) {
        JSONObject json = new JSONObject();
        if (req.getProjectId() != null) {
            json.put("projectId", req.getProjectId());
        }
        json.put("pageNum", req.getPageNo());
        json.put("pageSize", req.getPageSize());
        return json.toJSONString();
    }

    private String buildDeleteRequestBody(ReportDeleteReq req) {
        JSONObject json = new JSONObject();

        json.put("endDate", req.getEndDate());
        json.put("name", req.getName());
        json.put("projectIdList", req.getProjectIdList());
        json.put("reportId", req.getReportId());
        json.put("sourceCode", req.getSourceCode());
        json.put("startDate", req.getStartDate());
        json.put("status", req.getStatus());
        json.put("type", req.getType());
        json.put("use", req.getUse());

        return json.toJSONString();
    }

    private String buildDownloadRequestBody(BaseIdReq req) {
        JSONObject json = new JSONObject();
        json.put("reportIds", req.getReportIds());
        return json.toJSONString();
    }


    private String buildAssetRequestBody(ReportAssetTaskReq req) {
        JSONObject json = new JSONObject();

        if (req.getAdvancedSearch() != null) {
            json.put("advancedSearch", JSONObject.toJSONString(req.getAdvancedSearch()));

        }
        json.put("dimension", req.getDimension());
        json.put("reportTemplateId", req.getReportTemplateId());
        json.put("type", req.getType());
        json.put("reportName", req.getReportName());
        json.put("scaTaskId", req.getScaTaskId());

        return json.toJSONString();
    }


    private void setReportFindResp(JSONObject data, String xmTraceId, List<ReportResp> respList) {
        JSONArray records = data.getJSONArray("records");
        for (int i = 0; i < records.size(); i++) {
            JSONObject report = records.getJSONObject(i);
            ReportResp reportResp = new ReportResp();

            reportResp.setId(report.getInteger("id"));
            reportResp.setCreateDate(report.getString("createDate"));
            reportResp.setCreator(report.getString("creator"));
            reportResp.setDimension(report.getInteger("dimension"));
            reportResp.setMd5(report.getString("md5"));
            reportResp.setName(report.getString("name"));
            reportResp.setProjectName(report.getString("projectName"));
            reportResp.setSerialNumber(report.getString("serialNumber"));
            reportResp.setSource(report.getInteger("source"));
            reportResp.setSourceName(report.getString("sourceName"));
            reportResp.setStatus(report.getInteger("status"));

            reportResp.setXmTraceId(xmTraceId);

            List<Integer> typeList = new ArrayList<>();
            JSONArray typeArray = report.getJSONArray("type");
            for (int j = 0; j < typeArray.size(); j++) {
                typeList.add(typeArray.getInteger(j));
            }
            reportResp.setType(typeList);

            respList.add(reportResp);
        }
    }


    private void setReportDeleteResp(JSONObject data, String xmTraceId, ReportResp reportResp) {
        reportResp.setFail(data.getInteger("fail"));
        reportResp.setSuccess(data.getInteger("success"));
        reportResp.setXmTraceId(xmTraceId);
    }

    private void setReportAssetResp(String xmTraceId, Integer data, ReportResp reportResp) {
        reportResp.setXmTraceId(xmTraceId);
        reportResp.setMessage("success");
        reportResp.setId(data);
    }


    private void setFindReportTaskResp(JSONObject data, String xmTraceId, ReportTaskResp taskResp) {
        if (data == null) {
            throw new IllegalArgumentException("data 不能为空");
        }

        taskResp.setApplicationId(data.getInteger("applicationId"));
        taskResp.setComponentAuditNum(data.getInteger("componentAuditNum"));
        taskResp.setComponentBlackNum(data.getInteger("componentBlackNum"));
        taskResp.setComponentHighNum(data.getInteger("componentHighNum"));
        taskResp.setComponentLowNum(data.getInteger("componentLowNum"));
        taskResp.setComponentMediumNum(data.getInteger("componentMediumNum"));
        taskResp.setComponentNormalNum(data.getInteger("componentNormalNum"));
        taskResp.setComponentNum(data.getInteger("componentNum"));
        taskResp.setComponentPoisonNum(data.getInteger("componentPoisonNum"));
        taskResp.setComponentSeriousNum(data.getInteger("componentSeriousNum"));
        taskResp.setComponentUnAuditNum(data.getInteger("componentUnAuditNum"));
        taskResp.setComponentWhiteNum(data.getInteger("componentWhiteNum"));

        taskResp.setDetectEndTime(data.getString("detectEndTime"));
        taskResp.setDetectStartTime(data.getString("detectStartTime"));
        taskResp.setDetectTime(data.getString("detectTime"));

        // 镜像分层信息：解析 JSONArray 到 List<ImageLayerInfo>
        JSONArray imageLayerArray = data.getJSONArray("imageLayerInfos");
        List<ImageLayerInfo> imageLayerInfos = new ArrayList<>();
        if (imageLayerArray != null && !imageLayerArray.isEmpty()) {
            for (int i = 0; i < imageLayerArray.size(); i++) {
                JSONObject layerObj = imageLayerArray.getJSONObject(i);
                ImageLayerInfo layerInfo = new ImageLayerInfo();

                layerInfo.setBasicLayer(layerObj.getString("basicLayer"));
                layerInfo.setCommand(layerObj.getString("command"));
                layerInfo.setCommandInstall(layerObj.getBoolean("commandInstall"));
                layerInfo.setLayerId(layerObj.getString("layerId"));
                layerInfo.setLayerIndex(layerObj.getInteger("layerIndex"));

                imageLayerInfos.add(layerInfo);
            }
        }
        taskResp.setImageLayerInfos(imageLayerInfos);

        taskResp.setLicenseAuditNum(data.getInteger("licenseAuditNum"));
        taskResp.setLicenseBlackNum(data.getInteger("licenseBlackNum"));
        taskResp.setLicenseHighNum(data.getInteger("licenseHighNum"));
        taskResp.setLicenseLowNum(data.getInteger("licenseLowNum"));
        taskResp.setLicenseMediumNum(data.getInteger("licenseMediumNum"));
        taskResp.setLicenseNum(data.getInteger("licenseNum"));
        taskResp.setLicenseUnAuditNum(data.getInteger("licenseUnAuditNum"));
        taskResp.setLicenseWhiteNum(data.getInteger("licenseWhiteNum"));

        taskResp.setProjectId(data.getInteger("projectId"));
        taskResp.setStatus(data.getInteger("status"));
        taskResp.setTaskId(data.getInteger("taskId"));

        taskResp.setVulAuditNum(data.getInteger("vulAuditNum"));
        taskResp.setVulBlackNum(data.getInteger("vulBlackNum"));
        taskResp.setVulHighNum(data.getInteger("vulHighNum"));
        taskResp.setVulLowNum(data.getInteger("vulLowNum"));
        taskResp.setVulMediumNum(data.getInteger("vulMediumNum"));
        taskResp.setVulNum(data.getInteger("vulNum"));
        taskResp.setVulSeriousNum(data.getInteger("vulSeriousNum"));
        taskResp.setVulUnAuditNum(data.getInteger("vulUnAuditNum"));
        taskResp.setVulWhiteNum(data.getInteger("vulWhiteNum"));

        taskResp.setXmTraceId(xmTraceId);
    }


    private List<PipReportInfo> setReportInfoToCreate(JSONObject data,String scaTaskId,String taskId) {
        List<PipReportInfo> pipReportInfos = new ArrayList<>();
        JSONArray records = data.getJSONArray("records");

        String creator = "";
        //根据taskId查询流水线信息并且设置漏洞归属人
        PipTask pipTask = pipTaskDao.selectById(taskId);
        if (!ObjectUtils.isEmpty(pipTask)){
            PipPipeline pipeline = pipelineDao.selectById(pipTask.getPipelineId());
            creator = pipeline.getCreator();
        }

        if (!ObjectUtils.isEmpty(records)){
            for (int i = 0; i < records.size(); i++) {
                JSONObject report = records.getJSONObject(i);
                PipReportInfo pipReportInfo = new PipReportInfo();

                pipReportInfo.setTaskId(taskId);
                pipReportInfo.setScaTaskId(scaTaskId);
                pipReportInfo.setSecurityLevelId(report.getInteger("securityLevelId"));
                pipReportInfo.setVulName(report.getString("vulName"));
                pipReportInfo.setCveId(report.getString("cveId"));
                pipReportInfo.setCweId(report.getString("cweId"));
                pipReportInfo.setCnnvdId(report.getString("cnnvdId"));
                pipReportInfo.setCnvdId(report.getString("cnvdId"));
                pipReportInfo.setVulType(report.getString("vulType"));
                pipReportInfo.setVulMarkStatus(report.getString("vulMarkStatus"));
                pipReportInfo.setAttackType(report.getString("attackType"));
                pipReportInfo.setCvssV2Score(report.getDouble("cvssV2Score"));
                pipReportInfo.setCvssV3Score(report.getDouble("cvssV3Score"));
                pipReportInfo.setExploitLevelIndex(report.getInteger("exploitLevelIndex"));
                pipReportInfo.setReleaseDate(report.getString("releaseDate"));
                pipReportInfo.setCreator(creator);
                pipReportInfos.add(pipReportInfo);
            }
            return pipReportInfos;
        }else {
            return new ArrayList<>();
        }
    }


    public enum FileType {
        // 文档类
        XLSX("xlsx", "Excel", new byte[]{0x50, 0x4B, 0x03, 0x04}),
        DOCX("docx", "Word", new byte[]{0x50, 0x4B, 0x03, 0x04}),
        PDF("pdf", "PDF", new byte[]{0x25, 0x50, 0x44, 0x46}),

        // 图片类
        PNG("png", "PNG", new byte[]{-119, 0x50, 0x4E, 0x47}),
        JPEG("jpg", "JPEG", new byte[]{-1, -40, -1, -32}),

        // 压缩包
        ZIP("zip", "ZIP", new byte[]{0x50, 0x4B, 0x03, 0x04}),
        RAR("rar", "RAR", new byte[]{0x52, 0x61, 0x72, 0x21});

        private final String extension;
        private final String description;
        private final byte[] magicNumber;

        FileType(String ext, String desc, byte[] magic) {
            this.extension = ext;
            this.description = desc;
            this.magicNumber = magic;
        }
    }

    public static Optional<FileType> detect(byte[] header) throws Exception {
        for (FileType type : FileType.values()) {
            if (header.length >= type.magicNumber.length) {
                boolean match = true;
                for (int i = 0; i < type.magicNumber.length; i++) {
                    if (header[i] != type.magicNumber[i]) {
                        match = false;
                        break;
                    }
                }
                if (match) return Optional.of(type);
            }
        }
        return Optional.empty();
    }

}
