package digital.laboratory.platform.inspection.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import digital.laboratory.platform.common.core.exception.CheckedException;
import digital.laboratory.platform.inspection.config.ApiPathProperties;
import digital.laboratory.platform.inspection.constant.TestRecordSampleDataConstant;
import digital.laboratory.platform.inspection.convert.TestRecordSampleDataConverter;
import digital.laboratory.platform.inspection.entity.TestRecordInstrument;
import digital.laboratory.platform.inspection.entity.TestRecordMethod;
import digital.laboratory.platform.inspection.entity.TestRecordReagent;
import digital.laboratory.platform.inspection.entity.TestRecordSampleData;
import digital.laboratory.platform.inspetion.api.enums.BusinessType;
import digital.laboratory.platform.inspection.mapper.TestRecordSampleDataMapper;
import digital.laboratory.platform.inspection.service.*;
import digital.laboratory.platform.inspection.vo.TestRecordReagentVO;
import digital.laboratory.platform.inspection.vo.TestRecordSampleDataExpandVO;
import digital.laboratory.platform.inspection.vo.TestRecordSampleDataVO;
import digital.laboratory.platform.inspetion.api.entity.EntrustInfo;
import digital.laboratory.platform.inspetion.api.entity.SampleInfo;
import digital.laboratory.platform.inspetion.api.entity.TestRecord;
import digital.laboratory.platform.othersys.utils.HttpsUtils;
import digital.laboratory.platform.sys.entity.Drug;
import digital.laboratory.platform.sys.entity.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.client.RestClientException;

import javax.annotation.Resource;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author ChenJiangBao
 * @version 1.0
 * @description: 推送数据到labscare平台接口
 * @date 2025/3/31 9:31
 */
@Slf4j
//@Service
public class PushDataToLabsCareServiceImpl implements PushDataToLabsCareService {

    @Resource
    private TestRecordService testRecordService;

    @Resource
    private EntrustInfoService entrustInfoService;

    @Resource
    private SampleInfoService sampleInfoService;

    @Resource
    private TestRecordReagentService testRecordReagentService;

    @Resource
    private TestRecordSampleDataMapper testRecordSampleDataMapper;

    @Resource
    private TestRecordInstrumentService testRecordInstrumentService;

    @Resource
    private TestRecordMethodService testRecordMethodService;

    @Resource
    private InspectRecordService inspectRecordService;

    @Resource
    private ProcessInspectDataService processInspectDataService;

    @Resource
    private CommonFeignService commonFeignService;

    @Resource
    private ApiPathProperties apiPathProperties;


    private final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");

    // "#NULL#" 作为空数据的占位符, 对于系统中没有的信息以占位符代替
    public final static String NULL_PLACEHOLDER = "#NULL#";

    // 生物检材定性检验记录标识
    private final static String BIOLOGY_QUALITATIVE_RECORD = "BiologyQualitativeRecord";

    // 普通检材定性记录非红外报告标识
    private final static String NON_INFRARED_GENERAL_QUALITATIVE_RECORD = "NonInfraredGeneralQualitativeRecord";

