package com.inspect.partrolresult.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.inspect.analysis.domain.AlgValue;
import com.inspect.analysis.domain.AnalyseResPoint;
import com.inspect.analysis.domain.ResultAnalysis;
import com.inspect.analysis.mapper.ResultAnalysisMapper;
import com.inspect.analysis.utils.ResultAnalysisUtils;
import com.inspect.base.core.constant.AlgConstants;
import com.inspect.base.core.enums.TaskType;
import com.inspect.base.core.exception.ServiceException;
import com.inspect.base.core.utils.DateUtils;
import com.inspect.base.core.utils.StringUtils;
import com.inspect.base.core.web.domain.AjaxResult;
import com.inspect.fegin.FeignBasedataAreaService;
import com.inspect.img.domain.InspectionReportImg;
import com.inspect.img.mapper.InspectionReportImgMapper;
import com.inspect.insreport.domain.InspectionReport;
import com.inspect.insreport.mapper.InspectionReportMapper;
import com.inspect.insreportdata.domain.InspectionReportData;
import com.inspect.insreportdata.mapper.InspectionReportDataMapper;
import com.inspect.message.MessageUtils;
import com.inspect.partrolresult.domain.*;
import com.inspect.partrolresult.mapper.PatrolResultMapper;
import com.inspect.partrolresult.service.IPatrolResultService;
import com.inspect.partrolresult.util.PrintUtil;
import com.inspect.patrolresultdefault.domain.PatrolResultDefaultValue;
import com.inspect.patrolresultdefault.mapper.PatrolResultDefaultValueMapper;
import com.inspect.resultmain.domain.PatrolTaskResultMain;
import com.inspect.resultmain.mapper.PatrolTaskResultMainMapper;
import com.inspect.system.base.openDomain.BasedataEqpBookMoMain;
import com.inspect.task.domain.PatrolData;
import com.inspect.task.domain.PatrolTask;
import com.inspect.task.mapper.PatrolTaskMapper;
import com.inspect.taskstatus.domain.PatrolTaskStatus;
import com.inspect.taskstatus.mapper.PatrolTaskStatusMapper;
import io.seata.common.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RefreshScope
public class PatrolResultServiceImpl implements IPatrolResultService {
    private static final Logger log = LoggerFactory.getLogger(PatrolResultServiceImpl.class);
    private static final Set<String> validAlgTypes = new HashSet<>(Arrays.asList(
            AlgConstants.METER,
            AlgConstants.XB,
            AlgConstants.INFRA_1800,
            AlgConstants.INFRA_YU3,
            AlgConstants.INFRA_CAMERA,
            AlgConstants.INFRA_CAMERA_REVERSE,
            AlgConstants.INFRARED,
            AlgConstants.INFRARED2,
            AlgConstants.GIS_METER_2,
            AlgConstants.GIS_METER
    ));
    final
    PatrolResultDefaultValueMapper patrolResultDefaultvalueMapper;
    private final PatrolResultMapper patrolResultMapper;
    private final PatrolTaskResultMainMapper patrolTaskResultMainMapper;
    private final PatrolTaskStatusMapper patrolTaskStatusMapper;
    private final PatrolTaskMapper patrolTaskMapper;
    private final InspectionReportMapper inspectionReportMapper;
    private final InspectionReportImgMapper inspectionReportImgMapper;
    private final InspectionReportDataMapper inspectionReportDataMapper;
    private final ResultAnalysisMapper resultAnalysisMapper;
    private final FeignBasedataAreaService feignBasedataAreaService;
    @Value("${inspect.task.report.voltage:±800kv}")
    private String voltage;
    @Value("${inspect.task.report.all:0}")
    private String exportReportFlag;
    @Autowired
    private MessageUtils messageUtils;
    @Resource
    private ResultAnalysisUtils resultAnalysisUtils;

    public PatrolResultServiceImpl(PatrolResultMapper patrolResultMapper, PatrolResultDefaultValueMapper patrolResultDefaultvalueMapper, PatrolTaskResultMainMapper patrolTaskResultMainMapper, PatrolTaskStatusMapper patrolTaskStatusMapper, PatrolTaskMapper patrolTaskMapper, InspectionReportMapper inspectionReportMapper, InspectionReportImgMapper inspectionReportImgMapper, InspectionReportDataMapper inspectionReportDataMapper, ResultAnalysisMapper resultAnalysisMapper, FeignBasedataAreaService feignBasedataAreaService) {
        this.patrolResultMapper = patrolResultMapper;
        this.patrolResultDefaultvalueMapper = patrolResultDefaultvalueMapper;
        this.patrolTaskResultMainMapper = patrolTaskResultMainMapper;
        this.patrolTaskStatusMapper = patrolTaskStatusMapper;
        this.patrolTaskMapper = patrolTaskMapper;
        this.inspectionReportMapper = inspectionReportMapper;
        this.inspectionReportImgMapper = inspectionReportImgMapper;
        this.inspectionReportDataMapper = inspectionReportDataMapper;
        this.resultAnalysisMapper = resultAnalysisMapper;
        this.feignBasedataAreaService = feignBasedataAreaService;
    }


    public PatrolResult selectPatrolResultByLineId(Long lineId) {
        return patrolResultMapper.selectPatrolResultByLineId(lineId);
    }

    public Map<String, Object> selectBaseInfoByPointId(String lineId) {
        return patrolResultMapper.selectBaseInfoByPointId(lineId);
    }

    public Map<String, Object> selectBaseByPointId(String lineId) {
        return patrolResultMapper.selectBaseByPointId(lineId);
    }

    public List<PatrolResult> selectPatrolResultList(PatrolResult patrolResult) {
        return patrolResultMapper.selectPatrolResultList(patrolResult);
    }

    public PatrolResult selectPatrolResultByDeviceName(String deviceName) {
        return patrolResultMapper.selectPatrolResultByDeviceName(deviceName);
    }

    public ResultAnalysis selectTaskAbnormalData(ResultAnalysis patrolResult) {
        return resultAnalysisMapper.selectTaskAbnormalData(patrolResult);
    }

    public List<PatrolResult> selectPatrolResultListOrderBy(PatrolResult patrolResult) {
        return patrolResultMapper.selectPatrolResultListOrderBy(patrolResult);
    }

    public List<PatrolData> selectPatrolDataResultByTaskCode(PatrolResult patrolResult) {
        return patrolResultMapper.selectPatrolDataResultByTaskCode(patrolResult);
    }

    @Override
    public List<PatrolData> selectPatrolDataResultByTaskCodeV2(ResultAnalysis resultAnalysis) {
        PatrolTaskStatus patrolTaskStatus = patrolTaskStatusMapper.selectPatrolTaskStatusByTaskPatrolledId(resultAnalysis.getTaskPatrolId());
        if (patrolTaskStatus != null) {
            if (patrolTaskStatus.getTaskType().equals(TaskType.MAIN.getCode())) {
                List<String> taskPatrolIds = patrolTaskStatus.getChildren().stream().map(PatrolTaskStatus::getTaskPatrolledId).collect(Collectors.toList());
                resultAnalysis.setTaskPatrolIds(taskPatrolIds);
            } else {
                resultAnalysis.setTaskPatrolIds(Collections.singletonList(patrolTaskStatus.getTaskPatrolledId()));
            }
        }
        log.info("---------------[TASK] query resultAnalysis {}", resultAnalysis);
        return this.patrolResultMapper.selectPatrolDataResultByTaskCodeV3(resultAnalysis);
    }

    public List<PatrolData> selectPatrolDataResultByTaskCodeList(PatrolTaskStatus patrolTaskStatus) {
        return patrolResultMapper.selectPatrolDataResultByTaskCodeList(patrolTaskStatus);
    }

    public List<BasedataEqpBookMoMain> selectBasedataEqpBookList(BasedataEqpBookMoMain patrolResult) {
        return patrolResultMapper.selectBasedataEqpBookList(patrolResult);
    }

    @Override
    public List<BasedataEqpBookMoMain> selectCamera(BasedataEqpBookMoMain basedataEqpBook) {
        return patrolResultMapper.selectCamera(basedataEqpBook);
    }

    public List<PatrolResult> selectPatroByAllDev(PatrolResult patrolResult) {
        return patrolResultMapper.selectPatroByAllDev(patrolResult);
    }

    public List<PatrolResult> selectPatroByAllDevByMainIds(PatrolResult patrolResult) {
        return patrolResultMapper.selectPatroByAllDevByMainIds(patrolResult);
    }

    public List<AlgInfo> selectAlgInfo(PatrolResult patrolResult) {
        return patrolResultMapper.selectAlgInfo(patrolResult);
    }

    public Map<String, String> selectAlgorithmType(String patrolPointId) {
        log.info("selectAlgorithmType patrolPointId: {}", patrolPointId);
        return patrolResultMapper.selectAlgorithmType(patrolPointId);
    }

    public Map<String, String> selectAlgorithmInfo(String code) {
        return patrolResultMapper.selectAlgorithmInfo(code);
    }

    public List<PatrolPresetPosModule> selectAlgorithmTypeList(String lineId) {
        return patrolResultMapper.selectAlgorithmTypeList(lineId);
    }

    public Map<String, String> selectPatrolPresetParam(String lineId) {
        return patrolResultMapper.selectPatrolPresetParam(lineId);
    }

    public Map<String, String> selectThresholdByPointId(String lineId) {
        return patrolResultMapper.selectThresholdByPointId(lineId);
    }

    public Map<String, String> selectAlgTypeDataType(String type) {
        return patrolResultMapper.selectAlgTypeDataType(type);
    }

    public Map<String, String> selectAlgTypeByCode(String algCode) {
        return patrolResultMapper.selectAlgTypeByCode(algCode);
    }

    public Map<String, String> selectBasedataStation() {
        return patrolResultMapper.selectBasedataStation();
    }

    public List<Map<String, String>> selectEvnData(String code) {
        return patrolResultMapper.selectEvnData(code);
    }

    public Map<String, Object> selectDevInfoById(String deviceId) {
        return patrolResultMapper.selectDevInfoById(deviceId);
    }

    public Map<String, String> selectAreaByAudit(String areaId) {
        return patrolResultMapper.selectAreByAudit(areaId);
    }

    public Map<String, Object> selectAreaInfo(String areaId) {
        return patrolResultMapper.selectAreInfo(areaId);
    }

    public List<Map<String, Object>> selectAreaInfoByParentId(String parentId) {
        return patrolResultMapper.selectAreInfoByParentId(parentId);
    }

    public int insertPatrolResult(PatrolResult patrolResult) {
        patrolResult.setCreateTime(new Date());
        return patrolResultMapper.insertPatrolResult(patrolResult);
    }

    public int updatePatrolResult(PatrolResult patrolResult) {
        return patrolResultMapper.updatePatrolResult(patrolResult);
    }

    public int updatePatrolResultByMainId(String mainId) {
        return patrolResultMapper.updatePatrolResultByMainId(mainId);
    }

    public int deletePatrolResultByLineIds(Long[] lineIds) {
        return patrolResultMapper.deletePatrolResultByLineIds(lineIds);
    }

    public int deletePatrolResultByLineId(Long lineId) {
        return patrolResultMapper.deletePatrolResultByLineId(lineId);
    }

    public Map<String, String> getPatrolResultValue(PatrolResult patrolResult) {
        log.info("[RES] ???????????????????/getPatrolResultValue: patrolResult: {}", patrolResult.toString());
        Map<String, String> map = new HashMap<>();
        String deviceId = patrolResult.getDeviceId();
        if (null != deviceId && !deviceId.isEmpty()) {
            log.info("[RES] getPatrolResultValue deviceId: {}", deviceId);
            PatrolResultDefaultValue patrolResultDefaultvalue = new PatrolResultDefaultValue();
            patrolResultDefaultvalue.setPatrolPointId(deviceId);
            List<PatrolResultDefaultValue> list = patrolResultDefaultvalueMapper.selectPatrolResultDefaultValueList(patrolResultDefaultvalue);
            PatrolResultDefaultValue patrolResultDefaultvalueResult = null;
            if (null != list && !list.isEmpty()) {
                log.info("[RES] getPatrolResultValue patrolPointId: {}", list.get(0).getPatrolPointId());
                patrolResultDefaultvalueResult = list.get(0);
            }

            if (null != patrolResultDefaultvalueResult) {
                int hour = DateUtils.getHourInt();
                log.info("[RES] getPatrolResultValue CUR HOUR: {}", hour);
                Map<String, String> retMap = this.getPatrolResultDefaultValueByHour(hour, patrolResultDefaultvalueResult);
                if (!retMap.isEmpty()) {
                    log.info("[RES] getPatrolResultValue VALUE: {}, VALUE_UNIT: {}", retMap.get("value"), retMap.get("value_unit"));
                    map = retMap;
                }
            }
        }

        return map;
    }

