package digital.laboratory.platform.inspection.service.impl;
/*
 *@title SampleInfoServiceImpl
 *@description
 *@author xy
 *@version 1.0
 *@create 2023/12/8 11:10
 */

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import digital.laboratory.platform.common.mybatis.security.service.DLPUser;
import digital.laboratory.platform.inspection.dto.TestRecordArgumentDto;
import digital.laboratory.platform.inspection.entity.*;
import digital.laboratory.platform.inspection.enums.TestRecordArgumentType;
import digital.laboratory.platform.inspection.mapper.SampleInfoMapper;
import digital.laboratory.platform.inspection.mapper.TestRecordMapper;
import digital.laboratory.platform.inspection.service.*;
import digital.laboratory.platform.inspetion.api.entity.*;
import digital.laboratory.platform.inspetion.api.vo.TestRecordVo;
import digital.laboratory.platform.sys.entity.DrugLite;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

@Service
@Slf4j
public class SampleInfoServiceImpl extends ServiceImpl<SampleInfoMapper, SampleInfo> implements SampleInfoService {

    @Resource
    private AssignmentInfoService assignmentInfoService;
    @Resource
    private TestRecordService testRecordService;
    @Resource
    private TestRecordMapper testRecordMapper;

    @Resource
    private TestRecordSampleSolutionService testRecordSampleSolutionService;
    @Resource
    private TestRecordSampleDataService testRecordSampleDataService;