    /**
     * 做一个定时推送，对于推送失败的委托进行重新推送， 每天凌晨2点推送
     */
//    @Scheduled(cron = "30 * * * * ?") // 测试
    @Scheduled(cron = "0 0 2 * * ?")  // 每天凌晨 2 点执行
    public void timingPushDataToLabsCare() {
        log.info("定时推送数据到LabsCare......");
        // 查询检验鉴定推送失败的委托
        List<EntrustInfo> entrustList = entrustInfoService.list(
                Wrappers.<EntrustInfo>lambdaQuery()
                        .and(wrapper -> wrapper
                                .eq(EntrustInfo::getPushFlag, "")
                                .or()
                                .isNull(EntrustInfo::getPushFlag)
                                .or()
                                .like(EntrustInfo::getPushFlag, "false")
                        )
        );
        if (CollUtil.isEmpty(entrustList)) {
            return;
        }
        Map<String, EntrustInfo> entrustInfoMap = entrustList.stream().collect(Collectors.toMap(EntrustInfo::getId, Function.identity()));
        // 获取所有完成实验的数据
        List<TestRecord> testRecordList = testRecordService.list(Wrappers.<TestRecord>lambdaQuery()
                .eq(TestRecord::getStatus, 5).in(TestRecord::getBusinessId, entrustList.stream()
                        .map(EntrustInfo::getId).collect(Collectors.toList()))
        );
        if (CollUtil.isEmpty(testRecordList)) {
            return;
        }

        for (TestRecord testRecord : testRecordList) {
            EntrustInfo entrustInfo = entrustInfoMap.get(testRecord.getBusinessId());
            String pushFlag = entrustInfo.getPushFlag();
            if (StrUtil.isBlank(pushFlag)) {
                if(testRecord.getBusinessType().equals(BusinessType.BOINT_CASE.getBusinessType())) {
                    pushBiologyQualitativeRecordData(testRecord.getId());
                } else if (testRecord.getBusinessType().equals(BusinessType.NPS_CASE.getBusinessType())) {
                    pushNonInfraredGeneralQualitativeRecordData(testRecord.getId());
                }
            } else {
                List<String> flagList = StrUtil.split(pushFlag, StrUtil.COMMA).stream().filter(str -> str.contains("false")).collect(Collectors.toList());
                for (String flag : flagList) {
                    if (flag.contains(BIOLOGY_QUALITATIVE_RECORD)) {
                        pushBiologyQualitativeRecordData(testRecord.getId());
                    } else {
                        pushNonInfraredGeneralQualitativeRecordData(testRecord.getId());
                    }
                }
            }
        }
    }

    /**
     * 推送普通检材定性记录非红外报告数据
     * @param testId 实验id
     */
    @Override
    public void pushNonInfraredGeneralQualitativeRecordData(String testId) {
        TestRecord testRecord = validTestRecord(testId);
        if (testRecord == null) return;
        // 获取委托信息
        EntrustInfo entrustInfo = entrustInfoService.getById(testRecord.getBusinessId());

        JSONObject recordJsonPayload = buildNonInfraredGeneralQualitativeRecordJsonPayload(entrustInfo, testRecord);

        String successFlag = NON_INFRARED_GENERAL_QUALITATIVE_RECORD + ":true";
        String failureFlag = NON_INFRARED_GENERAL_QUALITATIVE_RECORD + ":false";
        try {
            ResponseEntity<String> response = exchangeRemoteApi(recordJsonPayload, apiPathProperties.getNonInfraredGeneralQualitativeRecord());

            if (response.getStatusCode().is2xxSuccessful() && response.getBody().contains("\"status\":200")) {
                updatePushFlag(entrustInfo, NON_INFRARED_GENERAL_QUALITATIVE_RECORD, successFlag);
                log.info("推送普通检材定性记录非红外报告数据成功, 受理编号: {}, 响应: {}", entrustInfo.getAcceptNo(), response.getBody());
            } else {
                updatePushFlag(entrustInfo, NON_INFRARED_GENERAL_QUALITATIVE_RECORD, failureFlag);
                log.warn("推送普通检材定性记录非红外报告数据失败, 受理编号: {}, 状态码: {}, 响应: {}",
                        entrustInfo.getAcceptNo(), response.getStatusCode(), response.getBody());
            }
        } catch (RestClientException e) {
            log.error("推送普通检材定性记录非红外报告数据到 LabsCare 失败, 受理编号: {}", entrustInfo.getAcceptNo(), e);
        }
    }

    /**
     * 验证并获取有效的实验信息
     *
     * @param testId 测试记录的唯一标识符
     * @return 如果存在有效的测试记录，则返回该测试记录；否则返回null
     */
    private TestRecord validTestRecord(String testId) {
        TestRecord testRecord = testRecordService.getById(testId);
        if (testRecord == null) {
            log.error("实验id为 [{}] 的实验信息查询为空！", testId);
            return null;
        }
        return testRecord;
    }

