package com.rongwei.sfcommon.sys.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.rongwe.scentity.domian.*;
import com.rongwe.scentity.vo.CheckTemplateItemsVo;
import com.rongwe.scentity.vo.CompanyInfoVo;
import com.rongwe.scentity.vo.DistributeVo;
import com.rongwe.scentity.vo.FourColorSynchronizationVo;
import com.rongwei.rwcommon.base.exception.CustomException;
import com.rongwei.rwcommonentity.commonservers.domain.SysFileItemDo;
import com.rongwei.sfcommon.sys.dao.RiskSynchronizationDao;
import com.rongwei.sfcommon.sys.service.*;
import com.rongwei.sfcommon.utils.Result;
import com.sun.org.apache.xpath.internal.operations.Equals;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
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.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.rongwei.safecommon.utils.SaveConstans.AsyncAddress.*;
import static com.rongwei.safecommon.utils.SaveConstans.AsyncStatus.*;

@Service
public class SynchronizationImpl implements SynchronizationService {
    private static final Logger log = LoggerFactory.getLogger(SynchronizationImpl.class);

    @Autowired
    private AspRiskMapServiceImpl aspRiskMapService;

    @Autowired
    private AspRiskUnitService aspRiskUnitService;

    @Autowired
    private AspRiskEventService aspRiskEventService;

    @Autowired
    private AspRiskControlMeasuresService aspRiskControlMeasuresService;

    @Autowired
    private AspRiskProfileService aspRiskProfileService;

    @Autowired
    private RiskSynchronizationDao riskSynchronizationDao;

    @Autowired
    private CheckTemplateService checkTemplateService;

    @Autowired
    private CheckTemplateItemsService checkTemplateItemsService;

    @Value("${third-party.service.ip}")
    private String ip;

    private static final int BATCH_SIZE = 50;


    /**
     * 安全检查记录信息同步
     * 涉及到的表有：asp_theme_check_item 、aps_special_inspection_task、asp_check_discovery_item
     *
     * @param ids
     */
    @Override
    public void safeRecordSynchronizationList(List<String> ids) {

    }