    @Resource
    @Lazy
    private EntrustInfoService entrustInfoService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SampleInfo addSampleInfo(SampleInfo sampleInfo) {
        if (StringUtils.isBlank(sampleInfo.getId())) {
            sampleInfo.setId(IdWorker.get32UUID());
            log.info("保存对象sampleInfo的ID为空，由系统生成一个给它使用 {}", sampleInfo.getId());
        }
        List<SampleInfo> sampleInfos = new ArrayList<>();
        if (sampleInfo.getBusinessType().startsWith("1")) {
            EntrustInfo entrustInfo = entrustInfoService.getById(sampleInfo.getBusinessId());
            sampleInfos = this.list(Wrappers.<SampleInfo>lambdaQuery().eq(SampleInfo::getBusinessId, sampleInfo.getBusinessId()).orderByAsc(SampleInfo::getOrderNo));
            //鉴定要求与顺序号
            if (sampleInfos != null && sampleInfos.size() > 0) {
                sampleInfos.add(sampleInfo);
                sampleInfo.setOrderNo(sampleInfos.size());
                entrustInfo.setEntrustRequirement(this.getNameDesStrForEntrust(sampleInfos));
            } else {
                sampleInfos.add(sampleInfo);
                sampleInfo.setOrderNo(1);
                entrustInfo.setEntrustRequirement(this.getNameDesStrForEntrust(sampleInfos));
            }
            entrustInfoService.updateById(entrustInfo);
        }
        sampleInfo.setStatus(0);
        boolean ret = this.save(sampleInfo);
        if (ret) {
            log.info("{} 保存成功", sampleInfo);
            return sampleInfo;
        } else {
            log.info("{} 保存失败", sampleInfo);
            return null;
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public SampleInfo updateSampleInfo(SampleInfo sampleInfo) {
        if (sampleInfo.getSource() == 0) {
            log.info("数据是其他系统推送录入的，不能修改");
            return null;
        }
        if (sampleInfo.getBusinessType().startsWith("1")) {
            EntrustInfo entrustInfo = entrustInfoService.getById(sampleInfo.getBusinessId());
            List<SampleInfo> sampleInfoList = this.list(Wrappers.<SampleInfo>lambdaQuery().eq(SampleInfo::getBusinessId, sampleInfo.getBusinessId()));
            //鉴定要求
            entrustInfo.setEntrustRequirement(this.getNameDesStrForEntrust(sampleInfoList));
            entrustInfoService.updateById(entrustInfo);
        }
        boolean ret = this.updateById(sampleInfo);
        if (ret) {
            return sampleInfo;
        } else {
            return null;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteSampleInfo(String id) {
        SampleInfo sampleInfo = this.getById(id);
        if (sampleInfo.getSource() == 0) {
            log.info("数据是其他系统推送录入的，不能修改");
            throw new RuntimeException(String.format("数据是其他系统推送录入的，不能修改"));
        }
        //查询顺序号大于被删除的全部检材
        List<SampleInfo> sampleInfoList = this.list(Wrappers.<SampleInfo>lambdaQuery()
                .eq(SampleInfo::getBusinessId, sampleInfo.getBusinessId())
                .gt(SampleInfo::getOrderNo, sampleInfo.getOrderNo()));

        //将后面的顺序号减一 保持不断号
        if (sampleInfoList != null && sampleInfoList.size() > 0) {
            sampleInfoList.forEach(item -> {
                item.setOrderNo(item.getOrderNo() - 1);
            });
        }
        this.updateBatchById(sampleInfoList);
        return this.removeById(id);
    }

    @Override
    public IPage getSampleInfoPageList(Page page, SampleInfo sampleInfo) {
        IPage ret = this.page(page, Wrappers.<SampleInfo>lambdaQuery()
                .like(StringUtils.isNotBlank(sampleInfo.getSampleName()), SampleInfo::getSampleName, sampleInfo.getSampleName())
                .eq(sampleInfo.getStatus() != null, SampleInfo::getStatus, sampleInfo.getStatus())
                .orderByAsc(SampleInfo::getOrderNo));
        return ret;
    }

    @Override
    public List<SampleInfo> getSampleInfoList(SampleInfo sampleInfo) {
        List<SampleInfo> retList = this.list(Wrappers.<SampleInfo>lambdaQuery()
                .eq(SampleInfo::getBusinessId, sampleInfo.getBusinessId())
                .like(StringUtils.isNotBlank(sampleInfo.getSampleName()), SampleInfo::getSampleName, sampleInfo.getSampleName())
                .eq(sampleInfo.getStatus() != null, SampleInfo::getStatus, sampleInfo.getStatus())
                .orderByAsc(SampleInfo::getOrderNo));

        for (SampleInfo info : retList) {
            List<AssignmentInfo> list = assignmentInfoService.list(Wrappers.<AssignmentInfo>lambdaQuery().eq(AssignmentInfo::getSampleId, info.getId()));
            if (list.size() > 0) {
                info.setIsDistribution(true);
            } else {
                info.setIsDistribution(false);
            }
        }
        return retList;
    }

    @Override
    public Boolean checkExist(String id) {
        List<SampleInfo> retList = this.list(Wrappers.<SampleInfo>lambdaQuery()
                .eq(SampleInfo::getId, id));
        if (retList.size() > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 分页查询
     *
     * @param page
     * @param dlpUser
     * @param testId
     * @param keywords 样本编号、样本名称、业务名称查询参数
     * @return
     */
    @Override//
    public IPage getPageForTestRecord(Page page, DLPUser dlpUser, String testId, String keywords) {
        if (StringUtils.isNotBlank(testId)) {//查询这个实验下面绑定的检材列表
            TestRecordVo testRecordVo = testRecordMapper.getTestRecordMapById(testId);
            List<String> sampleTestList = testRecordVo.getSampleTestList();
            if (sampleTestList == null || sampleTestList.size() == 0) {
                sampleTestList.add("");//这一步操作是为了保证下面查询的时候不出错，如果没有对应的ID集合，那么应该就查不出来
            }
            return baseMapper.getFullSampleInfoList(page, Wrappers.<SampleInfo>lambdaQuery()
                    .in(SampleInfo::getId, sampleTestList)
                    .orderByAsc(SampleInfo::getOrderNo));
        } else {
            Integer status = 1;//代表已分配但未加入实验的检材的状态
            List<AssignmentInfo> assignmentInfoList = assignmentInfoService.list(Wrappers.<AssignmentInfo>lambdaQuery().in(AssignmentInfo::getTestUser, dlpUser.getId()));
            ArrayList<String> idList = new ArrayList<>();
            if (assignmentInfoList != null && assignmentInfoList.size() > 0) {
                assignmentInfoList.forEach(item -> idList.add(item.getSampleId()));
            }
            if (idList == null || idList.size() == 0) {
                idList.add("");//这一步操作是为了保证下面查询的时候不出错，如果没有对应的ID集合，那么应该就查不出来
            }
            return baseMapper.getFullSampleInfoList(page, Wrappers.<SampleInfo>lambdaQuery()
                    .and(StringUtils.isNotBlank(keywords), qw -> qw
                            .like(SampleInfo::getAcceptNo, keywords)
                            .or()
                            .like(SampleInfo::getSampleName, keywords)
                            .or()
                            .like(SampleInfo::getBusinessType, keywords))
                    .in(SampleInfo::getId, idList).eq(SampleInfo::getStatus, status).orderByAsc(SampleInfo::getOrderNo));
        }
    }

    /**
     * 向实验添加或移除检材
     *
     * @param testRecordArgumentDto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean useTestRecordSample(TestRecordArgumentDto testRecordArgumentDto) {
        SampleInfo sampleInfo = this.getById(testRecordArgumentDto.getArgumentId());
        TestRecord testRecord = testRecordService.getById(testRecordArgumentDto.getTestRecordId());
        if (testRecordArgumentDto.getOpCode() == -1) {
            testRecordSampleSolutionService.isLoadSample(sampleInfo.getAcceptNo(), testRecordArgumentDto.getTestRecordId());
            List<TestRecordSampleData> sampleDataList = testRecordSampleDataService.list(Wrappers.<TestRecordSampleData>lambdaQuery()
                    .eq(TestRecordSampleData::getTestId, testRecordArgumentDto.getTestRecordId())
                    .eq(TestRecordSampleData::getSampleNo, sampleInfo.getAcceptNo()));
            if (testRecord.getBusinessType().startsWith("1") && sampleDataList.size() > 0) {
                throw new RuntimeException(String.format("当前检材已存在上机数据，无法移除!"));
            }
        }
        if (testRecordArgumentDto.getOpCode() == 1) {
            if (sampleInfo.getStatus() != 1) {
                throw new RuntimeException(String.format("当前检材状态有误，请选择状态为1的检材"));
            }
            sampleInfo.setStatus(2);
        } else {
            if (sampleInfo.getStatus() != 2) {
                throw new RuntimeException(String.format("当前检材状态有误，请选择状态为2的检材"));
            }
            sampleInfo.setStatus(1);
        }
        return this.updateById(sampleInfo) && testRecordService.updateTestRecordArgument(testRecordArgumentDto.getTestRecordId(), sampleInfo.getId(), TestRecordArgumentType.TEST_RECORD_ARGUMENT_SAMPLE_DATA.getType(), testRecordArgumentDto.getOpCode());
    }

    /**
     * 通过业务ID，查询这个业务下分配给自己的检材
     *
     * @param businessId
     * @param testUser
     * @return
     */
    @Override
    public List<SampleInfo> getSampleInfoListForBusiness(String businessId, String testUser) {
        return baseMapper.getSampleInfoList(businessId, testUser);
    }

    /**
     * 检查样本编号是否重复
     *
     * @param acceptNo
     * @param id
     * @return
     */
    @Override
    public boolean checkRepeatNo(String acceptNo, String id) {
        if (StringUtils.isNotBlank(id)) {
            return true;
        }
        SampleInfo sampleInfo = this.getOne(Wrappers.<SampleInfo>lambdaQuery().eq(SampleInfo::getAcceptNo, acceptNo));
        return sampleInfo == null && StringUtils.isNotBlank(acceptNo) ? true : false;
    }

    @Override
    /**复制其他系统检材内容
     * @param sampleInfo
     * @param material
     * @param type       0:委托 1：任务 2：筛查
     */
    public void copy(SampleInfo sampleInfo, MaterialDto material, Integer type) {
        sampleInfo.setId(IdWorker.get32UUID().toUpperCase());
        sampleInfo.setStatus(0);
        if (StringUtils.isNotBlank(material.getFormName())) {
            sampleInfo.setForm(material.getFormName());
        } else {
            sampleInfo.setForm("/");
        }
        if (StringUtils.isNotBlank(material.getColor())) {
            sampleInfo.setColor(material.getColor());
        } else {
            sampleInfo.setColor("/");
        }
        if (type == 0 || type == 2) {
            sampleInfo.setSampleName(material.getName());
            sampleInfo.setAcceptNo(material.getAcceptNo());
        } else if (type == 1) {
            sampleInfo.setSampleName(material.getSampleName());
            sampleInfo.setAcceptNo(material.getImNo());
        }
        if (material.getQuantity() != null && !(material.getQuantity().compareTo(BigDecimal.ZERO) == 0)) {
            sampleInfo.setQuality(material.getQuantity().doubleValue());
        } else {
            sampleInfo.setQuality(0.0);
        }
        if (material.getSample1RepeatWeigh() != null && !(material.getSample1RepeatWeigh().compareTo(BigDecimal.ZERO) == 0)) {
            sampleInfo.setSampleQuality(material.getSample1RepeatWeigh().doubleValue());
        } else {
            sampleInfo.setSampleQuality(0.0);
        }
        if (StringUtils.isNotBlank(material.getFundUnit())) {
            sampleInfo.setSampleQualityUnit(material.getFundUnit());
        } else {
            sampleInfo.setSampleQualityUnit("/");
        }
        sampleInfo.setSource(0);
        //检材的筛查物列表
        List<DrugLite> candidateDrugs = material.getCandidateDrugs();
        if (candidateDrugs != null && candidateDrugs.size() > 0) {
            ArrayList<TargetObject> targetObjects = new ArrayList<>();
            for (DrugLite candidateDrug : candidateDrugs) {
                TargetObject targetObject = new TargetObject();
                BeanUtils.copyProperties(candidateDrug, targetObject);
                targetObjects.add(targetObject);
            }
            sampleInfo.setTargetObject(targetObjects);
        }
        if (StringUtils.isNotBlank(material.getUnit())) {
            sampleInfo.setUnit(material.getUnit());
        } else {
            sampleInfo.setUnit("/");
        }
        if (type == 0 || type == 2 && StringUtils.isNotBlank(material.getAcceptNo())) {
            String acceptNo = material.getAcceptNo();
            int lastIndexOf = acceptNo.lastIndexOf("-");
            sampleInfo.setOrderNo(Integer.parseInt(acceptNo.substring(lastIndexOf + 1)));
        }
        if (material.getAnalysisOption() != null) {
            sampleInfo.setAnalysisOption(material.getAnalysisOption());
        }
    }

    public String getNameDesStrForEntrust(List<SampleInfo> sampleInfos) {
        //格式
        //对 xx号，xx号检材中的xx1、xx2进行 xx 分析,
        //对1号、2号检材中的海洛因、甲基苯丙胺进行定量分析
        // 1.定性，2.定量 3.定性定量 4.关联性性 5.其他
        String result = "";
        //将检材排序
        Collections.sort(sampleInfos, new Comparator<SampleInfo>() {
            @Override
            public int compare(SampleInfo o1, SampleInfo o2) {
                return o1.getOrderNo() - o2.getOrderNo();
            }
        });
        for (int i = 0; i < sampleInfos.size(); i++) {
            StringBuffer sbMaterialName = new StringBuffer();
            StringBuffer sbDrugDes = new StringBuffer();
            String analysisDes = "";
            StringBuffer sbAnalysisDes = new StringBuffer();
            SampleInfo sampleInfo = sampleInfos.get(i);
            analysisDes = sampleInfo.getOrderNo() + "号";
            sbMaterialName.append(sampleInfo.getOrderNo() + "号").append(",");
            String toJSONString = JSONArray.toJSONString(sampleInfo.getTargetObject());
            List<TargetObject> drugLiteList = JSONArray.parseArray(toJSONString, TargetObject.class);
            drugLiteList.forEach(item -> {
                sbDrugDes.append(item.getName()).append("、");
            });
            sbDrugDes.delete(sbDrugDes.length() - 1, sbDrugDes.length());//删除多余的连接号
            if (sampleInfo.getAnalysisOption() == 1) {
                sbAnalysisDes.append("定性");
            } else if (sampleInfo.getAnalysisOption() == 2) {
                sbAnalysisDes.append("定量");
            } else {
                sbAnalysisDes.append("定性定量");
            }
            String req1 = "对" + analysisDes + "检材中的";
            String req2 = sbDrugDes.toString();
            String req3 = "进行" + sbAnalysisDes.toString() + "分析,";
            if (i == sampleInfos.size() - 1) {
                result = result + req1 + req2 + "进行" + sbAnalysisDes.toString() + "分析。";
            } else {
                result = result + req1 + req2 + req3;
            }
        }
        return result;
    }
}