    /**
     * 推送生物检材定性记录
     * @param testId 实验id
     */
    @Override
    public void pushBiologyQualitativeRecordData(String testId) {
        TestRecord testRecord = validTestRecord(testId);
        if (testRecord == null) return;
        // 获取委托信息
        EntrustInfo entrustInfo = entrustInfoService.getById(testRecord.getBusinessId());

        JSONObject recordJsonPayload = buildBiologyQualitativeRecordJsonPayload(entrustInfo, testRecord);

        String successFlag = BIOLOGY_QUALITATIVE_RECORD + ":true";
        String failureFlag = BIOLOGY_QUALITATIVE_RECORD + ":false";
        try {
            ResponseEntity<String> response = exchangeRemoteApi(recordJsonPayload, apiPathProperties.getBiologyQualitativeRecord());

            if (response.getStatusCode().is2xxSuccessful() && response.getBody().contains("\"status\":200")) {
                updatePushFlag(entrustInfo, BIOLOGY_QUALITATIVE_RECORD, successFlag);
                log.info("推送生物定性检验记录数据成功, 受理编号: {}, 响应: {}", entrustInfo.getAcceptNo(), response.getBody());
            } else {
                updatePushFlag(entrustInfo, BIOLOGY_QUALITATIVE_RECORD, failureFlag);
                log.warn("推送生物定性检验记录数据失败, 受理编号: {}, 状态码: {}, 响应: {}",
                        entrustInfo.getAcceptNo(), response.getStatusCode(), response.getBody());
            }
        } catch (RestClientException e) {
            log.error("推送生物定性检验记录数据到 LabsCare 失败, 受理编号: {}", entrustInfo.getAcceptNo(), e);
        }
    }

    /**
     * 根据委托id获取检验记录数据
     * @param entrustId 委托id
     * @return
     */
    @Override
    public JSONObject fetchInspectRecordData(String entrustId) {
        EntrustInfo entrustInfo = entrustInfoService.getById(entrustId);
        if (entrustInfo == null) {
            log.error("委托id为 {} 的委托信息不存在", entrustId);
            throw new CheckedException(String.format("委托id为 %s 的委托信息查询不到", entrustId));
        }
        // 根据委托id查询对应的实验信息
        TestRecord testRecord = testRecordService.getOne(Wrappers.<TestRecord>lambdaQuery().eq(TestRecord::getBusinessId, entrustId).last("LIMIT 1"));
        if (testRecord == null) {
            log.error("委托id为 {} 对应的实验信息不存在", entrustId);
            throw new CheckedException(String.format("委托id为 %s 对应的实验信息查询不到", entrustId));
        }
        if (entrustInfo.getBusinessType().equals(BusinessType.BOINT_CASE.getBusinessType())) {
            return buildBiologyQualitativeRecordJsonPayload(entrustInfo, testRecord);
        }
        return buildNonInfraredGeneralQualitativeRecordJsonPayload(entrustInfo, testRecord);
    }