    /**
     * 安全维护信息同步
     * 涉及到的表有：asp_check_template和asp_check_template_items
     *
     * @param ids
     */
    @Override
    public void safeMaintenanceSynchronizationList(List<String> ids) {
        /****************1.根据ID获取数据 ***********************/
        //校验一下ids集合不能为空
        if (ids.isEmpty()) {
            log.error("参数异常：{}", ids);
            throw new CustomException("请选择需要同步的数据！");
        }
        List<CheckTemplateDo> safeMaintenance = checkTemplateService.getBaseMapper().selectBatchIds(ids);
        if (safeMaintenance.isEmpty()) {
            return;
        }
        //收集List<CheckTemplateDo> safeMaintenance的id
        List<String> safeMaintenanceIds = safeMaintenance.stream()
                .map(CheckTemplateDo::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        //根据id查询asp_check_template_items
        List<CheckTemplateItemsDo> safeMaintenanceItems = new ArrayList<>();
        if (CollUtil.isNotEmpty(safeMaintenanceIds)) {
            safeMaintenanceItems = checkTemplateItemsService.getBaseMapper().selectList(new QueryWrapper<CheckTemplateItemsDo>()
                    .in("CHECKTEMPLATEID", safeMaintenanceIds));
        }
        //遍历集合List<CheckTemplateDo> safeMaintenance，将数据templatetype封装到List<CheckTemplateItemsDo>
        collectElement(safeMaintenance, safeMaintenanceItems);
        //收集企业编码
        collectCompanyId(safeMaintenanceItems, CheckTemplateItemsDo::getTenantid, CheckTemplateItemsDo::setEnterprisecode);

        /***************2.筛选出待同步的数据 ***********************/
        List<Map<String, Object>> waitSyncSafeMaintenanceData = new ArrayList<>();

        /************3.筛选出因为参数未必填导致无法推送的数据***********************/
        Map<String, String> checkErrorMap = new HashMap<>();
        // 保存每条记录对于的错误信息
        for (CheckTemplateItemsDo machine : safeMaintenanceItems) {
            collectSafeMaintenanceData(machine, waitSyncSafeMaintenanceData, checkErrorMap);
        }

        /************4.创建线程池，分批同步安全维护信息数据***********************/
        List<List<Map<String, Object>>> safeMaintenancePartitionedLists = Lists.partition(waitSyncSafeMaintenanceData, BATCH_SIZE);

        List<CheckTemplateDo> dataSave = new ArrayList<>();
        //4.1构建需要更新的 AspRiskMapDo 列表，包含四色图、分布信息和校验失败数据
        buildSafeMaintenanceDataSaveList(safeMaintenancePartitionedLists, checkErrorMap, ip, dataSave);

        /************5.所有批次处理完成后，统一更新记录***********************/
        if (!dataSave.isEmpty()) {
            checkTemplateService.updateBatchById(dataSave);
        }
    }

//============================================================================================================================================================================

    /**
     * 单元、事件和措施信息同步
     * 涉及到的表有：asp_risk_unit、asp_risk_event、asp_risk_control_measures
     *
     * @param ids
     */
    @Override
    public void unitSynchronizationList(List<String> ids) {
        /****************1.根据ID获取数据 ***********************/
        //校验一下ids集合不能为空
        if (ids == null || ids.isEmpty()) return;
        List<AspRiskUnitDo> riskUnit = aspRiskUnitService.getBaseMapper().selectBatchIds(ids);
        //收集企业编码
        collectCompanyId(riskUnit, AspRiskUnitDo::getTenantid, AspRiskUnitDo::setEnterprisecode);

        /***************2.筛选出待同步的数据 ***********************/
        List<Map<String, Object>> waitSyncUnitData = new ArrayList<>();
        List<Map<String, Object>> waitSyncEventData = new ArrayList<>();
        List<Map<String, Object>> waitSyncControlMeasureData = new ArrayList<>();

        /************3.筛选出因为参数未必填导致无法推送的数据***********************/
        Map<String, String> checkErrorMap = new HashMap<>();
        // 保存每条记录对于的待同步和错误信息
        for (AspRiskUnitDo machine : riskUnit) {
            collectUnitData(machine, waitSyncUnitData, checkErrorMap);
        }
        //遍历List<Map<String, Object>> waitSyncUnitData，拿到waitSyncUnitData的RISKUNIT_ID
        List<String> riskUnitIds = new ArrayList<>();
        collectDataIds(waitSyncUnitData, riskUnitIds, "RISKUNIT_ID");
        //  根据单元ID获取风险事件数据
        List<AspRiskEventDo> riskEvents = new ArrayList<>();
        if (CollUtil.isNotEmpty(riskUnitIds)) {
            riskEvents = aspRiskEventService.list(new QueryWrapper<AspRiskEventDo>()
                    .in("RISKUNITID", riskUnitIds));
        }
        //收集企业编码
        if (CollUtil.isNotEmpty(riskEvents)) {
            collectCompanyId(riskEvents, AspRiskEventDo::getTenantId, AspRiskEventDo::setEnterprisecode);
        }
        // 保存每条记录对于的待同步和错误信息
        for (AspRiskEventDo machine : riskEvents) {
            collectEventData(machine, waitSyncEventData, checkErrorMap);
        }
        List<AspRiskControlMeasuresDo> riskControlMeasures = new ArrayList<>();
        List<String> riskEventsIds = new ArrayList<>();
        if (CollUtil.isNotEmpty(riskEvents)) {
            //  获取风险事件ID
            collectDataIds(waitSyncEventData, riskEventsIds, "RISKEVENT_ID");
            //  根据风险事件ID获取风险措施数据
            if (CollUtil.isNotEmpty(riskEventsIds)) {
                riskControlMeasures = aspRiskControlMeasuresService.list(new QueryWrapper<AspRiskControlMeasuresDo>()
                        .in("RISKEVENTID", riskEventsIds));
            }
        }
        //收集企业编码
        if (CollUtil.isNotEmpty(riskControlMeasures)) {
            collectCompanyId(riskControlMeasures, AspRiskControlMeasuresDo::getTenantId, AspRiskControlMeasuresDo::setEnterprisecode);
        }

        // 保存每条记录对于的待同步和错误信息
        for (AspRiskControlMeasuresDo machine : riskControlMeasures) {
            collectControlMeasuresData(machine, waitSyncControlMeasureData, checkErrorMap);
        }

        /************4.创建线程池，分批同步单元、事件和管控措施的数据***********************/
        // 4.1 50条一处理
        List<List<Map<String, Object>>> unitPartitionedLists = Lists.partition(waitSyncUnitData, BATCH_SIZE);
        List<List<Map<String, Object>>> eventPartitionedLists = Lists.partition(waitSyncEventData, BATCH_SIZE);
        List<List<Map<String, Object>>> controlMeasurePartitionedLists = Lists.partition(waitSyncControlMeasureData, BATCH_SIZE);
        List<AspRiskUnitDo> dataSave = new ArrayList<>();
        //4.1构建需要更新的 AspRiskUnitDo 列表，包含单元、事件和管控措施的信息和校验失败数据
        buildAllDataSaveList(unitPartitionedLists, eventPartitionedLists, controlMeasurePartitionedLists, checkErrorMap, ip, dataSave);

        /************5.所有批次处理完成后，统一更新记录***********************/
        if (!dataSave.isEmpty()) {
            aspRiskUnitService.updateBatchById(dataSave);
        }
    }

//============================================================================================================================================================================

    /**
     * 四色图信息同步
     * 涉及到的表有：asp_risk_map
     */
    @Override
    public void fourColorSynchronizationList(List<String> ids) throws IOException {
        /****************1.根据ID获取数据 ***********************/
        //校验一下ids集合不能为空
        if (ids.isEmpty()) {
            log.error("参数异常：{}", ids);
            throw new CustomException("请选择需要同步的数据！");
        }
        List<AspRiskMapDo> riskFourColor = aspRiskMapService.getBaseMapper().selectBatchIds(ids);
        if (riskFourColor.isEmpty()) {
            return;
        }
//        List<AspRiskProfileDo> riskDistribute = aspRiskProfileService.getBaseMapper().selectBatchIds(ids);
        //收集企业编码
        collectCompanyId(riskFourColor, AspRiskMapDo::getTenantid, AspRiskMapDo::setEnterprisecode);

        /***************2.筛选出待同步的数据 ***********************/
        List<Map<String, Object>> waitSyncFourColorData = new ArrayList<>();
        List<Map<String, Object>> waitSyncDistributeData = new ArrayList<>();

        /************3.筛选出因为参数未必填导致无法推送的数据***********************/
        Map<String, String> checkErrorMap = new HashMap<>();
        // 保存每条记录对于的错误信息
        for (AspRiskMapDo machine : riskFourColor) {
            collectFourColorData(machine, waitSyncFourColorData, checkErrorMap);
        }
        //先过滤掉riskFourColor中必填属性为空的对象
        riskFourColor = filterFourColorEmptyObjects(riskFourColor);
        //再构建 DistributeVo 列表
        List<DistributeVo> riskDistribute = buildDistributeVoList(riskFourColor);
        for (DistributeVo machine : riskDistribute) {
            collectDistributeData(machine, waitSyncDistributeData, checkErrorMap);
        }

        /************4.创建线程池，分批同步四色图和分布信息数据***********************/
        List<List<Map<String, Object>>> fourColorPartitionedLists = Lists.partition(waitSyncFourColorData, BATCH_SIZE);

        List<List<Map<String, Object>>> distributePartitionedLists = Lists.partition(waitSyncDistributeData, BATCH_SIZE);

        List<AspRiskMapDo> dataSave = new ArrayList<>();
        //4.1构建需要更新的 AspRiskMapDo 列表，包含四色图、分布信息和校验失败数据
        buildFourColorDataSaveList(fourColorPartitionedLists, distributePartitionedLists, checkErrorMap, ip, dataSave);

        /************5.所有批次处理完成后，统一更新记录***********************/
        if (!dataSave.isEmpty()) {
            aspRiskMapService.updateBatchById(dataSave);
        }
    }

    /**
     * 通用收集企业编码的方法，支持任意类型 List<T>
     *
     * @param list                      待处理的列表
     * @param getTenantIdFunction       如何从 T 中获取 tenantId
     * @param setEnterpriseCodeConsumer 如何给 T 设置 enterprisecode
     */
    private <T> void collectCompanyId(
            List<T> list,
            Function<T, String> getTenantIdFunction,
            BiConsumer<T, String> setEnterpriseCodeConsumer) {

        if (list == null || list.isEmpty()) {
            return;
        }

        // 1. 收集所有 tenantId
        List<String> tenantIds = list.stream()
                .map(getTenantIdFunction)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        if (tenantIds.isEmpty()) {
            return;
        }

        // 2. 查询企业信息
        List<CompanyInfoVo> companyInfoVoList = riskSynchronizationDao.companyInfoList(tenantIds);
        companyInfoVoList = filterNullData(companyInfoVoList, CompanyInfoVo::getCompanyId);

        // 4. 遍历 list 并设置企业编码
        for (T item : list) {
            String tenantId = getTenantIdFunction.apply(item);

            // 从 companyInfoVoList 中找出第一个匹配的 companyId
            Optional<String> companyIdOpt = companyInfoVoList.stream()
                    .filter(vo -> vo.getTenantId().equals(tenantId))
                    .map(CompanyInfoVo::getCompanyId)
                    .filter(Objects::nonNull)
                    .findFirst();

            companyIdOpt.ifPresent(companyId -> setEnterpriseCodeConsumer.accept(item, companyId));
        }

    }


    /**
     * 校验方法
     * *  1.校验失败 保存的错误信息
     * *  2. 校验成功 是要保存同步的数据
     *
     * @param errorMsgList     用来保存错误信息
     * @param waitCheckData    等待校验的数据
     * @param errorMsg         数据校验失败需要保存的错误信息
     * @param syncDataMap      需要被同步的数据
     * @param key              本次同步的key
     * @param simpleDateFormat 防止时间格式固定需要传的格式化方法
     */
    public void dataCheck(List<String> errorMsgList, Object waitCheckData, String errorMsg, Map<String, Object> syncDataMap, String key,
                          SimpleDateFormat simpleDateFormat) {
        // 参数有效性检查
        if (errorMsgList == null || syncDataMap == null || key == null) {
            throw new IllegalArgumentException("errorMsgList, syncDataMap and key cannot be null");
        }

        // 检查待校验数据是否为空
        if (waitCheckData == null && ObjectUtil.isEmpty(waitCheckData)) {
            errorMsgList.add(errorMsg);
            return;
        }

        // 修正：检查字符串类型的数据是否为空
        if (waitCheckData instanceof String && StringUtils.isBlank((String) waitCheckData)) {
            errorMsgList.add(errorMsg);
            return;
        }

        // 处理日期类型
        if (waitCheckData instanceof Date) {
            // 使用默认格式(线程安全)
            if (simpleDateFormat == null) {
                simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
            }

            try {
                syncDataMap.put(key, simpleDateFormat.format((Date) waitCheckData));
            } catch (Exception e) {
                errorMsgList.add("日期格式化失败: " + e.getMessage());
            }
        } else {
            // 其他类型直接放入结果Map
            syncDataMap.put(key, waitCheckData);
        }
    }

    /**
     * @param doItem
     * @param waitSyncData
     * @param checkErrorMap
     */
    private void collectFourColorData(AspRiskMapDo doItem, List<Map<String, Object>> waitSyncData, Map<String, String> checkErrorMap) {
        List<String> errorMsgList = new ArrayList<>();
        Map<String, Object> syncDataMap = new HashMap<>();
        dataCheck(errorMsgList, doItem.getId(), "风险四色图ID为空", syncDataMap, "ID", null);
        dataCheck(errorMsgList, doItem.getSerialnumber(), "风险分区编号为空", syncDataMap, "FXFQBM", null);
        dataCheck(errorMsgList, doItem.getName(), "风险分区名称为空", syncDataMap, "FXFQMC", null);
        dataCheck(errorMsgList, doItem.getRisklevel(), "风险等级为空", syncDataMap, "FXDJ", null);
        dataCheck(errorMsgList, doItem.getRiskcoordinate(), "风险坐标范围为空", syncDataMap, "FXZBFW", null);
        dataCheck(errorMsgList, doItem.getInherentrisklevel(), "固有风险等级为空", syncDataMap, "GYFXDJ", null);
        dataCheck(errorMsgList, doItem.getControlrisklevel(), "控制风险等级为空", syncDataMap, "KZFXDJ", null);
        dataCheck(errorMsgList, doItem.getRiskcorrectionfactors(), "风险校正因素为空", syncDataMap, "FXJZYS", null);
        dataCheck(errorMsgList, doItem.getRiskcorrectionlevel(), "风险校正等级为空", syncDataMap, "FXJZDJ", null);
        dataCheck(errorMsgList, doItem.getDeptname(), "所在部门为空", syncDataMap, "SZBM", null);
        dataCheck(errorMsgList, doItem.getEvaluatorname(), "评价人为空", syncDataMap, "ZRR", null);
        dataCheck(errorMsgList, doItem.getReviewdate(), "复评日期为空", syncDataMap, "FPRQ", new SimpleDateFormat("yyyyMMdd"));
        dataCheck(errorMsgList, doItem.getCreatedate(), "创建时间为空", syncDataMap, "CREATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getCreateusername(), "创建人为空", syncDataMap, "CREATE_BY", null);
        dataCheck(errorMsgList, doItem.getModifydate(), "最后修改时间为空", syncDataMap, "UPDATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getModifyusername(), "最后修改人为空", syncDataMap, "UPDATE_BY", null);
        dataCheck(errorMsgList, doItem.getDeleted(), "删除标识为空", syncDataMap, "DELETE_MARK", null);
        dataCheck(errorMsgList, doItem.getEnterprisecode(), "企业编码为空", syncDataMap, "COMPANY_CODE", null);
        if (errorMsgList.isEmpty() || (errorMsgList.size() == 1 && "复评日期为空".equals(errorMsgList.get(0)))) {
            waitSyncData.add(syncDataMap);
        } else {
            checkErrorMap.put(doItem.getId(), StringUtils.join(errorMsgList, "、"));
        }
    }

    private void collectDistributeData(DistributeVo doItem, List<Map<String, Object>> waitSyncData, Map<String, String> checkErrorMap) {
        List<String> errorMsgList = new ArrayList<>();
        Map<String, Object> syncDataMap = new HashMap<>();
        dataCheck(errorMsgList, doItem.getFourColorId(), "安全风险空间分布图ID为空", syncDataMap, "ID", null);
        dataCheck(errorMsgList, doItem.getImageBase64(), "安全风险空间分布图为空", syncDataMap, "IMG", null);
        dataCheck(errorMsgList, doItem.getCreatedate(), "创建时间为空", syncDataMap, "CREATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getCreateusername(), "创建人为空", syncDataMap, "CREATE_BY", null);
        dataCheck(errorMsgList, doItem.getModifydate(), "最后修改时间为空", syncDataMap, "UPDATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getModifyusername(), "最后修改人为空", syncDataMap, "UPDATE_BY", null);
        dataCheck(errorMsgList, doItem.getDeleted(), "删除标识为空", syncDataMap, "DELETE_MARK", null);
        dataCheck(errorMsgList, doItem.getEnterprisecode(), "企业编码为空", syncDataMap, "COMPANY_CODE", null);
        if (errorMsgList.isEmpty()) {
            waitSyncData.add(syncDataMap);
        } else {
            checkErrorMap.put(doItem.getFourColorId(), StringUtils.join(errorMsgList, "、"));
        }
    }

    private void collectUnitData(AspRiskUnitDo doItem, List<Map<String, Object>> waitSyncData, Map<String, String> checkErrorMap) {
        List<String> errorMsgList = new ArrayList<>();
        Map<String, Object> syncDataMap = new HashMap<>();
        dataCheck(errorMsgList, doItem.getId(), "风险单元ID为空", syncDataMap, "RISKUNIT_ID", null);
        dataCheck(errorMsgList, doItem.getRiskobjectcode(), "风险分析对象编码为空", syncDataMap, "HAZARD_CODE", null);
        dataCheck(errorMsgList, doItem.getResponsibledept(), "责任部门为空", syncDataMap, "HAZARD_DEP", null);
        dataCheck(errorMsgList, doItem.getDutyofficername(), "责任人为空", syncDataMap, "HAZARD_LIABLE_PERSON", null);
        dataCheck(errorMsgList, doItem.getRiskunitname(), "风险分析单元名称为空", syncDataMap, "RISK_UNIT_NAME", null);
        dataCheck(errorMsgList, doItem.getRisklevel(), "风险等级为空", syncDataMap, "RISK_CLASS", null);
        dataCheck(errorMsgList, doItem.getCreatedate(), "创建时间为空", syncDataMap, "CREATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getCreateusername(), "创建人为空", syncDataMap, "CREATE_BY", null);
        dataCheck(errorMsgList, doItem.getModifydate(), "最后修改时间为空", syncDataMap, "UPDATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getModifyusername(), "最后修改人为空", syncDataMap, "UPDATE_BY", null);
        dataCheck(errorMsgList, doItem.getDeleted(), "删除标识为空", syncDataMap, "DELETE_MARK", null);
        dataCheck(errorMsgList, doItem.getEnterprisecode(), "企业编码为空", syncDataMap, "COMPANY_CODE", null);
        if (errorMsgList.isEmpty()) {
            waitSyncData.add(syncDataMap);
        } else {
            checkErrorMap.put(doItem.getId(), StringUtils.join(errorMsgList, "、"));
        }
    }

    private void collectEventData(AspRiskEventDo doItem, List<Map<String, Object>> waitSyncData, Map<String, String> checkErrorMap) {
        List<String> errorMsgList = new ArrayList<>();
        Map<String, Object> syncDataMap = new HashMap<>();
        dataCheck(errorMsgList, doItem.getId(), "风险事件ID为空", syncDataMap, "RISKEVENT_ID", null);
        dataCheck(errorMsgList, doItem.getRiskUnitId(), "风险单元ID为空", syncDataMap, "RISK_UNIT_ID", null);
        dataCheck(errorMsgList, doItem.getRiskEventName(), "风险事件名称为空", syncDataMap, "RISK_EVENT_NAME", null);
        dataCheck(errorMsgList, doItem.getCreatedate(), "创建时间为空", syncDataMap, "CREATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getCreateusername(), "创建人为空", syncDataMap, "CREATE_BY", null);
        dataCheck(errorMsgList, doItem.getModifydate(), "最后修改时间为空", syncDataMap, "UPDATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getModifyusername(), "最后修改人为空", syncDataMap, "UPDATE_BY", null);
        dataCheck(errorMsgList, doItem.getDeleted(), "删除标识为空", syncDataMap, "DELETE_MARK", null);
        dataCheck(errorMsgList, doItem.getEnterprisecode(), "企业编码为空", syncDataMap, "COMPANY_CODE", null);
        if (errorMsgList.isEmpty()) {
            waitSyncData.add(syncDataMap);
        } else {
            checkErrorMap.put(doItem.getRiskUnitId(), StringUtils.join(errorMsgList, "、"));
        }
    }

    private void collectControlMeasuresData(AspRiskControlMeasuresDo doItem, List<Map<String, Object>> waitSyncData, Map<String, String> checkErrorMap) {
        List<String> errorMsgList = new ArrayList<>();
        Map<String, Object> syncDataMap = new HashMap<>();
        dataCheck(errorMsgList, doItem.getId(), "管控措施ID为空", syncDataMap, "RISKMEASURE_ID", null);
        dataCheck(errorMsgList, doItem.getRiskEventId(), "风险事件ID为空", syncDataMap, "RISK_EVENT_ID", null);
        dataCheck(errorMsgList, doItem.getControlType(), "管控方式为空", syncDataMap, "DATA_SRC", null);
        dataCheck(errorMsgList, doItem.getControlDesc(), "管控措施描述为空", syncDataMap, "RISK_MEASURE_DESC", null);
        dataCheck(errorMsgList, doItem.getClassify1(), "管控措施分类1为空", syncDataMap, "CLASSIFY1", null);
        dataCheck(errorMsgList, doItem.getClassify2(), "管控措施分类2为空", syncDataMap, "CLASSIFY2", null);
        dataCheck(errorMsgList, doItem.getClassify3(), "管控措施分类3为空", syncDataMap, "CLASSIFY3", null);
        dataCheck(errorMsgList, doItem.getInvestigationContent(), "隐患排查内容为空", syncDataMap, "TROUBLESHOOT_CONTENT", null);
        dataCheck(errorMsgList, doItem.getCreatedate(), "创建时间为空", syncDataMap, "CREATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getCreateusername(), "创建人为空", syncDataMap, "CREATE_BY", null);
        dataCheck(errorMsgList, doItem.getModifydate(), "最后修改时间为空", syncDataMap, "UPDATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getModifyusername(), "最后修改人为空", syncDataMap, "UPDATE_BY", null);
        dataCheck(errorMsgList, doItem.getDeleted(), "删除标识为空", syncDataMap, "DELETE_MARK", null);
        dataCheck(errorMsgList, doItem.getEnterprisecode(), "企业编码为空", syncDataMap, "COMPANY_CODE", null);
        if (errorMsgList.isEmpty() || (errorMsgList.size() == 1 && "管控措施分类3为空".equals(errorMsgList.get(0)))) {
            waitSyncData.add(syncDataMap);
        } else {
            //错误信息只在单元菜单列表中展示
            AspRiskEventDo risk_event = aspRiskEventService.getById(doItem.getRiskEventId());
            checkErrorMap.put(risk_event.getRiskUnitId(), StringUtils.join(errorMsgList, "、"));
        }
    }

    private void collectSafeMaintenanceData(CheckTemplateItemsDo doItem, List<Map<String, Object>> waitSyncData, Map<String, String> checkErrorMap) {
        List<String> errorMsgList = new ArrayList<>();
        Map<String, Object> syncDataMap = new HashMap<>();
        dataCheck(errorMsgList, doItem.getId(), "安全检查项ID为空", syncDataMap, "ID", null);
        dataCheck(errorMsgList, doItem.getChecktemplateid(), "", syncDataMap, "TEMPLATEID", null);
        dataCheck(errorMsgList, doItem.getTemplatetype(), "检查类型为空", syncDataMap, "JCLX", null);
        dataCheck(errorMsgList, doItem.getCheckposition(), "检查项目为空", syncDataMap, "JCXM", null);
        dataCheck(errorMsgList, doItem.getChecktype(), "检查方式为空", syncDataMap, "JCFS", null);
        dataCheck(errorMsgList, doItem.getCheckcontent(), "检查内容为空", syncDataMap, "JCNR", null);
        dataCheck(errorMsgList, doItem.getCheckstandard(), "检查依据为空", syncDataMap, "JCYJ", null);
        dataCheck(errorMsgList, doItem.getRemark(), "备注为空", syncDataMap, "BZ", null);
        dataCheck(errorMsgList, doItem.getCreatedate(), "创建时间为空", syncDataMap, "CREATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getCreateusername(), "创建人为空", syncDataMap, "CREATE_BY", null);
        dataCheck(errorMsgList, doItem.getModifydate(), "最后修改时间为空", syncDataMap, "UPDATE_TIME", new SimpleDateFormat("yyyyMMddHHmmss"));
        dataCheck(errorMsgList, doItem.getModifyusername(), "最后修改人为空", syncDataMap, "UPDATE_BY", null);
        dataCheck(errorMsgList, doItem.getDeleted(), "删除标识为空", syncDataMap, "DELETE_MARK", null);
        dataCheck(errorMsgList, doItem.getEnterprisecode(), "企业编码为空", syncDataMap, "COMPANY_CODE", null);
        if (errorMsgList.isEmpty() || (errorMsgList.size() == 1 && "备注为空".equals(errorMsgList.get(0)))) {
            waitSyncData.add(syncDataMap);
        } else {
            checkErrorMap.put(doItem.getChecktemplateid(), StringUtils.join(errorMsgList, "、"));
        }
    }


    public static List<String> extractValues(String input) {
        List<String> values = new ArrayList<>();
        int startIndex = 0;

        while (true) {
            // 查找 `-;-` 的位置
            int separatorIndex = input.indexOf("-;-", startIndex);
            if (separatorIndex == -1) break;

            // 从 `-;-` 后开始查找 `^_^` 的位置
            int endIndex = input.indexOf("^_^", separatorIndex + 3);
            if (endIndex == -1) {
                // 如果没有 `^_^`，则取到字符串末尾
                endIndex = input.length();
            }

            // 提取中间的值
            String value = input.substring(separatorIndex + 3, endIndex);
            values.add(value);

            // 更新起始位置
            startIndex = endIndex + 2;
        }

        return values;
    }

    public String convertFilesToBase64(List<SysFileItemDo> sysFileItemDoList) {
        List<String> base64List = new ArrayList<>();
        Base64.Encoder encoder = Base64.getEncoder();
//        String sysPath = "C:\\file\\";

        for (SysFileItemDo item : sysFileItemDoList) {
            String fullPath = item.getFullpath();
//            fullPath = sysPath + fullPath;
            File file = new File(fullPath);

            try {
                if (!file.exists()) {
                    System.err.println("文件不存在：" + fullPath);
                    continue;
                }

                // 文件大小检查（最大5MB）
                long fileSizeInBytes = file.length();
                if (fileSizeInBytes > 5 * 1024 * 1024) { // 5MB
                    System.err.println("文件超过5MB，跳过：" + fullPath);
                    continue;
                }

                // 读取文件并判断是否是图片
                byte[] fileBytes = Files.readAllBytes(file.toPath());
                String mimeType = Files.probeContentType(file.toPath());

                if (mimeType == null || !(mimeType.equals("image/png") || mimeType.equals("image/jpeg"))) {
                    System.err.println("非PNG或JPEG图片，跳过：" + fullPath);
                    continue;
                }

                String base64 = "data:" + mimeType + ";base64," + encoder.encodeToString(fileBytes);
                base64List.add(base64);

            } catch (Exception e) {
                System.err.println("读取文件失败：" + fullPath);
                e.printStackTrace();
            }
        }
        if (CollUtil.isNotEmpty(base64List)) {
            return JSON.toJSONString(base64List);
        }
        return null;

    }


    private ExecutorService createCustomThreadPool() {
        int corePoolSize = 4;
        int maxPoolSize = 8;
        long keepAliveTime = 60; // 空闲线程存活时间

        return new ThreadPoolExecutor(
                corePoolSize,
                maxPoolSize,
                keepAliveTime, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100),
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
        );
    }

    //2.四色图信息存在，分布信息不存在
    //筛选出DistributeVo中imageBase64不为空的数据
    public List<DistributeVo> filterRiskDistributeData(List<DistributeVo> riskDistributeData) {
        if (riskDistributeData == null || riskDistributeData.isEmpty()) {
            return new ArrayList<>();
        }

        return riskDistributeData.stream()
                .filter(item -> item != null &&
                        item.getImageBase64() != null &&
                        !item.getImageBase64().isEmpty())
                .collect(Collectors.toList());
    }

    /**
     * 通用过滤方法：筛选出 imageBase64 不为空的元素
     *
     * @param list           待过滤的列表
     * @param filterNullData 如何从 T 中获取 imageBase64 字段
     * @return 过滤后的列表
     */
    public <T> List<T> filterNullData(
            List<T> list,
            Function<T, String> filterNullData) {

        if (list == null) {
            return new ArrayList<>();
        }

        return list.stream()
                .filter(Objects::nonNull)
                .filter(item -> {
                    String data = filterNullData.apply(item);
                    return data != null && !data.isEmpty();
                })
                .collect(Collectors.toList());
    }


    public List<AspRiskMapDo> filterFourColorEmptyObjects(List<AspRiskMapDo> riskFourColor) {
        return riskFourColor.stream()
                .filter(aspRiskMapDo -> aspRiskMapDo.getId() != null && !aspRiskMapDo.getId().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getSerialnumber() != null && !aspRiskMapDo.getSerialnumber().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getName() != null && !aspRiskMapDo.getName().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getRisklevel() != null && !aspRiskMapDo.getRisklevel().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getRiskcoordinate() != null && !aspRiskMapDo.getRiskcoordinate().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getInherentrisklevel() != null && !aspRiskMapDo.getInherentrisklevel().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getControlrisklevel() != null && !aspRiskMapDo.getControlrisklevel().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getRiskcorrectionfactors() != null && !aspRiskMapDo.getRiskcorrectionfactors().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getRiskcorrectionlevel() != null && !aspRiskMapDo.getRiskcorrectionlevel().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getDeptname() != null && !aspRiskMapDo.getDeptname().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getEvaluatorname() != null && !aspRiskMapDo.getEvaluatorname().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getReviewdate() != null)
                .filter(aspRiskMapDo -> aspRiskMapDo.getCreatedate() != null)
                .filter(aspRiskMapDo -> aspRiskMapDo.getCreateusername() != null && !aspRiskMapDo.getCreateusername().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getModifydate() != null)
                .filter(aspRiskMapDo -> aspRiskMapDo.getModifyusername() != null && !aspRiskMapDo.getModifyusername().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getDeleted() != null && !aspRiskMapDo.getDeleted().isEmpty())
                .filter(aspRiskMapDo -> aspRiskMapDo.getEnterprisecode() != null && !aspRiskMapDo.getEnterprisecode().isEmpty())

                .collect(Collectors.toList());
    }


    /**
     * 构建 DistributeVo 列表
     *
     * @param riskFourColor 四色图数据源（AspRiskMapDo 列表）
     * @return 过滤后的 DistributeVo 列表（imageBase64 不为空的）
     */
    public List<DistributeVo> buildDistributeVoList(List<AspRiskMapDo> riskFourColor) {
        List<DistributeVo> riskDistributeData = new ArrayList<>();

        if (CollUtil.isEmpty(riskFourColor)) {
            return riskDistributeData;
        }
        //将fourColorId和DistributeId赋值给riskDistribute
        for (AspRiskMapDo aspRiskMapDo : riskFourColor) {
            DistributeVo distributeVo = new DistributeVo();
            distributeVo.setFourColorId(aspRiskMapDo.getId());
            distributeVo.setTenantid(aspRiskMapDo.getTenantid());
            distributeVo.setEnterprisecode(aspRiskMapDo.getEnterprisecode());
            String distributeIds = aspRiskMapDo.getSpacedistribution();
            //非空检验，将distributeIds进行分割，并赋值给distributeVo
            List<String> distributeIdList = new ArrayList<>();
            if (StrUtil.isNotBlank(distributeIds)) {
                distributeIdList = extractValues(distributeIds);
            }
            //1.四色图信息存在，分布信息存在,distributeIdList就存在
            distributeVo.setDistributeId(distributeIdList);

            //查询数据库获取所有图片的全路径和冗余信息
            List<SysFileItemDo> sysFileItemDoList = new ArrayList<>();
            if (CollUtil.isNotEmpty(distributeIdList)) {
                sysFileItemDoList = riskSynchronizationDao.getFilePathById(distributeIdList);
            }
            //取出最后一张图片的冗余字段信息，例如时间，创建人等等
            if (sysFileItemDoList.size() >= 1) {
                SysFileItemDo lastSysFileItemDo = sysFileItemDoList.get(sysFileItemDoList.size() - 1);
                distributeVo.setCreateusername(lastSysFileItemDo.getCreateusername());
                distributeVo.setModifyusername(lastSysFileItemDo.getModifyusername());
                distributeVo.setModifydate(lastSysFileItemDo.getModifydate());
                distributeVo.setCreatedate(lastSysFileItemDo.getCreatedate());
                distributeVo.setDeleted(lastSysFileItemDo.getDeleted());
            }

            // 转换图片为 Base64
            String imageBase64 = convertFilesToBase64(sysFileItemDoList);
            distributeVo.setImageBase64(imageBase64);

            // 添加到临时列表
            riskDistributeData.add(distributeVo);
        }

        // 过滤掉 imageBase64 为空的数据--
        return filterRiskDistributeData(riskDistributeData);
    }

    /**
     * 构建需要更新的 AspRiskMapDo 列表，包含四色图、分布信息和校验失败数据
     *
     * @param fourColorSyncDataList  四色图同步任务列表
     * @param distributeSyncDataList 分布信息同步任务列表
     * @param checkErrorMap          校验失败的数据映射
     * @param ip                     服务 IP
     * @param dataSave               输出参数：收集所有待更新的数据
     */
    private void buildFourColorDataSaveList(
            List<List<Map<String, Object>>> fourColorSyncDataList,
            List<List<Map<String, Object>>> distributeSyncDataList,
            Map<String, String> checkErrorMap,
            String ip,
            List<AspRiskMapDo> dataSave) {

        ExecutorService executorService = createCustomThreadPool();

        try {
            // 处理四色图同步任务
            for (List<Map<String, Object>> syncData : fourColorSyncDataList) {
                Future<Result> future = executorService.submit(() -> dataPush(ip, FOURCOLORCONSTANT, syncData));
                Result result = future.get();// 等待结果

                AspRiskMapDo aspRiskMapDo;
                if (Objects.equals(result.getStatus(), 200)) {
                    // 当前批次成功，记录日志和状态
                    for (Map<String, Object> waitSyncDatum : syncData) {
                        aspRiskMapDo = new AspRiskMapDo();
                        aspRiskMapDo.setId((String) waitSyncDatum.get("ID"));
                        aspRiskMapDo.setSyncstatus(SUCCESSSYNC);
                        aspRiskMapDo.setSynclog(waitSyncDatum.toString());
                        aspRiskMapDo.setSynctime(new Date());
                        dataSave.add(aspRiskMapDo);
                    }
                } else {
                    //1.四色图信息同步失败，状态为同步失败
                    // 四色图信息同步失败，记录日志和状态
                    for (Map<String, Object> waitSyncDatum : syncData) {
                        aspRiskMapDo = new AspRiskMapDo();
                        aspRiskMapDo.setId((String) waitSyncDatum.get("ID"));
                        aspRiskMapDo.setSyncstatus(FAILURESYNC);
                        aspRiskMapDo.setSynclog(result.getMessage());
                        aspRiskMapDo.setSynctime(new Date());
                        dataSave.add(aspRiskMapDo);
                    }
                }
            }

            // 处理分布信息同步任务
            for (List<Map<String, Object>> syncData : distributeSyncDataList) {
                Future<Result> future = executorService.submit(() -> dataPush(ip, DISTRIBUTECONSTANT, syncData));
                Result result = future.get(); // 等待结果

                //2.无论四色图信息是否同步成功，只要分布信息同步失败，状态为同步失败
                if (!Objects.equals(result.getStatus(), 200)) {
                    // 分布信息同步失败，记录日志和状态
                    for (Map<String, Object> waitSyncDatum : syncData) {
                        AspRiskMapDo aspRiskMapDo = new AspRiskMapDo();
                        aspRiskMapDo.setId((String) waitSyncDatum.get("ID"));
                        aspRiskMapDo.setSyncstatus(FAILURESYNC);
                        aspRiskMapDo.setSynclog(result.getMessage());
                        aspRiskMapDo.setSynctime(new Date());
                        dataSave.add(aspRiskMapDo);
                    }
                }
            }

            // 处理校验失败的数据
            for (Map.Entry<String, String> entry : checkErrorMap.entrySet()) {
                AspRiskMapDo aspRiskMapDo = new AspRiskMapDo();
                aspRiskMapDo.setId(entry.getKey());
                aspRiskMapDo.setSynclog(entry.getValue());
                aspRiskMapDo.setSyncstatus(WAITSYNC);
                aspRiskMapDo.setSynctime(new Date());
                dataSave.add(aspRiskMapDo);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executorService.shutdown(); // 关闭线程池
        }
    }

    /**
     * 构建需要更新的 AspRiskMapDo 列表，包含单元、事件、管控措施的信息和校验失败数据
     */
    private void buildAllDataSaveList(
            List<List<Map<String, Object>>> unitPartitionedLists,
            List<List<Map<String, Object>>> eventPartitionedLists,
            List<List<Map<String, Object>>> controlMeasurePartitionedLists,
            Map<String, String> checkErrorMap,
            String ip,
            List<AspRiskUnitDo> dataSave) {
        //定义事件和措施的集合，收集事件和措施同步时间的数据储存在数据库中
        List<AspRiskEventDo> eventDataSave = new ArrayList<>();
        List<AspRiskControlMeasuresDo> controlMeasureDataSave = new ArrayList<>();

        ExecutorService executorService = createCustomThreadPool();

        try {
            // 处理单元同步任务
            for (List<Map<String, Object>> syncData : unitPartitionedLists) {
                Future<Result> future = executorService.submit(() -> dataPush(ip, UNITCONSTANT, syncData));
                Result result = future.get(); // 等待结果

                if (Objects.equals(result.getStatus(), 200)) {
                    // 当前批次成功，记录日志和状态
                    for (Map<String, Object> waitSyncDatum : syncData) {
                        AspRiskUnitDo aspRiskUnitDo = new AspRiskUnitDo();
                        aspRiskUnitDo.setId((String) waitSyncDatum.get("RISKUNIT_ID"));
                        aspRiskUnitDo.setSyncstatus(SUCCESSSYNC);
                        aspRiskUnitDo.setSynclog(waitSyncDatum.toString());
                        aspRiskUnitDo.setSynctime(new Date());
                        dataSave.add(aspRiskUnitDo);
                    }
                } else {
                    //1.单元信息同步失败，状态为同步失败，记录日志和状态
                    for (Map<String, Object> waitSyncDatum : syncData) {
                        AspRiskUnitDo aspRiskUnitDo = new AspRiskUnitDo();
                        aspRiskUnitDo.setId((String) waitSyncDatum.get("RISKUNIT_ID"));
                        aspRiskUnitDo.setSyncstatus(FAILURESYNC);
                        aspRiskUnitDo.setSynclog(result.getMessage());
                        aspRiskUnitDo.setSynctime(new Date());
                        dataSave.add(aspRiskUnitDo);
                    }
                }
            }

            // 处理事件信息同步任务
            for (List<Map<String, Object>> syncData : eventPartitionedLists) {
                Future<Result> future = executorService.submit(() -> dataPush(ip, DISTRIBUTECONSTANT, syncData));
                Result result = future.get(); // 等待结果

                //2.无论四色图信息是否同步成功，只要分布信息同步失败，状态为同步失败
                if (!Objects.equals(result.getStatus(), 200)) {
                    // 分布信息同步失败，记录日志和状态
                    for (Map<String, Object> waitSyncDatum : syncData) {
                        AspRiskUnitDo aspRiskUnitDo = new AspRiskUnitDo();
                        aspRiskUnitDo.setId((String) waitSyncDatum.get("RISK_UNIT_ID"));
                        aspRiskUnitDo.setSyncstatus(FAILURESYNC);
                        aspRiskUnitDo.setSynclog(result.getMessage());
                        aspRiskUnitDo.setSynctime(new Date());
                        dataSave.add(aspRiskUnitDo);
                        AspRiskEventDo aspRiskEventDo = new AspRiskEventDo();
                        aspRiskEventDo.setId((String) waitSyncDatum.get("RISKEVENT_ID"));
                        aspRiskEventDo.setSyncTime(new Date());
                        eventDataSave.add(aspRiskEventDo);
                    }
                } else {
                    for (Map<String, Object> waitSyncDatum : syncData) {
                        AspRiskEventDo aspRiskEventDo = new AspRiskEventDo();
                        aspRiskEventDo.setId((String) waitSyncDatum.get("RISKEVENT_ID"));
                        aspRiskEventDo.setSyncTime(new Date());
                        eventDataSave.add(aspRiskEventDo);
                    }
                }
            }
            if (eventDataSave.size() > 0) {
                aspRiskEventService.updateBatchById(eventDataSave);
            }
            // 处理措施信息同步任务
            for (List<Map<String, Object>> syncData : controlMeasurePartitionedLists) {
                Future<Result> future = executorService.submit(() -> dataPush(ip, CONTROLMEASURECONSTANT, syncData));
                Result result = future.get();
                //2.无论四色图信息是否同步成功，只要分布信息同步失败，状态为同步失败
                if (!Objects.equals(result.getStatus(), 200)) {
                    // 分布信息同步失败，记录日志和状态
                    for (Map<String, Object> waitSyncDatum : syncData) {
                        //获取分险事件的ID从数据库查询单元的ID(String)
                        AspRiskEventDo risk_event = aspRiskEventService.getById(waitSyncDatum.get("RISK_EVENT_ID").toString());
                        AspRiskUnitDo aspRiskUnitDo = new AspRiskUnitDo();
                        aspRiskUnitDo.setId(risk_event.getRiskUnitId());
                        aspRiskUnitDo.setSyncstatus(FAILURESYNC);
                        aspRiskUnitDo.setSynclog(result.getMessage());
                        aspRiskUnitDo.setSynctime(new Date());
                        dataSave.add(aspRiskUnitDo);
                        AspRiskControlMeasuresDo aspRiskControlMeasuresDo = new AspRiskControlMeasuresDo();
                        aspRiskControlMeasuresDo.setId((String) waitSyncDatum.get("RISKMEASURE_ID"));
                        aspRiskControlMeasuresDo.setSyncTime(new Date());
                        controlMeasureDataSave.add(aspRiskControlMeasuresDo);
                    }
                } else {
                    for (Map<String, Object> waitSyncDatum : syncData) {
                        AspRiskControlMeasuresDo aspRiskControlMeasuresDo = new AspRiskControlMeasuresDo();
                        aspRiskControlMeasuresDo.setId((String) waitSyncDatum.get("RISKMEASURE_ID"));
                        aspRiskControlMeasuresDo.setSyncTime(new Date());
                        controlMeasureDataSave.add(aspRiskControlMeasuresDo);
                    }
                }
                if (controlMeasureDataSave.size() > 0) {
                    aspRiskControlMeasuresService.updateBatchById(controlMeasureDataSave);
                }
            }

            // 处理校验失败的数据
            for (Map.Entry<String, String> entry : checkErrorMap.entrySet()) {
                AspRiskUnitDo aspRiskUnitDo = new AspRiskUnitDo();
                aspRiskUnitDo.setId(entry.getKey());
                aspRiskUnitDo.setSynclog(entry.getValue());
                aspRiskUnitDo.setSyncstatus(WAITSYNC);
                aspRiskUnitDo.setSynctime(new Date());
                dataSave.add(aspRiskUnitDo);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executorService.shutdown(); // 关闭线程池
        }
    }

    /**
     * @param checkErrorMap 校验失败的数据映射
     * @param ip            服务 IP
     * @param dataSave      输出参数：收集所有待更新的数据
     */
    private void buildSafeMaintenanceDataSaveList(
            List<List<Map<String, Object>>> safeMaintenanceSyncDataList,
            Map<String, String> checkErrorMap,
            String ip,
            List<CheckTemplateDo> dataSave) {

        ExecutorService executorService = createCustomThreadPool();

        try {
            // 处理安全维护同步任务
            for (List<Map<String, Object>> syncData : safeMaintenanceSyncDataList) {
                Future<Result> future = executorService.submit(() -> dataPush(ip, SAFEMAINTENANCECONSTANT, syncData));
                Result result = future.get();// 等待结果

                CheckTemplateDo checkTemplateDo;
                if (Objects.equals(result.getStatus(), 200)) {
                    // 当前批次成功，记录日志和状态
                    for (Map<String, Object> waitSyncDatum : syncData) {
                        checkTemplateDo = new CheckTemplateDo();
                        checkTemplateDo.setId((String) waitSyncDatum.get("TEMPLATEID"));
                        checkTemplateDo.setSyncstatus(SUCCESSSYNC);
                        checkTemplateDo.setSynclog(waitSyncDatum.toString());
                        checkTemplateDo.setSynctime(new Date());
                        dataSave.add(checkTemplateDo);
                    }
                } else {
                    //1.四色图信息同步失败，状态为同步失败
                    // 四色图信息同步失败，记录日志和状态
                    for (Map<String, Object> waitSyncDatum : syncData) {
                        checkTemplateDo = new CheckTemplateDo();
                        checkTemplateDo.setId((String) waitSyncDatum.get("TEMPLATEID"));
                        checkTemplateDo.setSyncstatus(FAILURESYNC);
                        checkTemplateDo.setSynclog(result.getMessage());
                        checkTemplateDo.setSynctime(new Date());
                        dataSave.add(checkTemplateDo);
                    }
                }
            }

            // 处理校验失败的数据
            for (Map.Entry<String, String> entry : checkErrorMap.entrySet()) {
                CheckTemplateDo checkTemplateDo = new CheckTemplateDo();
                checkTemplateDo.setId(entry.getKey());
                checkTemplateDo.setSynclog(entry.getValue());
                checkTemplateDo.setSyncstatus(WAITSYNC);
                checkTemplateDo.setSynctime(new Date());
                dataSave.add(checkTemplateDo);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executorService.shutdown(); // 关闭线程池
        }
    }

    private void collectDataIds(List<Map<String, Object>> waitSyncUnitData, List<String> riskUnitIds, String id) {
        // 遍历集合，取出每个 Map 中的 RISKUNIT_ID 对应的值
        for (Map<String, Object> map : waitSyncUnitData) {
            Object riskUnitIdObj = map.get(id);
            if (riskUnitIdObj != null) {
                // 转换为字符串并添加到列表中
                riskUnitIds.add(riskUnitIdObj.toString());
            } else {
                // 处理 RISKUNIT_ID 为 null 的情况
                System.out.println("发现 RISKUNIT_ID 为 null 的条目，已跳过");
            }
        }
    }

    private void collectElement(List<CheckTemplateDo> safeMaintenance, List<CheckTemplateItemsDo> safeMaintenanceItems) {
        // 构建一个 Map：key 是 CheckTemplateDo.id，value 是对应的 templatetype
        Map<String, String> templateTypeMap = safeMaintenance.stream()
                .collect(Collectors.toMap(
                        CheckTemplateDo::getId,
                        CheckTemplateDo::getTemplatetype,
                        (existing, replacement) -> existing // 如果有重复 key，保留第一个
                ));

// 遍历 safeMaintenanceItems，设置对应的 templatetype
        safeMaintenanceItems.forEach(item -> {
            String templatetype = templateTypeMap.get(item.getChecktemplateid());
            if (templatetype != null) {
                item.setTemplatetype(templatetype);
            }
        });

    }

    public static void populateBeanFromMap(FourColorSynchronizationVo target, Map<String, Object> pushMap) {
        for (Map.Entry<String, Object> entry : pushMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            try {
                // 判断对象是否有该属性
                if (PropertyUtils.isWriteable(target, key)) {
                    PropertyUtils.setSimpleProperty(target, key, value);
                } else {
                    System.out.println("属性 " + key + " 不存在或不可写");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
