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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import digital.laboratory.platform.inspection.convert.TestSampleDataExpandConverter;
import digital.laboratory.platform.inspection.dto.TestSampleDataExpandDTO;
import digital.laboratory.platform.inspection.entity.TestRecordSampleData;
import digital.laboratory.platform.inspection.enums.BusinessType;
import digital.laboratory.platform.inspection.constant.TestRecordSampleDataConstant;
import digital.laboratory.platform.inspection.dto.HairSewageDataDto;
import digital.laboratory.platform.inspection.dto.NPSCaseTestDataDto;
import digital.laboratory.platform.inspection.entity.TestRecordSampleDataExpand;
import digital.laboratory.platform.inspection.mapper.TestRecordSampleDataExpandMapper;
import digital.laboratory.platform.inspection.service.ProcessInspectDataService;
import digital.laboratory.platform.inspection.service.TestRecordSampleDataService;
import digital.laboratory.platform.inspection.service.TestRecordSampledataExpandService;
import digital.laboratory.platform.inspection.service.TestRecordService;
import digital.laboratory.platform.inspection.utils.datafile.nps.NPSTestDetailDataStruct;
import digital.laboratory.platform.inspetion.api.entity.TestRecord;
import digital.laboratory.platform.sys.entity.Drug;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author ChenJiangBao
* @description 针对表【b_test_record_sampledata_expand(样本检验数据的扩展信息)】的数据库操作Service实现
* @createDate 2025-03-19 14:58:17
*/
@Service
public class TestRecordSampledataExpandServiceImpl extends ServiceImpl<TestRecordSampleDataExpandMapper, TestRecordSampleDataExpand>
    implements TestRecordSampledataExpandService{

    @Resource
    private TestRecordService testRecordService;

    @Resource
    private TestRecordSampleDataService testRecordSampleDataService;

    @Resource
    private ProcessInspectDataService processInspectDataService;

    /**
     * 封装处理毛发案件、任务等检验扩展数据信息
     * @param hairSewageDataDto
     * @param testDataId
     * @return
     */
    public Collection<? extends TestRecordSampleDataExpand> saveHairSewageInspectExpData(HairSewageDataDto hairSewageDataDto, String testDataId) {
        List<TestRecordSampleDataExpand> hairSewageInspectExpDataList = new ArrayList<>();

        // 设置基峰的扩展数据
        if (!TestRecordSampleDataConstant.isInvalidValue(hairSewageDataDto.getPeakAreaUp())) {
            hairSewageInspectExpDataList.add(createTestRecordSampleDataExpand(testDataId, Boolean.TRUE,
                    hairSewageDataDto.getPeakAreaUp(), null, null, null, null, null, hairSewageDataDto.getQualitativeIonPairUp(), null));
        }

        if (!TestRecordSampleDataConstant.isInvalidValue(hairSewageDataDto.getPeakAreaDown())) {
            hairSewageInspectExpDataList.add(createTestRecordSampleDataExpand(testDataId, Boolean.FALSE,
                    hairSewageDataDto.getPeakAreaDown(), hairSewageDataDto.getIonAbundanceRatio(),
                    hairSewageDataDto.getIonAbundanceRatioWithinError(), hairSewageDataDto.getWhetherCheckOut(), null, null, hairSewageDataDto.getQualitativeIonPairDown(), null));
        }

        return hairSewageInspectExpDataList;
    }

    /**
     * 封装处理nps案件检验扩展数据信息
     *
     * @param npsCaseTestDataDto
     * @param testDataId
     * @return
     */
    @Override
    public Collection<? extends TestRecordSampleDataExpand> saveNPSInspectExpData(NPSCaseTestDataDto npsCaseTestDataDto, String testDataId) {
        // 检验数据
        List<NPSTestDetailDataStruct> npsTestSampleDataList = npsCaseTestDataDto.getTestSampleDataList();

        List<TestRecordSampleDataExpand> testRecordSampleDataExpandList = npsTestSampleDataList.stream().map(item -> {
            return createTestRecordSampleDataExpand(
                    testDataId,
                    item.getIsBasePeak() == 1 ? Boolean.TRUE : Boolean.FALSE,
                    item.getArea(),
                    item.getAbundanceRatio(),
                    item.getAbundanceRatioError(),
                    item.getWithinError(),
                    item.getRetTime(),
                    item.getMass(),
                    null, null
            );
        }).collect(Collectors.toList());

        return testRecordSampleDataExpandList;
    }

    /**
     * 根据业务类型保存检验数据扩展信息
     * @param testDataId 检验数据id
     * @param drug 对应的标准品毒品清单
     * @param businessType 业务类型
     * @return
     */
    @Override
    public List<TestRecordSampleDataExpand> saveExpDataByBusinessType(String testDataId, Drug drug, String businessType) {
        List<TestRecordSampleDataExpand> testRecordSampleDataExpandList = null;
        if (BusinessType.NPS_CASE.getBusinessType().equals(businessType)) {
            List<String> characteristicIonsList = StrUtil.split(drug.getCharacteristicIons(), "、");

            testRecordSampleDataExpandList = characteristicIonsList.stream().map(characteristicIons -> {
                TestRecordSampleDataExpand testRecordSampleDataExpand = new TestRecordSampleDataExpand();
                testRecordSampleDataExpand.setTestDataId(testDataId);
                if (characteristicIons.contains("*")) {
                    testRecordSampleDataExpand.setBasePeak(Boolean.TRUE);
                } else {
                    testRecordSampleDataExpand.setBasePeak(Boolean.FALSE);
                }
                // 如果有 * 号就替换掉
                testRecordSampleDataExpand.setMassToChargeRatio(new BigDecimal(characteristicIons.replace("*", "")));
                return testRecordSampleDataExpand;
            }).collect(Collectors.toList());
        } else {
            for (int i = 0; i < 2; i++) {
                TestRecordSampleDataExpand testRecordSampleDataExpand = new TestRecordSampleDataExpand();
                testRecordSampleDataExpand.setTestDataId(testDataId);
                if (i == 0) {
                    testRecordSampleDataExpand.setBasePeak(Boolean.TRUE);
                    testRecordSampleDataExpand.setQualitativeIonPair(drug.getMainProductIon());
                } else {
                    testRecordSampleDataExpand.setBasePeak(Boolean.FALSE);
                    testRecordSampleDataExpand.setQualitativeIonPair(drug.getMinorProductIon());
                }
                testRecordSampleDataExpandList.add(testRecordSampleDataExpand);
            }
        }

        return testRecordSampleDataExpandList;
    }

    /**
     *根据DTO去更新
     * @param updateDTO
     * @return
     */
    @Override
    public Boolean updateByDTO(TestSampleDataExpandDTO updateDTO) {
        TestRecordSampleDataExpand testRecordSampleDataExpand = TestSampleDataExpandConverter.dtoToEntity(updateDTO);
        boolean update = super.updateById(testRecordSampleDataExpand);
        if (update) {
            TestRecordSampleDataExpand sampleDataExpand = super.getById(updateDTO.getId());
            // 查询对应的基峰数据是否存在
            TestRecordSampleDataExpand basePeakData = super.getOne(Wrappers.<TestRecordSampleDataExpand>lambdaQuery()
                    .eq(TestRecordSampleDataExpand::getTestDataId, sampleDataExpand.getTestDataId())
                    .eq(TestRecordSampleDataExpand::getBasePeak, Boolean.TRUE)
            );
            if (!sampleDataExpand.getBasePeak() && basePeakData != null) {
                // 获取标准物质的扩展信息，1 先查询对应的实验数据 2 根据实验数据的实验id以及化合物以及类型获取标准物质的实验数据信息 3 根据标准物质实验数据id取对应的扩展数据
                TestRecordSampleData testRecordSampleData = testRecordSampleDataService.getById(sampleDataExpand.getTestDataId());
                TestRecord testRecord = testRecordService.getById(testRecordSampleData.getTestId());
                List<TestRecordSampleDataExpand> stdDataExpandList = null;
                if (!testRecordSampleData.getSampleType().equals(TestRecordSampleDataConstant.SAMPLE_TYPE_STD)) {
                    TestRecordSampleData stdTestSampleData = testRecordSampleDataService.getOne(Wrappers.<TestRecordSampleData>lambdaQuery().eq(TestRecordSampleData::getTestId, testRecordSampleData.getTestId()).eq(TestRecordSampleData::getCompoundName, testRecordSampleData.getCompoundName()).eq(TestRecordSampleData::getSampleType, TestRecordSampleDataConstant.SAMPLE_TYPE_STD));
                    stdDataExpandList = super.list(Wrappers.<TestRecordSampleDataExpand>lambdaQuery().eq(TestRecordSampleDataExpand::getTestDataId, stdTestSampleData.getId()));
                }
                if (sampleDataExpand.getPeakArea() != null && basePeakData.getPeakArea() != null) {
                    sampleDataExpand.setIonAbundanceRatio(sampleDataExpand.getPeakArea().divide(basePeakData.getPeakArea(), 5, BigDecimal.ROUND_HALF_UP));
                    if (CollUtil.isNotEmpty(stdDataExpandList)) {
                        stdDataExpandList.forEach(stdDataExpand -> {
                            if (stdDataExpand.getMassToChargeRatio().equals(sampleDataExpand.getMassToChargeRatio())) {
                                BigDecimal ionAbundanceRatioError = sampleDataExpand.getIonAbundanceRatio()
                                        .subtract(stdDataExpand.getIonAbundanceRatio())
                                        .divide(stdDataExpand.getIonAbundanceRatio(), 5, BigDecimal.ROUND_HALF_UP)
                                        .multiply(BigDecimal.valueOf(100));
                                sampleDataExpand.setIonAbundanceRatioError(ionAbundanceRatioError);
                                if (testRecord.getBusinessType().equals(BusinessType.NPS_CASE.getBusinessType())) {
                                    sampleDataExpand.setIonAbundanceRatioWithinError(processInspectDataService.getWithinErrorText(ionAbundanceRatioError, processInspectDataService.getErrorRange(sampleDataExpand.getIonAbundanceRatio())));
                                } else {
                                    sampleDataExpand.setIonAbundanceRatioWithinError(processInspectDataService.calculateHairCaseIonAbundanceRatioWithinError(ionAbundanceRatioError.doubleValue(), stdDataExpand.getIonAbundanceRatio().doubleValue()));
                                }
                            }
                        });
                    }
                    update = super.updateById(sampleDataExpand);
                }

            }
        }
        return update;
    }


    /**
     * 根据提供的参数创建一个TestRecordSampleDataExpand对象。
     *
     * @param testDataId                   测试数据ID
     * @param isBasePeak                   是否为基本峰
     * @param peakArea                     峰面积
     * @param ionAbundanceRatio            离子丰度比
     * @param ionAbundanceRatioError       离子丰度比误差
     * @param ionAbundanceRatioWithinError 离子丰度比是否在误差范围内
     * @param retTime                      碎片保留时间，目前该字段仅对nps实验有用
     * @param mass                         质荷比(m/z)，nps案件
     * @param qualitativeIonPair           定性离子对，生物案件使用
     * @param someOtherValue               其他值
     * @return 创建的TestRecordSampleDataExpand对象
     */
    private TestRecordSampleDataExpand createTestRecordSampleDataExpand(
            String testDataId,
            Boolean isBasePeak,
            Double peakArea,
            Double ionAbundanceRatio,
            Double ionAbundanceRatioError,
            String ionAbundanceRatioWithinError,
            Double retTime,
            String mass,
            String qualitativeIonPair,
            Double someOtherValue
    ) {
        TestRecordSampleDataExpand testRecordSampleDataExpand = new TestRecordSampleDataExpand();
        testRecordSampleDataExpand.setTestDataId(testDataId);
        testRecordSampleDataExpand.setId(IdWorker.getIdStr());
        testRecordSampleDataExpand.setBasePeak(isBasePeak);
        testRecordSampleDataExpand.setPeakArea(BigDecimal.valueOf(peakArea));  // 注意: BigDecimal.valueOf(double)

        if (ionAbundanceRatio != null) {
            testRecordSampleDataExpand.setIonAbundanceRatio(BigDecimal.valueOf(ionAbundanceRatio));
        }

        if (ionAbundanceRatioError != null) {
            testRecordSampleDataExpand.setIonAbundanceRatioError(BigDecimal.valueOf(ionAbundanceRatioError));
        }

        if (ionAbundanceRatioWithinError != null) {
            testRecordSampleDataExpand.setIonAbundanceRatioWithinError(ionAbundanceRatioWithinError);
        }

        if (retTime != null) {
            testRecordSampleDataExpand.setFragmentRetTime(BigDecimal.valueOf(retTime));
        }

        if (StrUtil.isNotBlank(mass)) {
            testRecordSampleDataExpand.setMassToChargeRatio(new BigDecimal(mass));
        }

        // 如果有其他需要设置的值，可以继续扩展
        if (someOtherValue != null) {
            // 处理其他值的设置逻辑
        }

        return testRecordSampleDataExpand;
    }

}