    /**
     * 构建生物检材定性记录Json数据
     *
     * @param entrustInfo 委托信息
     * @param testRecord  测试记录
     * @return 构建好的Json对象
     */
    private JSONObject buildBiologyQualitativeRecordJsonPayload(EntrustInfo entrustInfo, TestRecord testRecord) {
        // 查询封装需要用到的数据
        List<SampleInfo> sampleInfoList = sampleInfoService
                .lambdaQuery()
                .in(SampleInfo::getId, testRecord.getSampleTestList())
                .list();
        // 检材转map
        Map<String, SampleInfo> sampleInfoMap = sampleInfoList.stream().collect(Collectors.toMap(SampleInfo::getAcceptNo, Function.identity()));
        // 对受理编号进行分隔
        List<String> splitAcceptNo = StrUtil.split(entrustInfo.getAcceptNo(), "-");

        // 设置使用的标准物质和试剂
        List<TestRecordReagentVO> references = testRecordReagentService.voListByWrapper(Wrappers.<TestRecordReagent>lambdaQuery()
                .in(TestRecordReagent::getId, testRecord.getReagentConsumablesList())
                .eq(TestRecordReagent::getCategory, "标准物质"));
        // 本次实验使用的标准品
        String stdStr = references.stream().map(TestRecordReagentVO::getReagentConsumableName).collect(Collectors.joining("、"));

        // 获取标准物质对应的毒品成分
        Map<String, Drug> drugMap = references.stream().map(TestRecordReagentVO::getDrug).collect(Collectors.toMap(Drug::getEnglishName, Function.identity()));

        // 获取检测人用户信息
        SysUser testUser = commonFeignService.remoteGetUserById(testRecord.getTestUserId());

        // 获取样品检测数据，按照样品编号分组
        Map<String, List<TestRecordSampleDataVO>> testDataGroupBySampleNO = fetchTestDataGroupBySampleNo(testRecord);

        // 获取标准物质的测试数据
        Map<String, TestRecordSampleDataVO> stdTestDataMap = fetchStdTestData(testRecord);

        // 获取使用的仪器和方法
        String useInstrumentNameStr = getInstrumentNames(testRecord);
        String useMethodNameStr = getMethodNames(testRecord);

        // 开始封装数据参数
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("jcxz", inspectRecordService.buildMaterialCharacterDesc(sampleInfoList)); // 检材性状描述
        jsonObject.set("jdwsh", String.format("[%s]%s号", splitAcceptNo.get(0), splitAcceptNo.get(1))); // 鉴定文书号
        jsonObject.set("jysj", testRecord.getTestStartDate().format(formatter)); // 检验时间
        jsonObject.set("jyy1qm", testUser.getName()); // 检测人1
        jsonObject.set(
                "jyyq",
                String.format("对所送检材中是否含有 %s 成分进行定性检测", stdStr)
        ); // 检验要求，根据模板上的值来生成
        jsonObject.set("sjr1", entrustInfo.getDeliver1Name()); // 送检人1
        jsonObject.set("sjr2", entrustInfo.getDeliver2Name()); // 送检人2
        jsonObject.set("slrq", entrustInfo.getAcceptDate().format(formatter)); // 受理日期
        jsonObject.set("sprqm", testUser.getName()); // 检测人2
        jsonObject.set("swmbw", stdStr); // 生物检测目标物
        jsonObject.set("tpfj", NULL_PLACEHOLDER); // 图谱
        jsonObject.set("wtdw", entrustInfo.getEntrustDepartment());

        // 生物检材定性记录样品信息
        List<JSONObject> sampleJsonList = new ArrayList<>();
        testDataGroupBySampleNO.forEach((sampleNo,  testDataList) -> {
            JSONObject sampleJson = new JSONObject();
            sampleJson.set("caseName", sampleNo); // 样品编号

            // 该样品编号对应的检测数据信息
            List<JSONObject> gauging = testDataList.stream().map(data -> {
                JSONObject testDataJson = new JSONObject();
                testDataJson.set("blsjxdwc", data.getRtTimeError()); // 保留时间相对误差（%）
                TestRecordSampleDataVO stdData = stdTestDataMap.get(data.getCompoundName());
                testDataJson.set("bzwzblsj", stdData.getTargetRtTime()); // 标准物质保留时间（min）
                testDataJson.set("bzwzfdb", stdData.getIonAbundanceRatio()); // 标准物质离子对相对丰度比
                testDataJson.set("bzwzwb", stdData.getCompoundName()); // 标准物质名称
                testDataJson.set("dcypfdb", data.getIonAbundanceRatio()); // 待测样品离子对相对丰度比
                testDataJson.set("dxlzd", data.getExpandList().stream().map(TestRecordSampleDataExpandVO::getQualitativeIonPair).collect(Collectors.joining(","))); // 定性离子对
                testDataJson.set("dxyq", useInstrumentNameStr); // 使用仪器
                testDataJson.set("fdbwc", data.getIonAbundanceRatioError()); // 丰度比相对偏差
                testDataJson.set("ffStr", useMethodNameStr); // 所用的方法
                testDataJson.set("gradientA", NULL_PLACEHOLDER); // 梯度洗脱参考条件-A（%）
                testDataJson.set("gradientB", NULL_PLACEHOLDER); // 梯度洗脱参考条件-B（%）
                testDataJson.set("gradientTime", NULL_PLACEHOLDER); // 梯度洗脱参考条件-时间（min）
                testDataJson.set("jcxz", sampleInfoMap.get(data.getSampleNo()).getForm()); // 检材性状描述
                testDataJson.set("jdwsh", String.format("[%s]%s号", splitAcceptNo.get(0), splitAcceptNo.get(1))); // 鉴定文书号
                testDataJson.set("jdyj", inspectRecordService.buildInspectOpinion(Collections.singletonList(TestRecordSampleDataConverter.voToEntity(data))));
                testDataJson.set("jgpd", data.getWhetherCheckOut()); // 结果判定
                testDataJson.set("jysj", testRecord.getTestStartDate().format(formatter)); // 检验时间
                testDataJson.set("jyyq", String.format("对所送检材中是否含有 %s 成分进行定性检测", stdData.getCompoundCnName())); // 检验要求
                testDataJson.set("mbwblsj", data.getTargetRtTime()); // 目标物保留时间（min）
                testDataJson.set("projectName", "定性检测"); // 化合物名称， 对方公司并未标明该字段信息
                // 获取对应的化合物信息
                Drug drug = drugMap.get(data.getCompoundName());
                testDataJson.set("pzdy", StrUtil.join(",", drug.getMainCollisionEnergy(), drug.getMinorCollisionEnergy())); // 碰撞电压
                testDataJson.set("rjwb", NULL_PLACEHOLDER); // 溶剂
                testDataJson.set("sjr1", entrustInfo.getDeliver1Name()); // 送检人1
                testDataJson.set("sjr2", entrustInfo.getDeliver2Name()); // 送检人2
                testDataJson.set("slrq", entrustInfo.getAcceptDate().format(formatter)); // 受理日期
                testDataJson.set("swbzgzyzb", NULL_PLACEHOLDER); // 标准工作溶液制备
                testDataJson.set("swdcypzb", NULL_PLACEHOLDER);  // 待测样品制备
                testDataJson.set("swmbw", drug.getName()); // 目标物
                testDataJson.set("swsj", NULL_PLACEHOLDER); // 上机
                testDataJson.set("swyxtj", NULL_PLACEHOLDER); // 	液相条件
                testDataJson.set("swzptj", NULL_PLACEHOLDER); // 质谱条件
                testDataJson.set("wjcjgpd", "±" + processInspectDataService.getHairCaseIonAbundanceRatioWithinErrorRange(Double.parseDouble(stdData.getIonAbundanceRatio()))); //相对离子丰度比的最大允许相对误差（%）
                testDataJson.set("wtdw", entrustInfo.getEntrustDepartment());
                testDataJson.set("wzdy", StrUtil.join(",", drug.getMainDeclusteringPotential(), drug.getMinorDeclusteringPotential()));
                return testDataJson;
            }).collect(Collectors.toList());
            sampleJson.set("gauging", gauging); // 生物检材定性记录检测信息
            sampleJsonList.add(sampleJson);
        });
        jsonObject.set("sample", sampleJsonList);
        return jsonObject;
    }