    private Map<String, String> getPatrolResultDefaultValueByHour(int hour, PatrolResultDefaultValue patrolResultDefaultvalue) {
        Map<String, String> map = new HashMap<>();
        String value = null;
        if (hour == 0) {
            value = patrolResultDefaultvalue.getHour0();
        } else if (hour == 1) {
            value = patrolResultDefaultvalue.getHour1();
        } else if (hour == 2) {
            value = patrolResultDefaultvalue.getHour2();
        } else if (hour == 3) {
            value = patrolResultDefaultvalue.getHour3();
        } else if (hour == 4) {
            value = patrolResultDefaultvalue.getHour4();
        } else if (hour == 5) {
            value = patrolResultDefaultvalue.getHour5();
        } else if (hour == 6) {
            value = patrolResultDefaultvalue.getHour6();
        } else if (hour == 7) {
            value = patrolResultDefaultvalue.getHour7();
        } else if (hour == 8) {
            value = patrolResultDefaultvalue.getHour8();
        } else if (hour == 9) {
            value = patrolResultDefaultvalue.getHour9();
        } else if (hour == 10) {
            value = patrolResultDefaultvalue.getHour10();
        } else if (hour == 11) {
            value = patrolResultDefaultvalue.getHour11();
        } else if (hour == 12) {
            value = patrolResultDefaultvalue.getHour12();
        } else if (hour == 13) {
            value = patrolResultDefaultvalue.getHour13();
        } else if (hour == 14) {
            value = patrolResultDefaultvalue.getHour14();
        } else if (hour == 15) {
            value = patrolResultDefaultvalue.getHour15();
        } else if (hour == 16) {
            value = patrolResultDefaultvalue.getHour16();
        } else if (hour == 17) {
            value = patrolResultDefaultvalue.getHour17();
        } else if (hour == 18) {
            value = patrolResultDefaultvalue.getHour18();
        } else if (hour == 19) {
            value = patrolResultDefaultvalue.getHour19();
        } else if (hour == 20) {
            value = patrolResultDefaultvalue.getHour20();
        } else if (hour == 21) {
            value = patrolResultDefaultvalue.getHour21();
        } else if (hour == 22) {
            value = patrolResultDefaultvalue.getHour22();
        } else if (hour == 23) {
            value = patrolResultDefaultvalue.getHour23();
        }

        if (null == value) {
            value = patrolResultDefaultvalue.getDefaultValue();
        }

        String valueUnit = patrolResultDefaultvalue.getDefaultValueUnit();
        log.info("[RES] pointId: {}, value: {}, valueUnit: {}", patrolResultDefaultvalue.getPatrolPointId(), value, valueUnit);
        map.put("value", value);
        map.put("value_unit", valueUnit);
        return map;
    }

    public List<ResultValue> selectOilResultValue(PatrolResult patrolResult) {
        return patrolResultMapper.selectOilResultValue(patrolResult);
    }

    public List<ResultValue> select6FsResultValue(PatrolResult patrolResult) {
        return patrolResultMapper.select6FsResultValue(patrolResult);
    }

    @Transactional
    public List<Long> saveReport(PatrolTaskResultMain resultMain, List<Long> lineIds, Long currentLineId, List<PatrolResult> resultList, int aiQxNum, int csQxNum) {
        long startTime = System.currentTimeMillis();
//        String mainId = String.valueOf(resultMain.getLineId());
        for (Long lineId : lineIds) {
            resultMain.setLineId(lineId);
            resultMain.setCheckTime(new Date());
            resultMain.setFileStatus("1");
            this.patrolTaskResultMainMapper.updatePatrolTaskResultMain(resultMain);
            this.patrolResultMapper.updatePatrolResultByMainId(String.valueOf(lineId));
        }
        PrintUtil.useTime("AMENDING DATA", startTime);
        resultMain.setLineId(currentLineId);
        return saveReportData(resultList, resultMain, lineIds, aiQxNum, csQxNum);
    }

    @Transactional
    public List<Long> saveReportLingzhou_v1(PatrolTaskResultMain resultMain, List<Long> lineIds, Long currentLineId, List<PatrolResult> resultList, int aiQxNum, int csQxNum) {
        long startTime = System.currentTimeMillis();
        List<Long> reportIds = new ArrayList<>();
//        String mainId = String.valueOf(resultMain.getLineId());
        for (Long lineId : lineIds) {
            resultMain.setLineId(lineId);
            resultMain.setCheckTime(new Date());
            resultMain.setFileStatus("1");
            this.patrolTaskResultMainMapper.updatePatrolTaskResultMain(resultMain);
            this.patrolResultMapper.updatePatrolResultByMainId(String.valueOf(lineId));
            reportIds.addAll(saveReportDataLingzhou_v1(resultList, resultMain, lineIds, aiQxNum, csQxNum));
        }

        PrintUtil.useTime("获取所有报告id", startTime);
        return reportIds;
//        resultMain.setLineId(currentLineId);
//        return saveReportData(resultList, resultMain, lineIds);
    }

    @Transactional
    public List<Long> saveReportLingzhou_v2(PatrolTaskResultMain resultMain, List<Long> lineIds, Long currentLineId, List<PatrolResult> resultList) {
        long startTime = System.currentTimeMillis();
        List<Long> reportIds = new ArrayList<>();
        if (resultList.isEmpty()) {
            log.error("EMPTY REPORT DATA");
            return reportIds;
        }
//        statisticsAnalyseNumLingZhou(lineIds);
        List<String> taskNames = resultList.stream().map(PatrolResult::getTaskName).distinct().collect(Collectors.toList());
        List<String> taskPatrolledIds = resultList.stream().map(PatrolResult::getTaskPatrolledId).distinct().collect(Collectors.toList());
        String taskName = StringUtils.join(taskNames, ",");

        List<PatrolTaskStatus> taskStatuses = this.patrolTaskStatusMapper.selectPatrolTaskStatusListByTaskPatrolledIds(taskPatrolledIds);
        if (taskStatuses.isEmpty()) {
            log.error("LACKING STATUS: " + resultMain.getLineId());
        }
        List<Date> startTimes = taskStatuses.stream().map(PatrolTaskStatus::getStartTime).sorted().collect(Collectors.toList());
        List<String> endTimes = taskStatuses.stream().map(PatrolTaskStatus::getEndTime).sorted().collect(Collectors.toList());

        Map<String, String> stationMap = patrolResultMapper.selectBasedataStation();
        String stationName = stationMap.get("station_name");
        String stationType = stationMap.get("station_type");
        String voltLevel = stationMap.get("volt_level");
        AjaxResult ajaxResult = feignBasedataAreaService.evnList();
        List<JSONObject> jsonObjects = JSONObject.parseArray(JSON.toJSONString(ajaxResult.get("data")), JSONObject.class);
        log.debug("EVN LIST: " + jsonObjects);
        List<String> envoList = new ArrayList<>();
        for (JSONObject jsonObject : jsonObjects) {
            String typeName = jsonObject.getString("typeName");
            String valueUnit = jsonObject.getString("valueUnit");
            if (StringUtils.isEmpty(valueUnit) || StringUtils.isEmpty(typeName)) {
                continue;
            }
            envoList.add(typeName + ":" + valueUnit);
        }

        Map<String, PatrolResultRef> keyPatrolResultRef = new HashMap<>();
        List<PatrolResultRef> patrolResultRefs = patrolResultMapper.selectResultRefByLineIds(lineIds, "0");
        List<PatrolResultRef> patrolResultRefsFilter = patrolResultMapper.selectResultRefByLineIds(lineIds, "1");
        int qxNumFilter = 0;
        int ycNumFilter = 0;
        int qxNumAI = 0;
        for (PatrolResultRef AIRef : patrolResultRefs) {
            keyPatrolResultRef.put(AIRef.getDeviceId() + "_" + AIRef.getAlgType(), AIRef);
//            if ("0".equals(AIRef.getResultType())) {
//                ++qxNumAI;
//            }
        }
        for (PatrolResultRef filterRef : patrolResultRefsFilter) {
            keyPatrolResultRef.putIfAbsent(filterRef.getDeviceId() + "_" + filterRef.getAlgType(), filterRef);
//            if ("0".equals(filterRef.getResultType())) {
//                ++qxNumFilter;
//            } else if ("2".equals(filterRef.getResultType())) {
//                ++ycNumFilter;
//            }
        }
        patrolResultRefs = new ArrayList<>(keyPatrolResultRef.values());
        for (PatrolResultRef patrolResultRef : patrolResultRefs) {
            if ("0".equals(patrolResultRef.getFilter()) && "0".equals(patrolResultRef.getResultType())) {
                ++qxNumAI;
            }
            if ("1".equals(patrolResultRef.getFilter()) && "0".equals(patrolResultRef.getResultType())) {
                ++qxNumFilter;
            }
            if ("2".equals(patrolResultRef.getResultType())) {
                ++ycNumFilter;
            }
        }
        int totalNum = patrolResultRefs.size();
        String AiNum = String.format(messageUtils.get("本次任务巡视总点位：%d个，已检点位：%d个，未检点位：0个，初筛缺陷点位：%d个，异常点位：%d个；大模型复检缺陷点位：%d个。"), totalNum, totalNum, qxNumFilter, ycNumFilter, qxNumAI);
        List<BasePointAreaInfo> basePointAreaInfoList = patrolResultMapper.selectBaseInfoByMainIds(lineIds);
        // 每个任务生成一份报告
        for (Long lineId : lineIds) {
            resultMain.setLineId(lineId);
            resultMain.setCheckTime(new Date());
            resultMain.setFileStatus("1");
            this.patrolTaskResultMainMapper.updatePatrolTaskResultMain(resultMain);
            this.patrolResultMapper.updatePatrolResultByMainId(String.valueOf(lineId));
            startTime = System.currentTimeMillis();
            String mainId = String.valueOf(resultMain.getLineId());
            String[] nums = new String[]{AiNum};

            PatrolResult patrolResult = resultList.stream().filter(item -> mainId.equals(item.getMainId())).findFirst().orElse(null);
            assert patrolResult != null;
            String taskCode = patrolResult.getTaskCode();
            String taskPatrolId = patrolResult.getTaskPatrolledId();

            if (StringUtils.isEmpty(taskPatrolId)) {
                throw new ServiceException("LACK PLAN ID: " + mainId);
            } else {
                if (taskStatuses.isEmpty()) {
                    throw new ServiceException("LACKING STATUS: " + mainId);
                } else {
//                    PatrolTaskStatus taskStatus = taskStatuses.stream().filter(item -> taskPatrolId.equals(item.getTaskPatrolledId())).findFirst().orElse(null);
                    List<PatrolTask> list = patrolTaskMapper.selectPatrolTaskList(PatrolTask.builder().taskCode(taskCode).build());
                    if (list.isEmpty()) {
                        throw new ServiceException("TASK PLAN LOST: " + taskCode);
                    } else {
                        PatrolTask task = list.get(0);
                        for (int i = 0; i < nums.length; i++) {
                            InspectionReport report = new InspectionReport();
//                            resetReport(report, nums[i], mainId, task, taskStatus);
                            report.setPatrolStatistics(nums[i]);
                            report.setInspectionDate(new Date());
                            report.setTaskResultId(mainId);
                            report.setInspectionStartTime(startTimes.get(0));
                            report.setInspectionEndTime(DateUtils.parseDate(endTimes.get(endTimes.size() - 1)));
                            report.setTaskId(String.valueOf(task.getTaskId()));
                            report.setEnvInfo(StringUtils.join(envoList, ","));
                            report.setTaskPatrolledId(taskPatrolId);
                            report.setInspectionTaskName(taskName);
                            report.setDescription(resultMain.getTaskResult());
                            report.setCheckPerson(resultMain.getCheckPerson());
                            report.setCheckTime(resultMain.getCheckTime());
                            report.setStationName(stationName);
                            report.setVoltLevel(StringUtils.isEmpty(voltLevel) ? voltage : voltLevel);
                            report.setFilter(String.valueOf(i));
                            report.setStationType(stationType);
                            inspectionReportMapper.insertInspectionReport(report);
                            PrintUtil.useTime("NEW TASK REPORT", startTime); // 12s
                            batchInsertReportData_Lingzhou(String.valueOf(report.getLineId()), basePointAreaInfoList, String.valueOf(i), patrolResultRefs);
                            PrintUtil.useTime("BATCH INSERT DETAIL", startTime); // 13s
                            log.info("[ARCHIVE] reportId: {}", report.getLineId());
                            reportIds.add(report.getLineId());
                        }
                    }
                }
            }
        }

        PrintUtil.useTime("获取所有报告id", startTime);
        return reportIds;
    }