    /**
     * 普通检材定性记录 非红外报告  的json 数据
     *
     * @param entrustInfo 委托信息
     * @param testRecord  测试记录
     * @return 构建好的Json对象
     */
    private JSONObject buildNonInfraredGeneralQualitativeRecordJsonPayload(EntrustInfo entrustInfo, TestRecord testRecord) {
        // 查询封装需要用到的数据
        List<SampleInfo> sampleInfoList = sampleInfoService
                .lambdaQuery()
                .in(SampleInfo::getId, testRecord.getSampleTestList())
                .list();
        // 对受理编号进行分隔
        List<String> splitAcceptNo = StrUtil.split(entrustInfo.getAcceptNo(), "-");

        // 设置使用的标准物质和试剂
        List<TestRecordReagentVO> references = testRecordReagentService.voListByWrapper(Wrappers.<TestRecordReagent>lambdaQuery()
                .in(TestRecordReagent::getId, testRecord.getReagentConsumablesList())
                .eq(TestRecordReagent::getCategory, "标准物质"));
        // 本次实验使用的标准品
        String stdStr = references.stream().map(TestRecordReagentVO::getReagentConsumableName).collect(Collectors.joining("、"));

        // 获取检测人用户信息
        SysUser testUser = commonFeignService.remoteGetUserById(testRecord.getTestUserId());

        // 获取样品检测数据，按照样品编号分组
        Map<String, List<TestRecordSampleDataVO>> testDataGroupBySampleNO = fetchTestDataGroupBySampleNo(testRecord);

        // 获取标准物质的测试数据
        Map<String, TestRecordSampleDataVO> stdTestDataMap = fetchStdTestData(testRecord);
        // 获取使用的仪器和方法
        String useInstrumentNameStr = getInstrumentNames(testRecord);
        String useMethodNameStr = getMethodNames(testRecord);

        // 开始封装数据参数
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("jcxz", inspectRecordService.buildMaterialCharacterDesc(sampleInfoList)); // 检材性状描述
        jsonObject.set("jdwsh", String.format("[%s]%s号", splitAcceptNo.get(0), splitAcceptNo.get(1))); // 鉴定文书号
        jsonObject.set("jysj", testRecord.getTestStartDate().format(formatter)); // 检验时间
        jsonObject.set("jyy1qm", testUser.getName()); // 检测人1
        jsonObject.set(
                "jyyq",
                String.format("对所送检材中是否含有 %s 成分进行定性检测", stdStr)
        ); // 检验要求，根据模板上的值来生成
        jsonObject.set("sjr1", entrustInfo.getDeliver1Name()); // 送检人1
        jsonObject.set("sjr2", entrustInfo.getDeliver2Name()); // 送检人2
        jsonObject.set("slrq", entrustInfo.getAcceptDate().format(formatter)); // 受理日期
        jsonObject.set("sprqm", testUser.getName()); // 检测人2
        jsonObject.set("tpfj", NULL_PLACEHOLDER); // 图谱
        jsonObject.set("wtdw", entrustInfo.getEntrustDepartment());
        // 普通检材定性记录 非红外样品信息
        List<JSONObject> sampleJsonList = new ArrayList<>();
        testDataGroupBySampleNO.forEach((sampleNo,  testDataList) -> {
            JSONObject sampleJson = new JSONObject();
            sampleJson.set("caseName", sampleNo); // 样品编号

            // 普通检材定性记录 非红外检测信息
            List<JSONObject> gauging = testDataList.stream().map(data -> {
                JSONObject testDataJson = new JSONObject();
                testDataJson.set("blsjxdwc", data.getRtTimeError()); // 保留时间相对误差（%）
                testDataJson.set("bzgzyzb", NULL_PLACEHOLDER); // 标准工作溶液制备
                TestRecordSampleDataVO stdData = stdTestDataMap.get(data.getCompoundName());
                testDataJson.set("bzwzblsj", stdData.getTargetRtTime()); // 标准物质保留时间（min）
                testDataJson.set("bzwzwb", stdData.getCompoundName()); // 标准物质名称
                testDataJson.set("dcypzb", NULL_PLACEHOLDER);  // 待测样品制备
                testDataJson.set("dxff", useMethodNameStr); // 所用的方法
                testDataJson.set("dxyq", useInstrumentNameStr); // 使用仪器
                testDataJson.set("jdyj", inspectRecordService.buildInspectOpinion(Collections.singletonList(TestRecordSampleDataConverter.voToEntity(data))));
                testDataJson.set("jgpd", data.getWhetherCheckOut()); // 结果判定
                testDataJson.set("jysj", testRecord.getTestStartDate().format(formatter)); // 检验时间
                testDataJson.set("jytj", NULL_PLACEHOLDER); // 进样条件
                testDataJson.set("mbwblsj", data.getTargetRtTime()); // 目标物保留时间（min）
                testDataJson.set("rjwb", NULL_PLACEHOLDER); // 溶剂
                testDataJson.set("sj", NULL_PLACEHOLDER); // 上机
                testDataJson.set("spz", NULL_PLACEHOLDER); // 仪器条件-色谱柱
                testDataJson.set("zptppd", NULL_PLACEHOLDER); // 质谱图匹配度（%）
                testDataJson.set("zw", NULL_PLACEHOLDER); // 柱温
                return testDataJson;
            }).collect(Collectors.toList());
            sampleJson.set("gauging", gauging); // 生物检材定性记录检测信息
            sampleJsonList.add(sampleJson);
        });
        jsonObject.set("sample", sampleJsonList);
        return jsonObject;
    }

    /**
     * 通过POST请求与远程API进行交互
     *
     * @param jsonObject 包含请求数据的JSONObject对象
     * @param url        远程API的URL
     * @return ResponseEntity<String> 包含远程API响应数据的ResponseEntity对象
     */
    private ResponseEntity<String> exchangeRemoteApi(JSONObject jsonObject, String url) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);  // 设置为 application/json
        HttpEntity<JSONObject> requestEntity = new HttpEntity<>(jsonObject, headers);
        ResponseEntity<String> response = HttpsUtils
                .genRestTemplate()
                .exchange(
                        url,
                        HttpMethod.POST,
                        requestEntity,
                        String.class
                );
        return response;
    }

    /**
     * 更新推送标志
     *
     * @param entrust   委托对象
     * @param pushType    推送类型 EntrustLetter 委托书 | ItemConfirmLetter 事项确认书
     * @param newFlag     新的推送标志
     */
    private void updatePushFlag(EntrustInfo entrust, String pushType, String newFlag) {
        List<String> flagList = Optional.ofNullable(StrUtil.split(entrust.getPushFlag(), StrUtil.COMMA))
                .orElse(new ArrayList<>());

        // 判断是否已有 指定的推送类型，如果有就替换，否则添加
        boolean exists = flagList.stream().anyMatch(flag -> flag.contains(pushType));
        if (exists) {
            flagList.replaceAll(flag -> flag.contains(pushType) ? newFlag : flag);
        } else {
            flagList.add(newFlag);
        }
        // 更新标识, 防止定时任务那里连续推送数据时推送标识更新出错
        entrust.setPushFlag(String.join(",", flagList));
        // 更新数据库
        entrustInfoService.update(Wrappers.<EntrustInfo>lambdaUpdate()
                .eq(EntrustInfo::getId, entrust.getId())
                .set(EntrustInfo::getPushFlag, String.join(",", flagList)));
    }


    /**
     * 根据实验记录中的样本编号对检验数据进行分组。
     *
     * @param testRecord 测试记录对象
     * @return 包含分组后的测试数据映射关系，键为样本编号，值为样本编号对应的测试数据列表
     */
    private Map<String, List<TestRecordSampleDataVO>> fetchTestDataGroupBySampleNo(TestRecord testRecord) {
        return testRecordSampleDataMapper.queryTestRecordSampleDataVOList(Wrappers.<TestRecordSampleData>lambdaQuery()
                        .eq(TestRecordSampleData::getTestId, testRecord.getId())
                        .eq(TestRecordSampleData::getSampleType, TestRecordSampleDataConstant.SAMPLE_TYPE_ANALYTE))
                .stream()
                .collect(Collectors.groupingBy(TestRecordSampleDataVO::getSampleNo));
    }

    /**
     * 根据实验id获取标准测试数据
     *
     * @param testRecord 测试记录对象
     * @return 标准测试数据的Map集合，键为化合物名称，值为TestRecordSampleDataVO对象
     */
    private Map<String, TestRecordSampleDataVO> fetchStdTestData(TestRecord testRecord) {
        return testRecordSampleDataMapper.queryTestRecordSampleDataVOList(Wrappers.<TestRecordSampleData>lambdaQuery()
                        .eq(TestRecordSampleData::getTestId, testRecord.getId())
                        .eq(TestRecordSampleData::getSampleType, TestRecordSampleDataConstant.SAMPLE_TYPE_STD))
                .stream()
                .collect(Collectors.toMap(TestRecordSampleDataVO::getCompoundName, Function.identity()));
    }


    /**
     * 根据测试记录获取仪器名称列表
     *
     * @param testRecord 测试记录对象
     * @return 仪器名称列表，若列表为空则返回NULL_PLACEHOLDER
     */
    private String getInstrumentNames(TestRecord testRecord) {
        List<String> deviceIdList = testRecord.getDeviceIdList();
        List<TestRecordInstrument> instruments = CollectionUtils.isEmpty(deviceIdList)
                ? Collections.emptyList()
                : testRecordInstrumentService.list(Wrappers.<TestRecordInstrument>lambdaQuery()
                .in(TestRecordInstrument::getId, deviceIdList));

        return CollectionUtils.isEmpty(instruments)
                ? NULL_PLACEHOLDER
                : instruments.stream()
                .map(TestRecordInstrument::getInstrumentName)
                .collect(Collectors.joining(","));
    }

    /**
     * 获取方法名称列表，用逗号分隔
     *
     * @param testRecord 测试记录对象
     * @return 方法名称列表，用逗号分隔，若为空则返回NULL_PLACEHOLDER
     */
    private String getMethodNames(TestRecord testRecord) {
        List<String> testMethodList = testRecord.getTestMethodList();
        List<TestRecordMethod> testRecordMethodList = CollectionUtils.isEmpty(testMethodList)
                ? Collections.emptyList()
                : testRecordMethodService.list(Wrappers.<TestRecordMethod>lambdaQuery()
                .in(TestRecordMethod::getId, testMethodList));

        return CollectionUtils.isEmpty(testRecordMethodList)
                ? NULL_PLACEHOLDER
                : testRecordMethodList.stream()
                .map(TestRecordMethod::getMethodName)
                .collect(Collectors.joining(","));
    }
}