    @Transactional
    public List<Long> saveReportShaoxing(PatrolTaskResultMain resultMain, List<Long> lineIds, List<PatrolResult> resultList) {
        log.info("saveReportShaoxing PatrolTaskResultMain:{},lineIds:{},resultList:{} ", resultMain, lineIds, resultList);
        long startTime = System.currentTimeMillis();
        List<Long> reportIds = new ArrayList<>();
        // 获取站信息
        Map<String, String> stationMap = patrolResultMapper.selectBasedataStation();
        String stationName = stationMap.get("station_name");
        String stationType = stationMap.get("station_type");
        String voltLevel = stationMap.get("volt_level");
        startTime = PrintUtil.useTime("导出报告：查询站点信息", startTime);

        AjaxResult ajaxResult = feignBasedataAreaService.evnList();
        List<JSONObject> jsonObjects = JSONObject.parseArray(JSON.toJSONString(ajaxResult.get("data")), JSONObject.class);
        List<String> envoList = new ArrayList<>();
        for (JSONObject jsonObject : jsonObjects) {
            String typeName = jsonObject.getString("typeName");
            String valueUnit = jsonObject.getString("valueUnit");
            if (StringUtils.isEmpty(valueUnit) || StringUtils.isEmpty(typeName)) {
                continue;
            }
            envoList.add(typeName + ":" + valueUnit);
        }
        startTime = PrintUtil.useTime("导出报告：获取气象数据", startTime);

        // 查询任务状态信息
        List<String> taskPatrolledIds = resultList.stream().map(PatrolResult::getTaskPatrolledId).distinct().collect(Collectors.toList());
        List<PatrolTaskStatus> patrolTaskStatuses = patrolTaskStatusMapper.selectPatrolTaskStatusListByTaskPatrolledIds(taskPatrolledIds);
        List<Date> startTimes = patrolTaskStatuses.stream().map(PatrolTaskStatus::getStartTime).sorted().collect(Collectors.toList());
        List<String> endTimes = patrolTaskStatuses.stream().map(PatrolTaskStatus::getEndTime).sorted().collect(Collectors.toList());
        startTime = PrintUtil.useTime("导出报告：获取任务进度信息", startTime);

        List<String> taskNames = resultList.stream().map(PatrolResult::getTaskName).distinct().collect(Collectors.toList());
        String taskName = StringUtils.join(taskNames, ",");
        boolean isMultipleTasks = CollectionUtils.isNotEmpty(lineIds) && lineIds.size() > 1;
        if (isMultipleTasks) {
            // 说明多个任务合并，任务名称修改为巡视日期-巡视报告 例如：2026年3月23日-巡视报告
            Date date = CollectionUtils.isNotEmpty(startTimes) ? startTimes.get(0) : new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
            taskName = sdf.format(date) + "-" + messageUtils.get("巡视报告");
        }
        startTime = PrintUtil.useTime("导出报告：获取任务名信息", startTime);

        List<BasePointAreaInfo> basePointAreaInfoList = patrolResultMapper.selectBaseInfoByMainIds(lineIds);
        startTime = PrintUtil.useTime("导出报告：获取区域，生产，部件信息", startTime);

        List<PatrolResultRef> patrolResultRefs = patrolResultMapper.selectResultRefByLineIds(lineIds, null);
        startTime = PrintUtil.useTime("导出报告：获取巡视分析结果数据", startTime);

        Map<GroupKey, List<PatrolResultRef>> groupKeyListMap;
        if ("0".equals(exportReportFlag)) {
            List<PatrolResultRef> resultRefs = new ArrayList<>();
            // 只导出缺陷
            patrolResultRefs = patrolResultRefs.stream().filter((item) -> "0".equals(item.getResultType())).collect(Collectors.toList());
            // 分组，按点位ID和算法类型进行分组
            groupKeyListMap = patrolResultRefs.stream().collect(Collectors.groupingBy(item -> new GroupKey(item.getDeviceId(), item.getAlgType(), item.getTaskPatrolledId())));
            for (Map.Entry<GroupKey, List<PatrolResultRef>> entry : groupKeyListMap.entrySet()) {
                GroupKey key = entry.getKey();
                List<PatrolResultRef> value = entry.getValue();
                PatrolResultRef patrolResultRef = new PatrolResultRef();
                patrolResultRef.setDeviceId(key.objectId);
                patrolResultRef.setAlgType(key.algType);
                // 纠偏算法不归档
                if (AlgConstants.CORRECTION.equals(key.algType)) {
                    continue;
                }
                patrolResultRef.setDescription(value.stream().sorted(Comparator.comparing(PatrolResultRef::getFilter).reversed()).map(PatrolResultRef::getDescription).collect(Collectors.joining(",")));
                patrolResultRef.setValue(value.stream().sorted(Comparator.comparing(PatrolResultRef::getFilter).reversed()).map(PatrolResultRef::getValue).collect(Collectors.joining(",")));
                for (PatrolResultRef resultRef : value) {
                    // 初筛有缺陷，展示初筛结果
                    if ("1".equals(resultRef.getFilter()) && StringUtils.isEmpty(patrolResultRef.getResultContent())) {
                        patrolResultRef.setResultContent(resultRef.getResultContent());
                    }
                    if ("1".equals(resultRef.getFilter()) && StringUtils.isEmpty(patrolResultRef.getFilePath())) {
                        patrolResultRef.setFilePath(resultRef.getFilePath());
                    }
                    // 大模型有缺陷，展示大模型结果
                    if ("0".equals(resultRef.getFilter())) {
                        patrolResultRef.setResultContent(resultRef.getResultContent());
                        patrolResultRef.setFilePath(resultRef.getFilePath());
                    }
                }
                patrolResultRef.setDevType(value.stream().map(item -> item.getDevType() != null ? item.getDevType() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setDeviceSource(value.stream().map(item -> item.getDeviceSource() != null ? item.getDeviceSource() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setTime(value.stream().map(item -> item.getTime() != null ? item.getTime() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setThreshold(value.stream().map(item -> item.getThreshold() != null ? item.getThreshold() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setAlgName(value.get(0).getAlgName());
                patrolResultRef.setResultType("0");
                resultRefs.add(patrolResultRef);
            }
            patrolResultRefs = resultRefs;
            startTime = PrintUtil.useTime("导出报告：筛选缺陷数据", startTime);
        } else {
            groupKeyListMap = patrolResultRefs.stream().collect(Collectors.groupingBy(item -> new GroupKey(item.getDeviceId(), item.getAlgType(), item.getTaskPatrolledId())));
            List<PatrolResultRef> processedRefs = new ArrayList<>();
            for (Map.Entry<GroupKey, List<PatrolResultRef>> entry : groupKeyListMap.entrySet()) {
                List<PatrolResultRef> value = entry.getValue();
                GroupKey key = entry.getKey();
                String algType = key.algType;
                // 纠偏算法不归档
                if (AlgConstants.CORRECTION.equals(algType)) {
                    continue;
                }
                List<PatrolResultRef> filterResults = value.stream().filter(item -> "1".equals(item.getFilter())).collect(Collectors.toList());
                List<PatrolResultRef> AIResults = value.stream().filter(item -> "0".equals(item.getFilter())).collect(Collectors.toList());
                PatrolResultRef filterResult = filterResults.isEmpty() ? null : filterResults.get(0);
                PatrolResultRef AIResult = AIResults.isEmpty() ? null : AIResults.get(0);

                if (AlgConstants.BIG_MODEL_ALG_LIST.contains(algType)) {
                    // 表计类处理
                    if (filterResult != null && AIResult != null) {
                        String filterResultType = filterResult.getResultType();
                        String AIResultType = AIResult.getResultType();
                        if ("1".equals(filterResultType)) { // 初筛正常
                            // 只归档大模型
                            processedRefs.add(AIResult);
                        } else if ("0".equals(filterResultType)) { // 初筛缺陷
                            if ("1".equals(AIResultType)) {
                                // 分开：初筛缺陷，大模型正常
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            } else if ("0".equals(AIResultType)) {
                                // 合并：初筛缺陷，大模型缺陷
                                PatrolResultRef merged = mergePatrolResultRef(filterResult, AIResult, "0");
                                processedRefs.add(merged);
                            } else if ("2".equals(AIResultType)) {
                                // 分开：初筛缺陷，大模型异常
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            }
                        } else if ("2".equals(filterResultType)) { // 初筛异常
                            if ("1".equals(AIResultType)) {
                                // 分开：初筛异常，大模型正常
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            } else if ("0".equals(AIResultType)) {
                                // 分开：初筛异常，大模型缺陷
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            } else if ("2".equals(AIResultType)) {
                                // 合并：初筛异常，大模型异常
                                PatrolResultRef merged = mergePatrolResultRef(filterResult, AIResult, "2");
                                processedRefs.add(merged);
                            }
                        } else {
                            // 未知类型，都添加
                            processedRefs.add(filterResult);
                            processedRefs.add(AIResult);
                        }
                    } else if (filterResult != null) {
                        processedRefs.add(filterResult);
                    } else if (AIResult != null) {
                        processedRefs.add(AIResult);
                    }
                } else {
                    // 外观处理
                    if (filterResult != null && AIResult != null) {
                        String filterResultType = filterResult.getResultType();
                        String AIResultType = AIResult.getResultType();
                        if ("0".equals(filterResultType)) { // 初筛缺陷
                            if ("1".equals(AIResultType)) {
                                // 分开：初筛缺陷，大模型正常
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            } else if ("0".equals(AIResultType)) {
                                // 合并：初筛缺陷，大模型缺陷
                                PatrolResultRef merged = mergePatrolResultRef(filterResult, AIResult, "0");
                                processedRefs.add(merged);
                            } else if ("2".equals(AIResultType)) {
                                // 分开：初筛缺陷，大模型异常
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            } else {
                                // 未知，都添加
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            }
                        } else {
                            // 初筛不是缺陷但有大模型（理论上不应出现），为保数据完整都添加
                            processedRefs.add(filterResult);
                            processedRefs.add(AIResult);
                        }
                    } else if (filterResult != null) {
                        processedRefs.add(filterResult);
                    } else if (AIResult != null) {
                        processedRefs.add(AIResult);
                    }
                }
            }
            patrolResultRefs = processedRefs;
            startTime = PrintUtil.useTime("导出报告：全部数据处理", startTime);
        }
        long okNum = 0L;
        long failNum = 0L;
        long defectNum = 0L;
        for (PatrolResultRef patrolResultRef : patrolResultRefs) {
            String resultType = patrolResultRef.getResultType();
            if (resultType == null) {
                continue;
            } else if (resultType.equals("0")) {
                // 缺陷编号
                ++defectNum;
            } else if (resultType.equals("1")) {
                // 正常编号
                ++okNum;
            } else {
                // 异常编号
                ++failNum;
            }
        }
        long total = okNum + defectNum;
        String patrolStatistics;
        if ("0".equals(exportReportFlag)) {
            patrolStatistics = String.format(messageUtils.get("缺陷数量：%d个。"), defectNum);
        } else {
            patrolStatistics = String.format(messageUtils.get("本次任务巡视总结果数量：%d个，正常结果数量：%d个，缺陷结果数量：%d个"), total, okNum, defectNum);
        }
        for (Long lineId : lineIds) {
            resultMain.setLineId(lineId);
            resultMain.setCheckTime(new Date());
            resultMain.setFileStatus("1");
            String mainId = String.valueOf(resultMain.getLineId());

            // 查询当前的结果信息
            PatrolResult patrolResult = resultList.stream().filter(item -> mainId.equals(item.getMainId())).findFirst().orElse(null);
            assert patrolResult != null;
            String taskCode = patrolResult.getTaskCode();
            PatrolTaskResultMain main = patrolTaskResultMainMapper.selectPatrolTaskResultMainByLineId(lineId);
            String taskPatrolId = main.getTaskPatrolledId();
            if (StringUtils.isEmpty(taskPatrolId)) {
                throw new ServiceException("LACK PLAN ID: " + mainId);
            } else {
                List<PatrolTaskStatus> taskStatuses = this.patrolTaskStatusMapper.selectPatrolTaskStatusList(PatrolTaskStatus.builder().taskPatrolledId(taskPatrolId).build());
                if (taskStatuses.isEmpty()) {
                    throw new ServiceException("LACKING STATUS: " + mainId);
                } else {
                    List<PatrolTask> list = patrolTaskMapper.selectPatrolTaskList(PatrolTask.builder().taskCode(taskCode).build());
                    PatrolTask task = new PatrolTask();
                    if (list.isEmpty()) {
                        log.error("TASK PLAN LOST: " + taskCode);
                    } else {
                        task = list.get(0);
                    }
                    InspectionReport report = new InspectionReport();
                    report.setPatrolStatistics(patrolStatistics);
                    report.setInspectionDate(new Date());
                    report.setTaskResultId(mainId);
                    report.setInspectionStartTime(startTimes.get(0));
                    report.setInspectionEndTime(DateUtils.parseDate(endTimes.get(endTimes.size() - 1)));
                    report.setTaskId(task.getTaskId() == null ? "" : String.valueOf(task.getTaskId()));
                    report.setEnvInfo(StringUtils.join(envoList, ","));
                    report.setTaskPatrolledId(taskPatrolId);
                    report.setInspectionTaskName(taskName);
                    report.setDescription(resultMain.getTaskResult());
                    report.setCheckPerson(resultMain.getCheckPerson());
                    report.setCheckTime(resultMain.getCheckTime());
                    report.setStationName(stationName);
                    report.setVoltLevel(StringUtils.isEmpty(voltLevel) ? voltage : voltLevel);
                    report.setFilter("0");
                    report.setStationType(stationType);
                    inspectionReportMapper.insertInspectionReport(report);
                    // 为每个报告生成数据
                    batchInsertReportData_shaoxing(String.valueOf(report.getLineId()), patrolResultRefs, basePointAreaInfoList, lineIds);
                    reportIds.add(report.getLineId());
                }
            }
            this.patrolTaskResultMainMapper.updatePatrolTaskResultMain(resultMain);
            this.patrolResultMapper.updatePatrolResultByMainId(String.valueOf(lineId));
        }
        return reportIds;
    }

    @Transactional
    public List saveReportV2(PatrolTaskResultMain resultMain, List<PatrolResult> resultList) {
        long startTime = System.currentTimeMillis();
        String mainId = String.valueOf(resultMain.getLineId());
        resultMain.setCheckTime(new Date());
        resultMain.setFileStatus("1");
        patrolTaskResultMainMapper.updatePatrolTaskResultMain(resultMain);
        patrolResultMapper.updatePatrolResultByMainId(mainId);
        PrintUtil.useTime("修正数据", startTime);
        List reportIds = saveReportDataV2(resultList, resultMain);
        return reportIds;
    }

    public List<Long> saveReportData(List<PatrolResult> resultList, PatrolTaskResultMain resultMain, List<Long> lineIds, int aiQxNum, int csQxNum) {
        long startTime = System.currentTimeMillis();
        String mainId = String.valueOf(resultMain.getLineId());
//        String analyseNum = statisticsAnalyseNum(lineIds, resultList.size());
        String filterNum = statisticsAnalyseNumV3(lineIds, "1");
        String AiNum = statisticsAnalyseNumV3(lineIds, "0");
        String[] nums = new String[]{AiNum, filterNum};
        startTime = PrintUtil.useTime("STATISTICS ANALYZE DATA", startTime);
        if (resultList.isEmpty()) {
            throw new ServiceException("LACK INSPECT RESULT: " + mainId);
        } else {
            PatrolResult patrolResult = resultList.get(0);
            String taskCode = patrolResult.getTaskCode();
            String taskPatrolId = patrolResult.getTaskPatrolledId();
            if (StringUtils.isEmpty(taskPatrolId)) {
                throw new ServiceException("LACK PLAN ID: " + mainId);
            } else {
                List<PatrolTaskStatus> taskStatuses = this.patrolTaskStatusMapper.selectPatrolTaskStatusList(PatrolTaskStatus.builder().taskPatrolledId(taskPatrolId).build());
                startTime = PrintUtil.useTime("INQUIRY STATUS", startTime);
                if (taskStatuses.isEmpty()) {
                    throw new ServiceException("LACKING STATUS: " + mainId);
                } else {
                    PatrolTaskStatus taskStatus = taskStatuses.get(0);
                    List<PatrolTask> list = patrolTaskMapper.selectPatrolTaskList(PatrolTask.builder().taskCode(taskCode).build());
                    startTime = PrintUtil.useTime("INQUIRY TASK PLAN", startTime);
                    if (list.isEmpty()) {
                        throw new ServiceException("TASK PLAN LOST: " + taskCode);
                    } else {
                        List<Long> reportIds = new ArrayList<>();
                        PatrolTask task = list.get(0);
//                        List<InspectionReport> reports = inspectionReportMapper.selectInspectionReportList(new InspectionReport(mainId));
//                        startTime = PrintUtil.useTime("INQUIRY TASK REPORT", startTime);
//                        InspectionReport report;
//                        if (!reports.isEmpty()) {
//                            report = reports.get(0);
//                            resetReport(report, analyseNum, mainId, task, taskStatus);
//                            inspectionReportMapper.updateInspectionReport(report);
//                            PrintUtil.useTime("MODIFY TASK REPORT", startTime);
//                        } else {
                        Map<String, String> stationMap = patrolResultMapper.selectBasedataStation();
                        String stationName = stationMap.get("station_name");
                        String stationType = stationMap.get("station_type");
                        String voltLevel = stationMap.get("volt_level");
                        for (int i = 0; i < nums.length; i++) {
                            if ("0".equals(exportReportFlag) && i == 0 && aiQxNum == 0) {
                                continue;
                            }
                            if ("0".equals(exportReportFlag) && i == 1 && csQxNum == 0) {
                                continue;
                            }
                            List<PatrolResultRef> patrolResultRefs = patrolResultMapper.selectResultRefByLineIds(lineIds, String.valueOf(i));
                            if (patrolResultRefs.isEmpty()) {
                                continue;
                            }
                            InspectionReport report = new InspectionReport();
                            resetReport(report, nums[i], mainId, task, taskStatus);
                            report.setTaskId(String.valueOf(task.getTaskId()));
                            report.setTaskPatrolledId(taskPatrolId);
                            report.setInspectionTaskName(task.getTaskName());
                            report.setDescription(resultMain.getTaskResult());
                            report.setCheckPerson(resultMain.getCheckPerson());
                            report.setCheckTime(resultMain.getCheckTime());
                            report.setStationName(stationName);
                            report.setVoltLevel(StringUtils.isEmpty(voltLevel) ? voltage : voltLevel);
                            report.setFilter(String.valueOf(i));
                            report.setStationType(stationType);
                            inspectionReportMapper.insertInspectionReport(report);
                            PrintUtil.useTime("NEW TASK REPORT", startTime);
                            batchInsertReportData(String.valueOf(report.getLineId()), lineIds, String.valueOf(i), patrolResultRefs);
                            PrintUtil.useTime("BATCH INSERT DETAIL", startTime);
                            log.info("[ARCHIVE] reportId: {}", report.getLineId());
                            Long lineId = report.getLineId();
                            reportIds.add(lineId);
                        }
//                        }
                        return reportIds;
                    }
                }
            }
        }
    }

    public List<Long> saveReportDataLingzhou_v1(List<PatrolResult> resultList, PatrolTaskResultMain resultMain, List<Long> lineIds, int aiQxNum, int csQxNum) {
        long startTime = System.currentTimeMillis();
        String mainId = String.valueOf(resultMain.getLineId());
//        String analyseNum = statisticsAnalyseNum(lineIds, resultList.size());
//        String filterNum = statisticsAnalyseNumLingZhou(lineIds, "1");
        String AiNum = statisticsAnalyseNumLingZhou(lineIds);
//        String[] nums = new String[]{AiNum, filterNum};
        String[] nums = new String[]{AiNum};
        startTime = PrintUtil.useTime("STATISTICS ANALYZE DATA", startTime); // 26s
        if (resultList.isEmpty()) {
            throw new ServiceException("LACK INSPECT RESULT: " + mainId);
        } else {
            PatrolResult patrolResult = resultList.stream().filter(item -> mainId.equals(item.getMainId())).findFirst().orElse(null);
            assert patrolResult != null;
            String taskCode = patrolResult.getTaskCode();
            String taskPatrolId = patrolResult.getTaskPatrolledId();
            List<String> taskNames = resultList.stream().map(PatrolResult::getTaskName).distinct().collect(Collectors.toList());
            List<String> taskPatrolledIds = resultList.stream().map(PatrolResult::getTaskPatrolledId).distinct().collect(Collectors.toList());
            String taskName = StringUtils.join(taskNames, ",");
            if (StringUtils.isEmpty(taskPatrolId)) {
                throw new ServiceException("LACK PLAN ID: " + mainId);
            } else {
//                List<PatrolTaskStatus> taskStatuses = this.patrolTaskStatusMapper.selectPatrolTaskStatusList(PatrolTaskStatus.builder().taskPatrolledId(taskPatrolId).build());
                List<PatrolTaskStatus> taskStatuses = this.patrolTaskStatusMapper.selectPatrolTaskStatusListByTaskPatrolledIds(taskPatrolledIds);
                List<Date> startTimes = taskStatuses.stream().map(PatrolTaskStatus::getStartTime).sorted().collect(Collectors.toList());
                List<String> endTimes = taskStatuses.stream().map(PatrolTaskStatus::getEndTime).sorted().collect(Collectors.toList());
                startTime = PrintUtil.useTime("INQUIRY STATUS", startTime);
                if (taskStatuses.isEmpty()) {
                    throw new ServiceException("LACKING STATUS: " + mainId);
                } else {
                    PatrolTaskStatus taskStatus = taskStatuses.stream().filter(item -> taskPatrolId.equals(item.getTaskPatrolledId())).findFirst().orElse(null);
                    List<PatrolTask> list = patrolTaskMapper.selectPatrolTaskList(PatrolTask.builder().taskCode(taskCode).build());
                    startTime = PrintUtil.useTime("INQUIRY TASK PLAN", startTime);
                    if (list.isEmpty()) {
                        throw new ServiceException("TASK PLAN LOST: " + taskCode);
                    } else {
                        List<Long> reportIds = new ArrayList<>();
                        PatrolTask task = list.get(0);
//                        List<InspectionReport> reports = inspectionReportMapper.selectInspectionReportList(new InspectionReport(mainId));
//                        startTime = PrintUtil.useTime("INQUIRY TASK REPORT", startTime);
//                        InspectionReport report;
//                        if (!reports.isEmpty()) {
//                            report = reports.get(0);
//                            resetReport(report, analyseNum, mainId, task, taskStatus);
//                            inspectionReportMapper.updateInspectionReport(report);
//                            PrintUtil.useTime("MODIFY TASK REPORT", startTime);
//                        } else {
                        Map<String, String> stationMap = patrolResultMapper.selectBasedataStation();
                        String stationName = stationMap.get("station_name");
                        String stationType = stationMap.get("station_type");
                        String voltLevel = stationMap.get("volt_level");
                        AjaxResult ajaxResult = feignBasedataAreaService.evnList();
                        List<JSONObject> jsonObjects = JSONObject.parseArray(JSON.toJSONString(ajaxResult.get("data")), JSONObject.class);
                        log.info("EVN LIST: " + jsonObjects);
                        List<String> envoList = new ArrayList<>();
                        for (JSONObject jsonObject : jsonObjects) {
                            String typeName = jsonObject.getString("typeName");
                            String valueUnit = jsonObject.getString("valueUnit");
                            if (StringUtils.isEmpty(valueUnit) || StringUtils.isEmpty(typeName)) {
                                continue;
                            }
                            envoList.add(typeName + ":" + valueUnit);
                        }
                        for (int i = 0; i < nums.length; i++) {
                            if ("0".equals(exportReportFlag) && aiQxNum == 0 && csQxNum == 0) {
                                continue;
                            }
                            Map<String, PatrolResultRef> keyPatrolResultRef = new HashMap<>();
                            List<PatrolResultRef> patrolResultRefs = patrolResultMapper.selectResultRefByLineIds(lineIds, "0");
                            List<PatrolResultRef> patrolResultRefsFilter = patrolResultMapper.selectResultRefByLineIds(lineIds, "1");
                            for (PatrolResultRef AIRef : patrolResultRefs) {
                                keyPatrolResultRef.put(AIRef.getDeviceId() + "_" + AIRef.getAlgType(), AIRef);
                            }
                            for (PatrolResultRef filterRef : patrolResultRefsFilter) {
                                keyPatrolResultRef.putIfAbsent(filterRef.getDeviceId() + "_" + filterRef.getAlgType(), filterRef);
                            }
                            patrolResultRefs = new ArrayList<>(keyPatrolResultRef.values());
                            if (patrolResultRefs.isEmpty()) {
                                continue;
                            }
                            InspectionReport report = new InspectionReport();
                            resetReport(report, nums[i], mainId, task, taskStatus);
                            report.setInspectionStartTime(startTimes.get(0));
                            report.setInspectionEndTime(DateUtils.parseDate(endTimes.get(endTimes.size() - 1)));
                            report.setTaskId(String.valueOf(task.getTaskId()));
                            report.setEnvInfo(StringUtils.join(envoList, ","));
                            report.setTaskPatrolledId(taskPatrolId);
                            report.setInspectionTaskName(taskName);
                            report.setDescription(resultMain.getTaskResult());
                            report.setCheckPerson(resultMain.getCheckPerson());
                            report.setCheckTime(resultMain.getCheckTime());
                            report.setStationName(stationName);
                            report.setVoltLevel(StringUtils.isEmpty(voltLevel) ? voltage : voltLevel);
                            report.setFilter(String.valueOf(i));
                            report.setStationType(stationType);
                            inspectionReportMapper.insertInspectionReport(report);
                            PrintUtil.useTime("NEW TASK REPORT", startTime); // 12s
                            batchInsertReportData(String.valueOf(report.getLineId()), lineIds, String.valueOf(i), patrolResultRefs);
                            PrintUtil.useTime("BATCH INSERT DETAIL", startTime); // 13s
                            log.info("[ARCHIVE] reportId: {}", report.getLineId());
                            Long lineId = report.getLineId();
                            reportIds.add(lineId);
                        }
//                        }
                        return reportIds;
                    }
                }
            }
        }
    }

    public List saveReportDataV2(List<PatrolResult> resultList, PatrolTaskResultMain resultMain) {
        long startTime = System.currentTimeMillis();
        String mainId = String.valueOf(resultMain.getLineId());
        String filterNum = statisticsAnalyseNumV2(mainId, "1");
        String AiNum = statisticsAnalyseNumV2(mainId, "0");
        String[] nums = new String[]{AiNum, filterNum};
        startTime = PrintUtil.useTime("统计分析数据", startTime);
        if (resultList.isEmpty()) {
            throw new ServiceException("缺少巡检结果：" + mainId);
        } else {
            PatrolResult patrolResult = resultList.get(0);
            String taskCode = patrolResult.getTaskCode();
            String taskPatrolId = patrolResult.getTaskPatrolledId();
            if (StringUtils.isEmpty(taskPatrolId)) {
                throw new ServiceException("缺少执行ID：" + mainId);
            } else {
                List<PatrolTaskStatus> taskStatuses = this.patrolTaskStatusMapper.selectPatrolTaskStatusList(new PatrolTaskStatus(taskPatrolId));
                startTime = PrintUtil.useTime("查询状态数据", startTime);
                if (taskStatuses.isEmpty()) {
                    throw new ServiceException("缺少状态数据：" + mainId);
                } else {
                    PatrolTaskStatus taskStatus = taskStatuses.get(0);
                    PatrolTask patrolTask = new PatrolTask();
                    patrolTask.setTaskCode(taskCode);
                    List<PatrolTask> list = this.patrolTaskMapper.selectPatrolTaskList(patrolTask);
                    startTime = PrintUtil.useTime("查询任务计划", startTime);
                    if (list.isEmpty()) {
                        throw new ServiceException("任务计划丢失：" + taskCode);
                    } else {
                        PatrolTask task = list.get(0);
                        startTime = PrintUtil.useTime("查询任务报告", startTime);
                        Map<String, String> stationMap = patrolResultMapper.selectBasedataStation();
                        String stationName = stationMap.get("station_name");
                        String stationType = stationMap.get("station_type");
                        ResultAnalysis resultAnalysis = new ResultAnalysis();
                        resultAnalysis.setTaskPatrolledId(resultList.get(0).getTaskPatrolledId());
                        ResultAnalysis ras = resultAnalysisMapper.selectTaskAbnormalData(resultAnalysis);
                        int ii = 0;
                        int iii = 0;
                        if (0 == ras.getCsQxNum()) {
                            ras.setFilter("0");
                            ii = 0;
                            iii = 0;
                        }

                        if (0 == ras.getAiQxNum()) {
                            ras.setFilter("1");
                            ii = 0;
                            iii = 1;
                        }

                        if (0 != ras.getCsQxNum() && 0 != ras.getAiQxNum()) {
                            ras.setFilter("2");
                            ii = 2;
                        }
                        Long[] ids = new Long[ii];
                        List list1 = new ArrayList<>();

                        for (int i = 0; i < 2; ++i) {
                            if (0 != ras.getCsQxNum() && 0 != ras.getAiQxNum()) {
                                iii = i;
                            }

                            if (i != Integer.parseInt(ras.getFilter())) {
                                InspectionReport report = new InspectionReport();
                                resetReport(report, nums[iii], mainId, task, taskStatus);
                                report.setFilter(iii + "");
                                report.setTaskId(String.valueOf(task.getTaskId()));
                                report.setTaskPatrolledId(taskPatrolId);
                                report.setInspectionTaskName(task.getTaskName());
                                report.setDescription(resultMain.getTaskResult());
                                report.setCheckPerson(resultMain.getCheckPerson());
                                report.setCheckTime(resultMain.getCheckTime());
                                report.setStationName(stationName);
                                report.setVoltLevel(this.voltage);
                                report.setStationType(stationType);
                                inspectionReportMapper.insertInspectionReport(report);
                                PrintUtil.useTime("新增任务报告", startTime);
                                batchInsertReportDataV2(String.valueOf(report.getLineId()), mainId, iii + "");
                                list1.add(report.getLineId());
                                PrintUtil.useTime("批量插入明细", startTime);
                            }
                        }

                        return list1;
                    }
                }
            }
        }
    }

    private void resetReport(InspectionReport report, String analyseNum, String mainId, PatrolTask task, PatrolTaskStatus taskStatus) {
        report.setPatrolStatistics(analyseNum);
        //report.setInspectionDate(task.getCreateTime());
        report.setInspectionDate(new Date());
        report.setTaskResultId(mainId);
        report.setInspectionStartTime(taskStatus.getStartTime());
        report.setInspectionEndTime(DateUtil.parseDateTime(taskStatus.getEndTime()));
    }

    public void batchInsertReportData(String reportId, List<Long> mainIds, String filter, List<PatrolResultRef> patrolResultRefs) {
        log.info("batchInsertReportData reportId:" + reportId + ", mainIds:" + mainIds + ", filter:" + filter);
        long startTime = System.currentTimeMillis();
//        List<PatrolResultRef> patrolResultRefs = patrolResultMapper.selectResultRefByLineId(mainId);
//        List<PatrolResultRef> patrolResultRefs = patrolResultMapper.selectResultRefByLineIds(mainIds, filter);
        if ("0".equals(exportReportFlag)) {
            List<PatrolResultRef> resultRefs = new ArrayList<>();
            // 只导出缺陷
            patrolResultRefs = patrolResultRefs.stream().filter((item) -> "0".equals(item.getResultType())).collect(Collectors.toList());
            // 分组，按点位ID和算法类型进行分组
            Map<GroupKey, List<PatrolResultRef>> groupKeyListMap = patrolResultRefs.stream().collect(Collectors.groupingBy(item -> new GroupKey(item.getDeviceId(), item.getAlgType(), item.getTaskPatrolledId())));
            groupKeyListMap.forEach((key, value) -> {
                PatrolResultRef patrolResultRef = new PatrolResultRef();
                patrolResultRef.setDeviceId(key.objectId);
                patrolResultRef.setAlgType(key.algType);
                patrolResultRef.setDescription(value.stream().sorted(Comparator.comparing(PatrolResultRef::getFilter).reversed()).map(PatrolResultRef::getDescription).collect(Collectors.joining(",")));
                patrolResultRef.setValue(value.stream().sorted(Comparator.comparing(PatrolResultRef::getFilter).reversed()).map(PatrolResultRef::getValue).collect(Collectors.joining(",")));
                for (PatrolResultRef resultRef : value) {
                    // 初筛有缺陷，展示初筛结果
                    if ("1".equals(resultRef.getFilter()) && StringUtils.isEmpty(patrolResultRef.getResultContent())) {
                        patrolResultRef.setResultContent(resultRef.getResultContent());
                    }
                    if ("1".equals(resultRef.getFilter()) && StringUtils.isEmpty(patrolResultRef.getFilePath())) {
                        patrolResultRef.setFilePath(resultRef.getFilePath());
                    }
                    // 大模型有缺陷，展示大模型结果
                    if ("0".equals(resultRef.getFilter())) {
                        patrolResultRef.setResultContent(resultRef.getResultContent());
                        patrolResultRef.setFilePath(resultRef.getFilePath());
                    }
                }
                patrolResultRef.setDevType(value.stream().map(item -> item.getDevType() != null ? item.getDevType() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setDeviceSource(value.stream().map(item -> item.getDeviceSource() != null ? item.getDeviceSource() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setTime(value.stream().map(item -> item.getTime() != null ? item.getTime() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setThreshold(value.stream().map(item -> item.getThreshold() != null ? item.getThreshold() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setAlgName(value.get(0).getAlgName());
                patrolResultRef.setResultType("0");
                resultRefs.add(patrolResultRef);
            });
            patrolResultRefs = resultRefs;
        }

//        log.info("batchInsertReportData patrolResultRefs:" + patrolResultRefs);
        startTime = PrintUtil.useTime("SELECT RESULT", startTime);
//        List<BasePointAreaInfo> basePointAreaInfoList = patrolResultMapper.selectBaseInfoByMainId(mainId);
        List<BasePointAreaInfo> basePointAreaInfoList = patrolResultMapper.selectBaseInfoByMainIds(mainIds);
//        log.info("batchInsertReportData basePointAreaInfoList:" + basePointAreaInfoList);
        PrintUtil.useTime("AREA INQUERY", startTime);
        log.info("REPORTS SIZE: {}", patrolResultRefs.size());
        List<InspectionReportData> reportDatas = new ArrayList<>();
        List<InspectionReportImg> reportImages = new ArrayList<>();

        long okNum = 1L;
        long failNum = 1L;
        long defectNum = 1L;
        int index;
        for (index = 0; index < patrolResultRefs.size(); ++index) {
            PatrolResultRef patrolResultRef = patrolResultRefs.get(index);
            String devType = patrolResultRef.getDevType();
            BasePointAreaInfo basePointAreaInfo;
            try {
                basePointAreaInfo = basePointAreaInfoList.stream().filter((item) -> item != null && patrolResultRef.getDeviceId().equals(item.getDeviceId())).findFirst().get();
            } catch (Exception e) {
                log.error("[REPORT DETAIL] The point lacking belonging area: {}", patrolResultRef.getDeviceId());
                basePointAreaInfo = new BasePointAreaInfo();
            }

            InspectionReportData reportData = new InspectionReportData();
            reportData.setReportId(reportId);
            reportData.setArea(basePointAreaInfo.getAreaName());
            reportData.setTimeInterval(basePointAreaInfo.getJgName());
            reportData.setEqName(basePointAreaInfo.getMainName());
            reportData.setParts(basePointAreaInfo.getDeviceName());
            reportData.setPointName(basePointAreaInfo.getPatrolPointName());
            reportData.setDataSources(patrolResultRef.getDeviceSource());
            reportData.setAcquisitionTime(DateUtils.parse(DateUtils.yyyyMMddHHmmss2, patrolResultRef.getTime()));
            if ("1".equals(patrolResultRef.getResultType()) && validAlgTypes.contains(patrolResultRef.getAlgType())) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            } else {
                reportData.setInspectionResults(patrolResultRef.getDescription());
            }
            reportData.setAlgName(patrolResultRef.getAlgName());
            String threshold = patrolResultRef.getThreshold();
            if (StringUtils.isBlank(threshold)) {
                threshold = "";
            }
            if ("1".equals(patrolResultRef.getResultType()) && threshold.contains("sub_53")) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            }

            if ("1".equals(patrolResultRef.getResultType()) && (threshold.contains("sub_52") || threshold.contains("sub_53"))
                    && !"0".equals(patrolResultRef.getValue())
                    && !"1".equals(patrolResultRef.getValue())
                    && !"-1".equals(patrolResultRef.getValue())
                    && !"check image".equals(patrolResultRef.getValue())) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            }

            String pointStatus = patrolResultRef.getPointStatus();
            String resultType = patrolResultRef.getResultType();
//            log.info("[RESULT] pointStatus: {}, patrolResultRef: {}", pointStatus, patrolResultRef);
//            if(pointStatus == null) {
//                continue;
//            } else if (pointStatus.equals("0")) {
//                reportData.setPointStatus(messageUtils.get("异常"));
//                reportData.setCode(failNum);
//                ++failNum;
//            } else if (pointStatus.equals("1")) {
//                reportData.setPointStatus(messageUtils.get("待人工确认"));
//                reportData.setCode(confirmNum);
//                ++confirmNum;
//            } else {
//                reportData.setPointStatus(messageUtils.get("正常"));
//                reportData.setCode(okNum);
//                ++okNum;
//            }
            log.info("[RESULT] resultType: {}, patrolResultRef: {}", resultType, patrolResultRef);
            if (resultType == null) {
                continue;
            } else if (resultType.equals("0")) {
                reportData.setPointStatus(messageUtils.get("缺陷"));
                // 缺陷编号
                reportData.setCode(defectNum);
                ++defectNum;
            } else if (resultType.equals("1")) {
                reportData.setPointStatus(messageUtils.get("正常"));
                reportData.setCode(okNum);
                ++okNum;
            } else {
                reportData.setPointStatus(messageUtils.get("异常"));
                // 异常编号
                reportData.setCode(failNum);
                ++failNum;
            }

            final String reportDataId = reportId + "_" + (100000 + index);
            reportData.setLineId(reportDataId);
            reportDatas.add(reportData);
            log.info("batchInsertReportData reportData:" + reportData);
            String resultContent = patrolResultRef.getResultContent();
            //List<resultList> results = JSONObject.parseObject(resultContent).getJSONArray("resultList").toJavaList(resultList.class);
            //String imgUrl = results.get(0).getResults().get(0).getResImageUrl();
            AnalyseResPoint analyseResPoint = JSONObject.parseObject(resultContent, AnalyseResPoint.class);
            String imgUrl = analyseResPoint.getResImageUrl();

            if (StringUtils.isEmpty(imgUrl)) {
                imgUrl = patrolResultRef.getFilePath().split(StringUtils.COMMA)[0];
            }

            InspectionReportImg reportImg = new InspectionReportImg();
            reportImg.setReportInfoId(reportDataId);
            reportImg.setImg(imgUrl);
            reportImg.setImgSrc(imgUrl);
            reportImg.setImgType("0");
            reportImg.setCreatTime(new Date());
            reportImages.add(reportImg);
            log.info("batchInsertReportData reportImg:" + reportImg);
        }

        index = reportDatas.size() / 50;
        if (reportDatas.size() % 50 > 0) {
            ++index;
        }

        log.info("[REPORT] BATCH INSERT PROGRESS: reportDatas size: {}", reportDatas.size());
        for (int j = 0; j < reportDatas.size(); j += 50) {
            log.info("[REPORT] BATCH INSERT PROGRESS: {}/{}", j / 50 + 1, j % 50 + 1);
            int end = j + 50;
            if (end > reportDatas.size() - 1) {
                end = reportDatas.size();
            }

            inspectionReportDataMapper.batchInsertInspectionReportData(reportDatas.subList(j, end));
            inspectionReportImgMapper.batchInsertInspectionReportImg(reportImages.subList(j, end));
        }
    }

    public void batchInsertReportData_shaoxing(String reportId, List<PatrolResultRef> patrolResultRefs, List<BasePointAreaInfo> basePointAreaInfoList, List<Long> lineIds) {
        Map<Long, Map<String, Long>> taskCounterMap = new HashMap<>();

        // 为每个任务初始化计数器
        for (Long item : lineIds) {
            Map<String, Long> counter = new HashMap<>();
            counter.put("defect", 0L);
            counter.put("ok", 0L);
            counter.put("fail", 0L);
            taskCounterMap.put(item, counter);
        }

        log.info("REPORTS SIZE: {}", patrolResultRefs.size());
        List<InspectionReportData> reportDatas = new ArrayList<>();
        List<InspectionReportImg> reportImages = new ArrayList<>();

        long okNum = 0L;
        long failNum = 0L;
        long defectNum = 0L;
        int index;
        for (index = 0; index < patrolResultRefs.size(); ++index) {
            PatrolResultRef patrolResultRef = patrolResultRefs.get(index);
            String devType = patrolResultRef.getDevType();
            // 获取该结果所属的任务名
            String resultTaskName = patrolResultRef.getTaskName();
            String taskPatrolledId = patrolResultRef.getTaskPatrolledId();
            Long mainId = patrolResultRef.getMainId();
            BasePointAreaInfo basePointAreaInfo;
            try {
                basePointAreaInfo = basePointAreaInfoList.stream().filter((item) -> item != null && patrolResultRef.getDeviceId().equals(item.getDeviceId())).findFirst().get();
            } catch (Exception e) {
                log.error("[REPORT DETAIL] The point lacking belonging area: {}", patrolResultRef.getDeviceId());
                basePointAreaInfo = new BasePointAreaInfo();
            }

            InspectionReportData reportData = new InspectionReportData();
            reportData.setReportId(reportId);
            reportData.setArea(basePointAreaInfo.getAreaName());
            reportData.setTimeInterval(basePointAreaInfo.getJgName());
            reportData.setEqName(basePointAreaInfo.getMainName());
            reportData.setParts(basePointAreaInfo.getDeviceName());
            reportData.setPointName(basePointAreaInfo.getPatrolPointName());
            reportData.setDataSources(patrolResultRef.getDeviceSource());
            reportData.setAcquisitionTime(DateUtils.parse(DateUtils.yyyyMMddHHmmss2, patrolResultRef.getTime()));
            reportData.setTaskName(resultTaskName);
            reportData.setTaskPatrolledId(taskPatrolledId);
            reportData.setTaskResultId(String.valueOf(mainId));
            if ("1".equals(patrolResultRef.getResultType()) && validAlgTypes.contains(patrolResultRef.getAlgType())) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            } else {
                reportData.setInspectionResults(patrolResultRef.getDescription());
            }
            reportData.setAlgName(patrolResultRef.getAlgName());
            String threshold = patrolResultRef.getThreshold();
            if (StringUtils.isBlank(threshold)) {
                threshold = "";
            }
            if ("1".equals(patrolResultRef.getResultType()) && threshold.contains("sub_53")) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            }

            if ("1".equals(patrolResultRef.getResultType()) && (threshold.contains("sub_52") || threshold.contains("sub_53"))
                    && !"0".equals(patrolResultRef.getValue())
                    && !"1".equals(patrolResultRef.getValue())
                    && !"-1".equals(patrolResultRef.getValue())
                    && !"check image".equals(patrolResultRef.getValue())) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            }

            // 给读数增加单位
            String resValue = resultAnalysisUtils.addUnit2Value(reportData.getInspectionResults(), patrolResultRef.getAlgType(), patrolResultRef.getUnit());
            reportData.setInspectionResults(resValue);

            String pointStatus = patrolResultRef.getPointStatus();
            String resultType = patrolResultRef.getResultType();
            log.info("[RESULT] resultType: {}, patrolResultRef: {}", resultType, patrolResultRef);
            if (resultType == null) {
                continue;
            } else if (resultType.equals("0")) {
                reportData.setPointStatus(messageUtils.get("缺陷"));
                // 按任务统计异常编号
                Map<String, Long> counter = taskCounterMap.get(mainId);
                if (counter != null) {
                    counter.put("defect", counter.get("defect") + 1);
                    reportData.setCode(counter.get("defect"));
                    defectNum++;
                } else {
                    reportData.setCode(++defectNum);
                }
            } else if (resultType.equals("1")) {
                reportData.setPointStatus(messageUtils.get("正常"));
                // 按任务统计异常编号
                Map<String, Long> counter = taskCounterMap.get(mainId);
                if (counter != null) {
                    counter.put("ok", counter.get("ok") + 1);
                    reportData.setCode(counter.get("ok"));
                    okNum++;
                } else {
                    reportData.setCode(++okNum);
                }
            } else {
                reportData.setPointStatus(messageUtils.get("异常"));
                // 按任务统计异常编号
                Map<String, Long> counter = taskCounterMap.get(mainId);
                if (counter != null) {
                    counter.put("fail", counter.get("fail") + 1);
                    reportData.setCode(counter.get("fail"));
                    failNum++;
                } else {
                    reportData.setCode(++failNum);
                }
            }

            final String reportDataId = reportId + "_" + (100000 + index);
            reportData.setLineId(reportDataId);
            reportDatas.add(reportData);
            log.info("batchInsertReportData reportData:" + reportData);
            String resultContent = patrolResultRef.getResultContent();
            //List<resultList> results = JSONObject.parseObject(resultContent).getJSONArray("resultList").toJavaList(resultList.class);
            //String imgUrl = results.get(0).getResults().get(0).getResImageUrl();
            AnalyseResPoint analyseResPoint = JSONObject.parseObject(resultContent, AnalyseResPoint.class);
            String imgUrl = analyseResPoint.getResImageUrl();

            if (StringUtils.isEmpty(imgUrl)) {
                imgUrl = patrolResultRef.getFilePath().split(StringUtils.COMMA)[0];
            }

            InspectionReportImg reportImg = new InspectionReportImg();
            reportImg.setReportInfoId(reportDataId);
            reportImg.setImg(imgUrl);
            reportImg.setImgSrc(imgUrl);
            reportImg.setImgType("0");
            reportImg.setCreatTime(new Date());
            reportImages.add(reportImg);
            log.info("batchInsertReportData reportImg:" + reportImg);
        }

        index = reportDatas.size() / 50;
        if (reportDatas.size() % 50 > 0) {
            ++index;
        }

        log.info("[REPORT] BATCH INSERT PROGRESS: reportDatas size: {}", reportDatas.size());
        for (int j = 0; j < reportDatas.size(); j += 50) {
            log.info("[REPORT] BATCH INSERT PROGRESS: {}/{}", j / 50 + 1, j % 50 + 1);
            int end = j + 50;
            if (end > reportDatas.size() - 1) {
                end = reportDatas.size();
            }

            inspectionReportDataMapper.batchInsertInspectionReportData(reportDatas.subList(j, end));
            inspectionReportImgMapper.batchInsertInspectionReportImg(reportImages.subList(j, end));
        }
    }

    public void batchInsertReportData_Lingzhou(String reportId, List<BasePointAreaInfo> basePointAreaInfoList, String filter, List<PatrolResultRef> patrolResultRefs) {
        long startTime = System.currentTimeMillis();
        if ("0".equals(exportReportFlag)) {
            List<PatrolResultRef> resultRefs = new ArrayList<>();
            // 只导出缺陷
            patrolResultRefs = patrolResultRefs.stream().filter((item) -> "0".equals(item.getResultType())).collect(Collectors.toList());
            // 分组，按点位ID和算法类型进行分组
            Map<GroupKey, List<PatrolResultRef>> groupKeyListMap = patrolResultRefs.stream().collect(Collectors.groupingBy(item -> new GroupKey(item.getDeviceId(), item.getAlgType(), item.getTaskPatrolledId())));
            groupKeyListMap.forEach((key, value) -> {
                PatrolResultRef patrolResultRef = new PatrolResultRef();
                patrolResultRef.setDeviceId(key.objectId);
                patrolResultRef.setAlgType(key.algType);
                patrolResultRef.setDescription(value.stream().sorted(Comparator.comparing(PatrolResultRef::getFilter).reversed()).map(PatrolResultRef::getDescription).collect(Collectors.joining(",")));
                patrolResultRef.setValue(value.stream().sorted(Comparator.comparing(PatrolResultRef::getFilter).reversed()).map(PatrolResultRef::getValue).collect(Collectors.joining(",")));
                for (PatrolResultRef resultRef : value) {
                    // 初筛有缺陷，展示初筛结果
                    if ("1".equals(resultRef.getFilter()) && StringUtils.isEmpty(patrolResultRef.getResultContent())) {
                        patrolResultRef.setResultContent(resultRef.getResultContent());
                    }
                    if ("1".equals(resultRef.getFilter()) && StringUtils.isEmpty(patrolResultRef.getFilePath())) {
                        patrolResultRef.setFilePath(resultRef.getFilePath());
                    }
                    // 大模型有缺陷，展示大模型结果
                    if ("0".equals(resultRef.getFilter())) {
                        patrolResultRef.setResultContent(resultRef.getResultContent());
                        patrolResultRef.setFilePath(resultRef.getFilePath());
                    }
                }
                patrolResultRef.setDevType(value.stream().map(item -> item.getDevType() != null ? item.getDevType() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setDeviceSource(value.stream().map(item -> item.getDeviceSource() != null ? item.getDeviceSource() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setTime(value.stream().map(item -> item.getTime() != null ? item.getTime() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setThreshold(value.stream().map(item -> item.getThreshold() != null ? item.getThreshold() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setAlgName(value.get(0).getAlgName());
                patrolResultRef.setAlgType(value.get(0).getAlgType());
                patrolResultRef.setResultType("0");
                resultRefs.add(patrolResultRef);
            });
            patrolResultRefs = resultRefs;
        }

        startTime = PrintUtil.useTime("SELECT RESULT", startTime);
        PrintUtil.useTime("AREA INQUERY", startTime);
        log.info("REPORTS SIZE: {}", patrolResultRefs.size());
        List<InspectionReportData> reportDatas = new ArrayList<>();
        List<InspectionReportImg> reportImages = new ArrayList<>();

        long okNum = 1L;
        long failNum = 1L;
        long defectNum = 1L;
        int index;
        for (index = 0; index < patrolResultRefs.size(); ++index) {
            PatrolResultRef patrolResultRef = patrolResultRefs.get(index);
            BasePointAreaInfo basePointAreaInfo;
            try {
                basePointAreaInfo = basePointAreaInfoList.stream().filter((item) -> item != null && patrolResultRef.getDeviceId().equals(item.getDeviceId())).findFirst().get();
            } catch (Exception e) {
                log.error("[REPORT DETAIL] The point lacking belonging area: {}", patrolResultRef.getDeviceId());
                basePointAreaInfo = new BasePointAreaInfo();
            }

            InspectionReportData reportData = new InspectionReportData();
            reportData.setReportId(reportId);
            reportData.setArea(basePointAreaInfo.getAreaName());
            reportData.setTimeInterval(basePointAreaInfo.getJgName());
            reportData.setEqName(basePointAreaInfo.getMainName());
            reportData.setParts(basePointAreaInfo.getDeviceName());
            reportData.setPointName(basePointAreaInfo.getPatrolPointName());
            reportData.setDataSources(patrolResultRef.getDeviceSource());
            reportData.setAcquisitionTime(DateUtils.parse(DateUtils.yyyyMMddHHmmss2, patrolResultRef.getTime()));
            if ("1".equals(patrolResultRef.getResultType()) && validAlgTypes.contains(patrolResultRef.getAlgType())) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            } else {
                reportData.setInspectionResults(patrolResultRef.getDescription());
            }
            reportData.setAlgName(patrolResultRef.getAlgName());
            String threshold = patrolResultRef.getThreshold();
            if (StringUtils.isBlank(threshold)) {
                threshold = "";
            }
            if ("1".equals(patrolResultRef.getResultType()) && threshold.contains("sub_53")) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            }

            if ("1".equals(patrolResultRef.getResultType()) && (threshold.contains("sub_52") || threshold.contains("sub_53"))
                    && !"0".equals(patrolResultRef.getValue())
                    && !"1".equals(patrolResultRef.getValue())
                    && !"-1".equals(patrolResultRef.getValue())
                    && !"check image".equals(patrolResultRef.getValue())) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            }

            String resultType = patrolResultRef.getResultType();
            log.info("[RESULT] resultType: {}, patrolResultRef: {}", resultType, patrolResultRef);
            if (resultType == null) {
                continue;
            } else if (resultType.equals("0")) {
                reportData.setPointStatus(messageUtils.get("缺陷"));
                // 缺陷编号
                reportData.setCode(defectNum);
                ++defectNum;
            } else if (resultType.equals("1")) {
                reportData.setPointStatus(messageUtils.get("正常"));
                reportData.setCode(okNum);
                ++okNum;
            } else {
                reportData.setPointStatus(messageUtils.get("异常"));
                // 异常编号
                reportData.setCode(failNum);
                ++failNum;
            }

            final String reportDataId = reportId + "_" + (100000 + index);
            reportData.setLineId(reportDataId);
            reportDatas.add(reportData);
            log.info("batchInsertReportData reportData:" + reportData);
            String resultContent = patrolResultRef.getResultContent();
            AnalyseResPoint analyseResPoint = JSONObject.parseObject(resultContent, AnalyseResPoint.class);
            String imgUrl = analyseResPoint.getResImageUrl();

            if (StringUtils.isEmpty(imgUrl)) {
                imgUrl = patrolResultRef.getFilePath().split(StringUtils.COMMA)[0];
            }

            InspectionReportImg reportImg = new InspectionReportImg();
            reportImg.setReportInfoId(reportDataId);
            reportImg.setImg(imgUrl);
            reportImg.setImgSrc(imgUrl);
            reportImg.setImgType("0");
            reportImg.setCreatTime(new Date());
            reportImages.add(reportImg);
            log.info("batchInsertReportData reportImg:" + reportImg);
        }

        index = reportDatas.size() / 50;
        if (reportDatas.size() % 50 > 0) {
            ++index;
        }

        log.info("[REPORT] BATCH INSERT PROGRESS: reportDatas size: {}", reportDatas.size());
        for (int j = 0; j < reportDatas.size(); j += 50) {
            log.info("[REPORT] BATCH INSERT PROGRESS: {}/{}", j / 50 + 1, j % 50 + 1);
            int end = j + 50;
            if (end > reportDatas.size() - 1) {
                end = reportDatas.size();
            }

            inspectionReportDataMapper.batchInsertInspectionReportData(reportDatas.subList(j, end));
            inspectionReportImgMapper.batchInsertInspectionReportImg(reportImages.subList(j, end));
        }
    }

    public void batchInsertReportDataV2(String reportId, String mainId, String filter) {
        long startTime = System.currentTimeMillis();
        long okNum = 1L;
        long failNum = 1L;
        long confirmNum = 1L;
        List<PatrolResultRef> patrolResultRefs = patrolResultMapper.selectResultRefByLineId(mainId);
        patrolResultRefs = patrolResultRefs.stream().filter((item) -> {
            return filter.equals(item.getFilter());
        }).collect(Collectors.toList());
        startTime = PrintUtil.useTime("查询结果关联信息", startTime);
        List<BasePointAreaInfo> areas = patrolResultMapper.selectBaseInfoByMainIdByReport(mainId);
        List<AlgInfo> algInfos = patrolResultMapper.selectAlgInfo(new PatrolResult());
        PrintUtil.useTime("查询地区", startTime);
        log.info("[报告点位数量]: {}", patrolResultRefs.size());
        List<InspectionReportData> reportDatas = new ArrayList<>();
        List<InspectionReportImg> reportImages = new ArrayList<>();

        int i;
        for (i = 0; i < patrolResultRefs.size(); ++i) {
            PatrolResultRef ref = patrolResultRefs.get(i);
            ref.setAlgName(algInfos.stream().filter((alg) -> {
                return alg.getAlgSubtypeCode().equals(ref.getAlgType());
            }).findFirst().get().getAlgSubtypeName());
            String type = ref.getDevType();

            BasePointAreaInfo area;
            try {
                area = areas.stream().filter((item) -> {
                    return item != null && ref.getDeviceId().equals(item.getPatrolPointId());
                }).findFirst().get();
            } catch (Exception e) {
                log.error("[整理报告明细] 该点位没有所属区域: {}", ref.getDeviceId());
                area = new BasePointAreaInfo();
            }

            Map<String, String> map = null;
            BasePointAreaInfo basePointAreaInfo;
            if(StringUtils.isNotNull(area.getEqpBookId())) {
                basePointAreaInfo = new BasePointAreaInfo();
                basePointAreaInfo.setEqpBookId(area.getEqpBookId());
                map = patrolResultMapper.selectDeviceNameById(basePointAreaInfo);
            }

            if(StringUtils.isNotNull(area.getChannelId())) {
                basePointAreaInfo = new BasePointAreaInfo();
                basePointAreaInfo.setChannelId(area.getChannelId());
                map = patrolResultMapper.selectDeviceNameById(basePointAreaInfo);
            }

            InspectionReportData reportData = new InspectionReportData();
            reportData.setReportId(reportId);
            reportData.setArea(area.getAreaName());
            reportData.setTimeInterval(area.getJgName());
            reportData.setEqName(area.getMainName());
            reportData.setParts(area.getDeviceName());
            reportData.setPointName(area.getPatrolPointName());
            reportData.setAlgName(ref.getAlgName());
            if(type.equals("0") || type.equals("1")) {
                reportData.setDataSources(map.get("device_source") + "/" + map.get("patrol_device_name"));
            } else {
                reportData.setDataSources(map.get("device_source") + "/" + map.get("channel_name"));
            }

            try {
                reportData.setAcquisitionTime(DateUtil.parseDateTime(ref.getTime()));
            } catch (Exception e) {
                reportData.setAcquisitionTime(new Date());
            }

            String desc = ref.getResDesc();
            String resultContent;
            if("meter".equals(ref.getAlgType()) || "infrared".equals(ref.getAlgType())) {
                desc = ref.getResValue();
                AlgValue algValue = new AlgValue();
                resultContent = algValue.formatValue(desc);
                if(resultContent.equals("1")) {
                    desc = "采集图片为空";
                } else if(resultContent.equals("-1")) {
                    desc = "与样本有差异";
                }
            }

            reportData.setInspectionResults(desc);
            if("meter".equals(ref.getAlgType())) {
                if("0".equals(ref.getPointStatus())) {
                    reportData.setPointStatus(ref.getDescription() + "(" + ref.getResValue() + ")");
                } else {
                    reportData.setPointStatus(ref.getResValue());
                }
            } else {
                reportData.setPointStatus(ref.getDescription());
            }

            reportData.setPointStatus("异常");
            reportData.setCode(failNum);
            ++failNum;
            String reportDataId = reportId + "_" + (100000 + i);
            reportData.setLineId(reportDataId);
            reportDatas.add(reportData);
            resultContent = ref.getResultContent();
            AnalyseResPoint resPoint = JSONObject.parseObject(resultContent, AnalyseResPoint.class);
            String imgUrl = resPoint.getResImageUrl();
            if(StringUtils.isEmpty(imgUrl)) {
                imgUrl = ref.getFilePath().split(StringUtils.COMMA)[0];
            }

            InspectionReportImg reportImg = new InspectionReportImg();
            reportImg.setReportInfoId(reportDataId);
            reportImg.setImg(ref.getResImgUrl());
            reportImg.setImgSrc(ref.getResImgUrl());
            reportImg.setImgType("0");
            reportImg.setCreatTime(new Date());
            reportImages.add(reportImg);
        }

        i = reportDatas.size() / 50;
        if(reportDatas.size() % 50 > 0) {
            ++i;
        }

        for(int j = 0; j < reportDatas.size(); j += 50) {
            log.info("[批量插入报告明细] 进度: {}/{}", j / 50 + 1, j);
            int end = j + 50;
            if(end > reportDatas.size()) {
                end = reportDatas.size();
            }

            inspectionReportDataMapper.batchInsertInspectionReportData(reportDatas.subList(j, end));
            inspectionReportImgMapper.batchInsertInspectionReportImg(reportImages.subList(j, end));
        }

    }
    public String statisticsAnalyseNum(List<Long> lineIds, int totalNum) {
        int okNum = 0;
        int failNum = 0;
        int confirmNum = 0;
//        List<ResultAnalysis> analyses = resultAnalysisMapper.selectResultAnalysisListByMainId(new ResultAnalysis(mainId));
        List<ResultAnalysis> analyses = resultAnalysisMapper.selectResultAnalysisListByMainIds(lineIds);
        log.info("lineIds:{},statisticsAnalyseNum analyses:{}", lineIds, analyses);
        for (ResultAnalysis analyse : analyses) {
            String pointStatus = analyse.getPointStatus();
            if (pointStatus.equals("0")) {
                ++failNum;
            } else if (pointStatus.equals("1")) {
                ++okNum;
            } else if (pointStatus.equals("2")) {
                ++confirmNum;
            } else {
                log.error("【归档-统计分析数量】异常分析类型：{}", analyse.getPointStatus());
            }
        }

        int lastNum = totalNum - failNum - confirmNum;
        if (lastNum != okNum) {
            okNum = lastNum;
        }

//        return String.format("总点位：%d个,已检点位：%d个,未检点位：0个,正常点位：%d个,异常点位：%d个,待人工确认点位：%d个。", totalNum, totalNum, okNum, failNum, confirmNum);
        return String.format(messageUtils.get("总点位：%d个,已检点位：%d个,未检点位：0个,正常点位：%d个,异常点位：%d个,待人工确认点位：%d个。"), totalNum, totalNum, okNum, failNum, confirmNum);
    }

    public String statisticsAnalyseNumV3(List<Long> lineIds, String filter) {
        int okNum = 0;
        int failNum = 0;
        int confirmNum = 0;
        List<ResultAnalysis> analyses = resultAnalysisMapper.selectResultAnalysisListByMainIdsNew(lineIds, filter);
        int totalNum = analyses.size();
        log.info("lineIds:{},statisticsAnalyseNum analyses:{}", lineIds, analyses);
        for (ResultAnalysis analyse : analyses) {
            String resultType = analyse.getResultType();
            if (resultType.equals("0")) {
                ++confirmNum;
            } else if (resultType.equals("1")) {
                ++okNum;
            } else if (resultType.equals("2")) {
                ++failNum;
            }
        }
//
//        int lastNum = totalNum - failNum - confirmNum;
//        if (lastNum != okNum) {
//            okNum = lastNum;
//        }

//        return String.format("总点位：%d个,已检点位：%d个,未检点位：0个,正常点位：%d个,异常点位：%d个,待人工确认点位：%d个。", totalNum, totalNum, okNum, failNum, confirmNum);
//        return String.format(messageUtils.get("总点位：%d个,已检点位：%d个,未检点位：0个,正常点位：%d个,异常点位：%d个,待人工确认点位：%d个。"), totalNum, totalNum, okNum, failNum, confirmNum);
        return String.format(messageUtils.get("缺陷总数：%d个"), confirmNum);
    }

    public String statisticsAnalyseNumLingZhou(List<Long> lineIds) {
        int okNum = 0;
        int failNum = 0;
        int confirmNum = 0;
        int qxNumFilter = 0;
        int ycNumFilter = 0;
        int qxNumAI = 0;
        List<ResultAnalysis> analysesAI = resultAnalysisMapper.selectResultAnalysisListByMainIdsNew(lineIds, "0");
        List<ResultAnalysis> analyseFilter = resultAnalysisMapper.selectResultAnalysisListByMainIdsNew(lineIds, "1");
        Map<String, ResultAnalysis> keyToAnalysisMap = new HashMap<>();
        for (ResultAnalysis resultAnalysis : analysesAI) {
            keyToAnalysisMap.put(resultAnalysis.getAlgType() + "_" + resultAnalysis.getObjectId(), resultAnalysis);
            if ("0".equals(resultAnalysis.getResultType())) {
                ++qxNumAI;
            }
        }
        for (ResultAnalysis analyse : analyseFilter) {
            keyToAnalysisMap.putIfAbsent(analyse.getAlgType() + "_" + analyse.getObjectId(), analyse);
            if ("0".equals(analyse.getResultType())) {
                ++qxNumFilter;
            } else if ("2".equals(analyse.getResultType())) {
                ++ycNumFilter;
            }
        }


        int totalNum = keyToAnalysisMap.size();

        if ("0".equals(exportReportFlag)) {
            for (ResultAnalysis analyse : keyToAnalysisMap.values()) {
                String resultType = analyse.getResultType();
                if (resultType.equals("0")) {
                    ++confirmNum;
                } else if (resultType.equals("1")) {
                    ++okNum;
                } else if (resultType.equals("2")) {
                    ++failNum;
                }
            }
            return String.format(messageUtils.get("缺陷点位：%d个。"), confirmNum);
        } else {
//            return String.format(messageUtils.get("本次任务巡视总点位：%d个,已检点位：%d个,未检点位：0个,正常点位：%d个,异常点位：%d个,缺陷点位：%d个。"), totalNum, totalNum, okNum, failNum, confirmNum);
            return String.format(messageUtils.get("本次任务巡视总点位：%d个，已检点位：%d个，未检点位：0个，初筛缺陷点位：%d个，异常点位：%d个；大模型复检缺陷点位：%d个。"), totalNum, totalNum, qxNumFilter, ycNumFilter, qxNumAI);
        }
    }

    public String statisticsAnalyseNumShaoxing(List<Long> lineIds) {
        int okNum = 0;
        int failNum = 0;
        int confirmNum = 0;
        List<ResultAnalysis> analyses = resultAnalysisMapper.selectResultAnalysisListByMainIdsNew(lineIds, null);
        if ("0".equals(exportReportFlag)) {
            // 直导缺陷
            List<ResultAnalysis> qxResultAnalyses = analyses.stream().filter(analysis -> "0".equals(analysis.getResultType())).collect(Collectors.toList());
            long count = qxResultAnalyses.stream().map(analysis -> analysis.getAlgType() + "|" + analysis.getObjectId() + "|" + analysis.getTaskPatrolId()).distinct().count();
            return String.format(messageUtils.get("缺陷数量：%d个。"), count);
        } else {
            int totalNum = analyses.size();
            log.info("lineIds:{},statisticsAnalyseNum analyses size:{}", lineIds, totalNum);
            for (ResultAnalysis analyse : analyses) {
                String resultType = analyse.getResultType();
                if ("0".equals(resultType)) {
                    ++confirmNum;
                } else if (("1").equals(resultType)) {
                    ++okNum;
                } else if (("2").equals(resultType)) {
                    ++failNum;
                }
            }
            return String.format(messageUtils.get("本次任务巡视总结果数量：%d个，正常结果数量：%d个，异常结果数量：%d个，缺陷结果数量：%d个。"), totalNum, okNum, failNum, confirmNum);
        }
    }

    public String statisticsAnalyseNumV2(String mainId, String filter) {
        int okNum = 0;
        int failNum = 0;
        int confirmNum = 0;
        ResultAnalysis resultAnalysis = new ResultAnalysis(mainId);
        resultAnalysis.setFilter(filter);
        List<ResultAnalysis> analyses = resultAnalysisMapper.selectResultAnalysisListByMainIdNew(resultAnalysis);

        for (ResultAnalysis analyse : analyses) {
            String var10 = analyse.getResStatus();
            byte var11 = -1;
            switch (var10.hashCode()) {
                case 49:
                    if (var10.equals("1")) {
                        var11 = 0;
                    }
                    break;
                case 50:
                    if (var10.equals("2")) {
                        var11 = 1;
                    }
                    break;
                case 51:
                    if (var10.equals("3")) {
                        var11 = 2;
                    }
            }

            switch (var11) {
                case 0:
                    ++failNum;
                    break;
                case 1:
                    ++okNum;
                    break;
                case 2:
                    ++confirmNum;
                    break;
                default:
                    log.error("【归档-统计分析数量】异常分析类型：{}", analyse.getPointStatus());
            }
        }

        int totalNum = analyses.size();
        int lastNum = totalNum - failNum - confirmNum;
        if (lastNum != okNum) {
            ;
        }

        return String.format("缺陷总数：%d个", totalNum);
    }

    public List<PatrolResultRef> selectResultRefByLineId(String mainId) {
        return this.patrolResultMapper.selectResultRefByLineId(mainId);
    }

    public List<BasePointAreaInfo> selectBaseInfoByMainId(String mainId) {
        return this.patrolResultMapper.selectBaseInfoByMainId(mainId);
    }

    @Override
    public List<InspectionPointResultVo> inspectResult(InspectionPointParam inspectionPointParam) {
        return this.patrolResultMapper.inspectResult(inspectionPointParam);
    }

    @Override
    public BasedataEqpBookChannel selectChannelName(String channelCode) {
        return patrolResultMapper.selectChannelName(channelCode);
    }

    @Override
    public List<PatrolResult> selectPatrolResultListByMainIds(List<Long> mainIds) {
        return patrolResultMapper.selectPatrolResultListByMainIds(mainIds);
    }

    @Override
    public InspectionReport getInspectionReport(List<Long> lineIds, PatrolTaskResultMain patrolTaskResultMain) {
        List<String> taskPatrolledIds = patrolTaskResultMain.getTaskPatrolledIds();
        // 巡视统计描述
        String patrolStatistics = "";
        // 查询任务状态信息
        List<PatrolTaskStatus> patrolTaskStatuses = patrolTaskStatusMapper.selectPatrolTaskStatusListByTaskPatrolledIds(taskPatrolledIds);
        List<Date> startTimes = patrolTaskStatuses.stream().map(PatrolTaskStatus::getStartTime).sorted().collect(Collectors.toList());
        List<String> endTimes = patrolTaskStatuses.stream().map(PatrolTaskStatus::getEndTime).sorted().collect(Collectors.toList());

        // 查询巡视结果信息
        List<PatrolResultRef> patrolResultRefs = patrolResultMapper.selectResultRefByLineIds(lineIds, null);
        List<String> taskNames = patrolTaskStatuses.stream().map(PatrolTaskStatus::getTaskName).distinct().collect(Collectors.toList());
        String taskName = StringUtils.join(taskNames, ",");
        Map<String, String> stationMap = patrolResultMapper.selectBasedataStation();
        String stationName = stationMap.get("station_name");
        String stationType = stationMap.get("station_type");
        String voltLevel = stationMap.get("volt_level");
//        AjaxResult ajaxResult = feignBasedataAreaService.evnList();
//        List<JSONObject> jsonObjects = JSONObject.parseArray(JSON.toJSONString(ajaxResult.get("data")), JSONObject.class);
//        log.info("EVN LIST: " + jsonObjects);
//        List<String> envoList = new ArrayList<>();
//        for (JSONObject jsonObject : jsonObjects) {
//            String typeName = jsonObject.getString("typeName");
//            String valueUnit = jsonObject.getString("valueUnit");
//            if (StringUtils.isEmpty(valueUnit) || StringUtils.isEmpty(typeName)) {
//                continue;
//            }
//            envoList.add(typeName + ":" + valueUnit);
//        }

        InspectionReport report = new InspectionReport();
        report.setInspectionDate(new Date());
        report.setInspectionStartTime(startTimes.get(0));
        report.setInspectionEndTime(DateUtils.parseDate(endTimes.get(endTimes.size() - 1)));
//        report.setTaskId(String.valueOf(task.getTaskId()));
//        report.setEnvInfo(StringUtils.join(envoList,","));
//        report.setTaskPatrolledId(taskPatrolId);
        report.setInspectionTaskName(taskName);
        report.setDescription(patrolTaskResultMain.getTaskResult());
        report.setCheckPerson(patrolTaskResultMain.getCheckPerson());
        report.setCheckTime(new Date());
        report.setStationName(stationName);
        report.setVoltLevel(StringUtils.isEmpty(voltLevel) ? voltage : voltLevel);
//        report.setFilter(String.valueOf(i));
        report.setStationType(stationType);
        Map<GroupKey, List<PatrolResultRef>> groupKeyListMap;
        if ("0".equals(exportReportFlag)) {
            List<PatrolResultRef> resultRefs = new ArrayList<>();
            // 只导出缺陷
            patrolResultRefs = patrolResultRefs.stream().filter((item) -> "0".equals(item.getResultType())).collect(Collectors.toList());
            // 分组，按点位ID和算法类型进行分组
            groupKeyListMap = patrolResultRefs.stream().collect(Collectors.groupingBy(item -> new GroupKey(item.getDeviceId(), item.getAlgType(), item.getTaskPatrolledId())));
            groupKeyListMap.forEach((key, value) -> {
                PatrolResultRef patrolResultRef = new PatrolResultRef();
                patrolResultRef.setDeviceId(key.objectId);
                patrolResultRef.setAlgType(key.algType);
                patrolResultRef.setDescription(value.stream().sorted(Comparator.comparing(PatrolResultRef::getFilter).reversed()).map(PatrolResultRef::getDescription).collect(Collectors.joining(",")));
                patrolResultRef.setValue(value.stream().sorted(Comparator.comparing(PatrolResultRef::getFilter).reversed()).map(PatrolResultRef::getValue).collect(Collectors.joining(",")));
                for (PatrolResultRef resultRef : value) {
                    // 初筛有缺陷，展示初筛结果
                    if ("1".equals(resultRef.getFilter()) && StringUtils.isEmpty(patrolResultRef.getResultContent())) {
                        patrolResultRef.setResultContent(resultRef.getResultContent());
                    }
                    if ("1".equals(resultRef.getFilter()) && StringUtils.isEmpty(patrolResultRef.getFilePath())) {
                        patrolResultRef.setFilePath(resultRef.getFilePath());
                    }
                    // 大模型有缺陷，展示大模型结果
                    if ("0".equals(resultRef.getFilter())) {
                        patrolResultRef.setResultContent(resultRef.getResultContent());
                        patrolResultRef.setFilePath(resultRef.getFilePath());
                    }
                }
                patrolResultRef.setDevType(value.stream().map(item -> item.getDevType() != null ? item.getDevType() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setDeviceSource(value.stream().map(item -> item.getDeviceSource() != null ? item.getDeviceSource() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setTime(value.stream().map(item -> item.getTime() != null ? item.getTime() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setThreshold(value.stream().map(item -> item.getThreshold() != null ? item.getThreshold() : "").distinct().findFirst().orElse(""));
                patrolResultRef.setAlgName(value.get(0).getAlgName());
                patrolResultRef.setResultType("0");
                resultRefs.add(patrolResultRef);
            });
            patrolResultRefs = resultRefs;
        } else {
            groupKeyListMap = patrolResultRefs.stream().collect(Collectors.groupingBy(item -> new GroupKey(item.getDeviceId(), item.getAlgType(), item.getTaskPatrolledId())));
            List<PatrolResultRef> processedRefs = new ArrayList<>();
            for (Map.Entry<GroupKey, List<PatrolResultRef>> entry : groupKeyListMap.entrySet()) {
                List<PatrolResultRef> value = entry.getValue();
                GroupKey key = entry.getKey();
                String algType = key.algType;
                List<PatrolResultRef> filterResults = value.stream().filter(item -> "1".equals(item.getFilter())).collect(Collectors.toList());
                List<PatrolResultRef> AIResults = value.stream().filter(item -> "0".equals(item.getFilter())).collect(Collectors.toList());
                PatrolResultRef filterResult = filterResults.isEmpty() ? null : filterResults.get(0);
                PatrolResultRef AIResult = AIResults.isEmpty() ? null : AIResults.get(0);

                if (AlgConstants.BIG_MODEL_ALG_LIST.contains(algType)) {
                    // 表计处理
                    if (filterResult != null && AIResult != null) {
                        String filterResultType = filterResult.getResultType();
                        String AIResultType = AIResult.getResultType();
                        if ("1".equals(filterResultType)) { // 初筛正常
                            // 只归档大模型
                            processedRefs.add(AIResult);
                        } else if ("0".equals(filterResultType)) { // 初筛缺陷
                            if ("1".equals(AIResultType)) {
                                // 分开：初筛缺陷，大模型正常
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            } else if ("0".equals(AIResultType)) {
                                // 合并：初筛缺陷，大模型缺陷
                                PatrolResultRef merged = mergePatrolResultRef(filterResult, AIResult, "0");
                                processedRefs.add(merged);
                            } else if ("2".equals(AIResultType)) {
                                // 分开：初筛缺陷，大模型异常
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            }
                        } else if ("2".equals(filterResultType)) { // 初筛异常
                            if ("1".equals(AIResultType)) {
                                // 分开：初筛异常，大模型正常
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            } else if ("0".equals(AIResultType)) {
                                // 分开：初筛异常，大模型缺陷
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            } else if ("2".equals(AIResultType)) {
                                // 合并：初筛异常，大模型异常
                                PatrolResultRef merged = mergePatrolResultRef(filterResult, AIResult, "2");
                                processedRefs.add(merged);
                            }
                        } else {
                            // 未知类型，都添加
                            processedRefs.add(filterResult);
                            processedRefs.add(AIResult);
                        }
                    } else if (filterResult != null) {
                        processedRefs.add(filterResult);
                    } else if (AIResult != null) {
                        processedRefs.add(AIResult);
                    }
                } else {
                    // 外观处理
                    if (filterResult != null && AIResult != null) {
                        String filterResultType = filterResult.getResultType();
                        String AIResultType = AIResult.getResultType();
                        if ("0".equals(filterResultType)) { // 初筛缺陷
                            if ("1".equals(AIResultType)) {
                                // 分开：初筛缺陷，大模型正常
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            } else if ("0".equals(AIResultType)) {
                                // 合并：初筛缺陷，大模型缺陷
                                PatrolResultRef merged = mergePatrolResultRef(filterResult, AIResult, "0");
                                processedRefs.add(merged);
                            } else if ("2".equals(AIResultType)) {
                                // 分开：初筛缺陷，大模型异常
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            } else {
                                // 未知，都添加
                                processedRefs.add(filterResult);
                                processedRefs.add(AIResult);
                            }
                        } else {
                            // 初筛不是缺陷但有大模型（理论上不应出现），为保数据完整都添加
                            processedRefs.add(filterResult);
                            processedRefs.add(AIResult);
                        }
                    } else if (filterResult != null) {
                        processedRefs.add(filterResult);
                    } else if (AIResult != null) {
                        processedRefs.add(AIResult);
                    }
                }
            }
            patrolResultRefs = processedRefs;
        }

        List<BasePointAreaInfo> basePointAreaInfoList = patrolResultMapper.selectBaseInfoByMainIds(lineIds);
//        log.info("batchInsertReportData basePointAreaInfoList:" + basePointAreaInfoList);
        log.info("REPORTS SIZE: {}", patrolResultRefs.size());
        List<InspectionReportData> reportDatas = new ArrayList<>();

        long okNum = 0L;
        long failNum = 0L;
        long defectNum = 0L;
        int index;
        for (index = 0; index < patrolResultRefs.size(); ++index) {
            PatrolResultRef patrolResultRef = patrolResultRefs.get(index);
            String devType = patrolResultRef.getDevType();
            BasePointAreaInfo basePointAreaInfo;
            try {
                basePointAreaInfo = basePointAreaInfoList.stream().filter((item) -> item != null && patrolResultRef.getDeviceId().equals(item.getDeviceId())).findFirst().get();
            } catch (Exception e) {
                log.error("[REPORT DETAIL] The point lacking belonging area: {}", patrolResultRef.getDeviceId());
                basePointAreaInfo = new BasePointAreaInfo();
            }

            InspectionReportData reportData = new InspectionReportData();
            reportData.setArea(basePointAreaInfo.getAreaName());
            reportData.setTimeInterval(basePointAreaInfo.getJgName());
            reportData.setEqName(basePointAreaInfo.getMainName());
            reportData.setParts(basePointAreaInfo.getDeviceName());
            reportData.setPointName(basePointAreaInfo.getPatrolPointName());
            reportData.setDataSources(patrolResultRef.getDeviceSource());
            reportData.setAcquisitionTime(DateUtils.parse(DateUtils.yyyyMMddHHmmss2, patrolResultRef.getTime()));
            if ("1".equals(patrolResultRef.getResultType()) && validAlgTypes.contains(patrolResultRef.getAlgType())) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            } else {
                reportData.setInspectionResults(patrolResultRef.getDescription());
            }
            reportData.setAlgName(patrolResultRef.getAlgName());
            String threshold = patrolResultRef.getThreshold();
            if (StringUtils.isBlank(threshold)) {
                threshold = "";
            }
            if ("1".equals(patrolResultRef.getResultType()) && threshold.contains("sub_53")) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            }

            if ("1".equals(patrolResultRef.getResultType()) && (threshold.contains("sub_52") || threshold.contains("sub_53"))
                    && !"0".equals(patrolResultRef.getValue())
                    && !"1".equals(patrolResultRef.getValue())
                    && !"-1".equals(patrolResultRef.getValue())
                    && !"check image".equals(patrolResultRef.getValue())) {
                reportData.setInspectionResults(patrolResultRef.getValue());
            }

            String resultType = patrolResultRef.getResultType();
//            log.info("[RESULT] resultType: {}, patrolResultRef: {}", resultType, patrolResultRef);
            if (resultType == null) {
                continue;
            } else if (resultType.equals("0")) {
                reportData.setPointStatus(messageUtils.get("缺陷"));
                // 缺陷编号
                ++defectNum;
                reportData.setCode(defectNum);
            } else if (resultType.equals("1")) {
                reportData.setPointStatus(messageUtils.get("正常"));
                ++okNum;
                reportData.setCode(okNum);
            } else {
                reportData.setPointStatus(messageUtils.get("异常"));
                // 异常编号
                ++failNum;
                reportData.setCode(failNum);
            }
            String resultContent = patrolResultRef.getResultContent();
            AnalyseResPoint analyseResPoint = JSONObject.parseObject(resultContent, AnalyseResPoint.class);
            String imgUrl = analyseResPoint.getResImageUrl();

            if (StringUtils.isEmpty(imgUrl)) {
                imgUrl = patrolResultRef.getFilePath().split(StringUtils.COMMA)[0];
            }
            List<InspectionReportImg> reportImages = new ArrayList<>();
            InspectionReportImg reportImg = new InspectionReportImg();
            reportImg.setImg(imgUrl);
            reportImg.setImgSrc(imgUrl);
            reportImg.setImgType("0");
            reportImg.setCreatTime(new Date());
            reportImages.add(reportImg);
            reportData.setReportImgList(reportImages);
            reportDatas.add(reportData);
        }
        long total = defectNum + okNum;
        if ("0".equals(exportReportFlag)) {
            patrolStatistics = String.format(messageUtils.get("缺陷数量：%d个。"), defectNum);
        } else {
            patrolStatistics = String.format(messageUtils.get("本次任务巡视总结果数量：%d个，正常结果数量：%d个，缺陷结果数量：%d个"), total, okNum, defectNum);
        }
        report.setPatrolStatistics(patrolStatistics);
        report.setReportDatalist(reportDatas);
        return report;
    }

    @Override
    public List<AlgInfo> selectPointAlgInfo(String patrolPointId) {
        return patrolResultMapper.selectPointAlgInfo(patrolPointId);
    }

    @Override
    public List<AlgInfo> selectAlgInfoByCode(String codes) {
        return patrolResultMapper.selectAlgInfoByCode(codes);
    }

    /**
     * 根据以下条件返回任务的全部或某设备类型的点位及其算法
     * @param sendCode 任务编码
     * @param specifiedAlg 设备唯一标识
     * @return 任务指定算法
     */
    @Override
    public List<String> selectAlgList(String taskCode, String sendCode, String specifiedAlg) {
        List<String> algList = new ArrayList<>();
        if ("摄像头".equals(sendCode)) {
            algList = patrolResultMapper.selectAlgList(taskCode, null, "2");
        } else {
            algList = patrolResultMapper.selectAlgList(taskCode, sendCode, null);
        }
        if (StringUtils.isNotEmpty(specifiedAlg)) {
            return algList.stream().map(item -> specifiedAlg).collect(Collectors.toList());
        }
        return algList;
    }

    private PatrolResultRef mergePatrolResultRef(PatrolResultRef filterResult, PatrolResultRef AIResult, String resultType) {
        PatrolResultRef merged = new PatrolResultRef();
        merged.setDeviceId(filterResult.getDeviceId());
        merged.setAlgType(filterResult.getAlgType());
        merged.setTaskPatrolledId(filterResult.getTaskPatrolledId());
        // 描述和值拼接
        merged.setDescription(filterResult.getDescription() + "," + AIResult.getDescription());
        merged.setValue(filterResult.getValue() + "," + AIResult.getValue());
        // 合并时使用大模型的结果内容和文件路径（因为图片要显示大模型分析后的图）
        merged.setResultContent(AIResult.getResultContent());
        merged.setFilePath(AIResult.getFilePath());
        // 其他字段取 filterResult
        merged.setDevType(filterResult.getDevType());
        merged.setDeviceSource(filterResult.getDeviceSource());
        merged.setTime(filterResult.getTime());
        merged.setThreshold(filterResult.getThreshold());
        merged.setAlgName(filterResult.getAlgName());
        merged.setResultType(resultType);
        return merged;
    }

    private static class GroupKey {
        private final String objectId;
        private final String algType;
        private final String taskPatrolled;

        public GroupKey(String objectId, String algType, String taskPatrolled) {
            this.objectId = objectId;
            this.algType = algType;
            this.taskPatrolled = taskPatrolled;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            GroupKey groupKey = (GroupKey) o;
            return Objects.equals(objectId, groupKey.objectId) && Objects.equals(algType, groupKey.algType) && Objects.equals(taskPatrolled, groupKey.taskPatrolled);

        }

        @Override
        public int hashCode() {
            return Objects.hash(objectId, algType, taskPatrolled);
        }

        @Override
        public String toString() {
            return "GroupKey{" +
                    "objectId='" + objectId + '\'' +
                    ", algType='" + algType + '\'' +
                    ", taskPatrolled='" + taskPatrolled + '\'' +
                    '}';
        }
    }

    public static void main(String[] args) {
        List<String> students = new ArrayList<>();
        students.add("s1");
        students.add("s2");
        students.add("s3");
        students.add("s4");
        students.add("s5");

        List<String> subStudents = students.subList(0, students.size() - 1);
        System.out.println(subStudents.size());
    }
}
