package com.lantone.facade.cdss;

import cn.afterturn.easypoi.exception.excel.ExcelImportException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.lantone.client.CdssCoreClient;
import com.lantone.dto.cdss.DictionaryInfoDTO;
import com.lantone.dto.med.IndexBatchDTO;
import com.lantone.dto.med.KllisDetailDTO;
import com.lantone.dto.cdss.LisDetailDTO;
import com.diagbot.dto.RespDTO;
import com.lantone.entity.cdss.AdministrationRouteConfig;
import com.lantone.entity.cdss.AnesthesiaConfig;
import com.lantone.entity.cdss.DeptConfig;
import com.lantone.entity.cdss.DiseaseConfig;
import com.lantone.entity.cdss.DrugConfig;
import com.lantone.entity.cdss.LisConfig;
import com.lantone.entity.cdss.MappingConfig;
import com.lantone.entity.cdss.NurseConfig;
import com.lantone.entity.cdss.OperationConfig;
import com.lantone.entity.cdss.PacsConfig;
import com.lantone.entity.cdss.ScaleConfig;
import com.lantone.entity.cdss.TcmdiseaseConfig;
import com.lantone.entity.cdss.TcmsyndromeConfig;
import com.lantone.entity.cdss.TransfusionConfig;
import com.lantone.entity.cdss.wrapper.AdministrationRouteConfigWrapper;
import com.lantone.entity.cdss.wrapper.AnesthesiaConfigWrapper;
import com.lantone.entity.cdss.wrapper.DeptConfigWrapper;
import com.lantone.entity.cdss.wrapper.DiseaseConfigWrapper;
import com.lantone.entity.cdss.wrapper.DrugConfigWrapper;
import com.lantone.entity.cdss.wrapper.LisConfigWrapper;
import com.lantone.entity.cdss.wrapper.MappingConfigWrapper;
import com.lantone.entity.cdss.wrapper.NurseConfigWrapper;
import com.lantone.entity.cdss.wrapper.OperationConfigWrapper;
import com.lantone.entity.cdss.wrapper.PacsConfigWrapper;
import com.lantone.entity.cdss.wrapper.ScaleConfigWrapper;
import com.lantone.entity.cdss.wrapper.TcmdiseaseConfigWrapper;
import com.lantone.entity.cdss.wrapper.TcmsyndromeConfigWrapper;
import com.lantone.entity.cdss.wrapper.TransfusionConfigWrapper;
import com.lantone.enums.cdss.ConceptTypeEnum;
import com.diagbot.enums.IsDeleteEnum;
import com.lantone.enums.cdss.MatchSourceEnum;
import com.lantone.enums.cdss.StatusEnum;
import com.diagbot.exception.CommonErrorCode;
import com.diagbot.exception.CommonException;
import com.lantone.service.cdss.MappingConfigService;
import com.lantone.service.cdss.impl.MappingConfigServiceImpl;
import com.diagbot.util.BeanUtil;
import com.diagbot.util.DateUtil;
import com.lantone.util.ExcelUtils;
import com.diagbot.util.ListUtil;
import com.diagbot.util.RespDTOUtil;
import com.diagbot.util.StringUtil;
import com.lantone.util.SysUserUtils;
import com.lantone.vo.med.ConceptVO;
import com.lantone.vo.med.FilterVO;
import com.lantone.vo.cdss.IdListVO;
import com.lantone.vo.cdss.IdVO;
import com.lantone.vo.med.IndexByApprovalVO;
import com.lantone.vo.med.KllisDetailVO;
import com.lantone.vo.cdss.MappingConfigPageVO;
import com.lantone.vo.cdss.MappingConfigVO;
import com.lantone.vo.cdss.PrecDataVO;
import com.lantone.vo.cdss.RetrievalVO;
import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author:zhaops
 * @time: 2021/6/9 14:19
 */
@Component
public class MappingConfigFacade extends MappingConfigServiceImpl {

    private static Pattern pattern = Pattern.compile("\\s*|\t|\r|\n");

    @Autowired
    private CdssCoreClient cdssCoreClient;
    @Autowired
    @Qualifier("mappingConfigServiceImpl")
    private MappingConfigService mappingConfigService;
    @Autowired
    private DictionaryFacade dictionaryFacade;

    /**
     * 分页查询
     *
     * @param mappingConfigPageVO
     * @return
     */
    @Override
    public IPage<MappingConfigWrapper> getPage(MappingConfigPageVO mappingConfigPageVO) {
        if (mappingConfigPageVO.getHospitalId() == null) {
            mappingConfigPageVO.setHospitalId(Long.valueOf(SysUserUtils.getCurrentHospitalID()));
        }

        FilterVO filterVO = new FilterVO();
        RespDTO<List<IndexBatchDTO>> respDTO = null;

        //标准词转conceptId
        List<Long> conceptIds = Lists.newLinkedList();
        Map<Long, IndexBatchDTO> conceptMap = new HashMap<>();
        if (StringUtil.isNotBlank(mappingConfigPageVO.getUniqueName())) {
            filterVO.setInputStr(mappingConfigPageVO.getUniqueName());
            filterVO.setStatus(mappingConfigPageVO.getStatus());
            respDTO = cdssCoreClient.filter(filterVO);
            if (RespDTOUtil.respIsOK(respDTO)) {
                if (ListUtil.isNotEmpty(respDTO.data)) {
                    conceptMap = respDTO.data.stream().collect(Collectors.toMap(IndexBatchDTO::getId, v -> v));
                    conceptIds.addAll(respDTO.data
                            .stream()
                            .map(IndexBatchDTO::getId)
                            .distinct()
                            .collect(Collectors.toList()));
                } else {
                    conceptIds.add(-1L);
                }
            }
        }
        mappingConfigPageVO.setConceptIds(conceptIds);

        //药品剂型转 conceptId
        List<Long> formConceptIds = Lists.newLinkedList();
        Map<Long, IndexBatchDTO> formMap = new HashMap<>();
        if (StringUtil.isNotBlank(mappingConfigPageVO.getForm())) {
            filterVO.setInputStr(mappingConfigPageVO.getForm());
            filterVO.setStatus(mappingConfigPageVO.getFormStatus());
            respDTO = cdssCoreClient.filter(filterVO);
            if (RespDTOUtil.respIsOK(respDTO)) {
                if (ListUtil.isNotEmpty(respDTO.data)) {
                    formMap = respDTO.data.stream().collect(Collectors.toMap(IndexBatchDTO::getId, v -> v));
                    formConceptIds.addAll(respDTO.data
                            .stream()
                            .filter(i -> i.getType().equals(ConceptTypeEnum.Form.getKey()))
                            .map(IndexBatchDTO::getId)
                            .distinct()
                            .collect(Collectors.toList()));
                } else {
                    formConceptIds.add(-1L);
                }
            }
        }
        mappingConfigPageVO.setFormConceptIds(formConceptIds);

        //启用禁用过滤
        List<MappingConfig> list = this.list(new QueryWrapper<MappingConfig>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("type", mappingConfigPageVO.getType())
                .eq("hospital_id", mappingConfigPageVO.getHospitalId()));
        if (ListUtil.isNotEmpty(list)) {
            List<Long> dbConceptIds = list.stream()
                    .filter(i -> i.getConceptId() != null)
                    .map(MappingConfig::getConceptId)
                    .distinct()
                    .collect(Collectors.toList());
            List<Long> dbFormConceptIds = list.stream()
                    .filter(i -> i.getFormConceptId() != null)
                    .map(MappingConfig::getFormConceptId)
                    .distinct()
                    .collect(Collectors.toList());
            ConceptVO conceptVO = new ConceptVO();
            conceptVO.setSource(-1);
            conceptVO.setIds(dbConceptIds);
            //conceptVO.setStatus(mappingConfigPageVO.getStatus());
            conceptVO.setStatus(StatusEnum.Disable.getKey());
            RespDTO<List<IndexBatchDTO>> conceptRespDTO = null;
            if (ListUtil.isEmpty(conceptIds)
                    && mappingConfigPageVO.getStatus() != null
                    && ListUtil.isNotEmpty(dbConceptIds)) {
                conceptRespDTO = cdssCoreClient.getConceptNames(conceptVO);
                if (RespDTOUtil.respIsOK(conceptRespDTO)) {
                    conceptIds = conceptRespDTO.data.stream().map(IndexBatchDTO::getId).collect(Collectors.toList());
                }
                if (ListUtil.isNotEmpty(conceptIds)) {
                    if (mappingConfigPageVO.getStatus().equals(StatusEnum.Disable.getKey())) {
                        mappingConfigPageVO.setConceptIds(conceptIds);
                    } else if (mappingConfigPageVO.getStatus().equals(StatusEnum.Enable.getKey())) {
                        mappingConfigPageVO.setNotInConceptIds(conceptIds);
                    }
                } else {
                    //没有启用禁用记录时返回空而不是全量
                    if (mappingConfigPageVO.getStatus().equals(StatusEnum.Disable.getKey())) {
                        mappingConfigPageVO.setConceptIds(Arrays.asList(new Long[] { -1L }));
                    } else if (mappingConfigPageVO.getStatus().equals(StatusEnum.Enable.getKey())) {
                        mappingConfigPageVO.setNotInConceptIds(Arrays.asList(new Long[] { -1L }));
                    }
                }
            }

            if (ListUtil.isEmpty(formConceptIds)
                    && mappingConfigPageVO.getFormStatus() != null
                    && ListUtil.isNotEmpty(dbFormConceptIds)) {
                conceptVO.setIds(dbFormConceptIds);
                conceptVO.setStatus(mappingConfigPageVO.getFormStatus());
                conceptRespDTO = cdssCoreClient.getConceptNames(conceptVO);
                if (RespDTOUtil.respIsOK(conceptRespDTO)) {
                    formConceptIds = conceptRespDTO.data.stream().map(IndexBatchDTO::getId).collect(Collectors.toList());

                }
                if (ListUtil.isNotEmpty(formConceptIds)) {
                    if (mappingConfigPageVO.getFormStatus().equals(StatusEnum.Disable.getKey())) {
                        mappingConfigPageVO.setFormConceptIds(formConceptIds);
                    } else if (mappingConfigPageVO.getFormStatus().equals(StatusEnum.Enable.getKey())) {
                        mappingConfigPageVO.setNotInFormConceptIds(formConceptIds);
                    }
                } else {
                    //没有启用禁用记录时返回空而不是全量
                    if (mappingConfigPageVO.getFormStatus().equals(StatusEnum.Disable.getKey())) {
                        mappingConfigPageVO.setFormConceptIds(Arrays.asList(new Long[] { -1L }));
                    } else if (mappingConfigPageVO.getFormStatus().equals(StatusEnum.Enable.getKey())) {
                        mappingConfigPageVO.setNotInFormConceptIds(Arrays.asList(new Long[] { -1L }));
                    }
                }
            }
        }

        //多条匹配
        if (mappingConfigPageVO.getIsMatch() != null && mappingConfigPageVO.getIsMatch().equals(2)) {
            mappingConfigPageVO.setIsMatch(null);
            mappingConfigPageVO.setIsMultiple(1);
        }

        IPage<MappingConfigWrapper> page = super.getPage(mappingConfigPageVO);
        List<MappingConfigWrapper> records = page.getRecords();

        records = addNames(records, null);
        page.setRecords(records);

        return page;
    }


    /**
     * 导出文件
     *
     * @param response
     * @param type
     * @param extFileName
     * @param mode        1：模板导出、2：关联关系
     */
    public void exportExcel(HttpServletResponse response, List<?> list, Integer type, String extFileName, Integer mode) {
        String fileName = extFileName + ".xls";
        switch (type) {
            case 1:
                fileName = "检验" + fileName;
                if (mode.equals(1)) {
                    List<LisConfig> lisConfigList = BeanUtil.listCopyTo(list, LisConfig.class);
                    ExcelUtils.exportExcel(lisConfigList, null, "sheet1", LisConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<LisConfigWrapper> lisConfigList = BeanUtil.listCopyTo(list, LisConfigWrapper.class);
                    ExcelUtils.exportExcel(lisConfigList, null, "sheet1", LisConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 3:
                fileName = "检查" + fileName;
                if (mode.equals(1)) {
                    List<PacsConfig> pacsConfigList = BeanUtil.listCopyTo(list, PacsConfig.class);
                    ExcelUtils.exportExcel(pacsConfigList, null, "sheet1", PacsConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<PacsConfigWrapper> pacsConfigWrapperList = BeanUtil.listCopyTo(list, PacsConfigWrapper.class);
                    ExcelUtils.exportExcel(pacsConfigWrapperList, null, "sheet1", PacsConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 4:
                fileName = "诊断" + fileName;
                if (mode.equals(1)) {
                    List<DiseaseConfig> diseaseConfigList = BeanUtil.listCopyTo(list, DiseaseConfig.class);
                    ExcelUtils.exportExcel(diseaseConfigList, null, "sheet1", DiseaseConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<DiseaseConfigWrapper> diseaseConfigList = BeanUtil.listCopyTo(list, DiseaseConfigWrapper.class);
                    ExcelUtils.exportExcel(diseaseConfigList, null, "sheet1", DiseaseConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 5:
                fileName = "药品" + fileName;
                if (mode.equals(1)) {
                    List<DrugConfig> drugConfigList = BeanUtil.listCopyTo(list, DrugConfig.class);
                    ExcelUtils.exportExcel(drugConfigList, getForm(), "sheet1", DrugConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<DrugConfigWrapper> drugConfigList = BeanUtil.listCopyTo(list, DrugConfigWrapper.class);
                    ExcelUtils.exportExcel(drugConfigList, getForm(), "sheet1", DrugConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 6:
                fileName = "手术和操作" + fileName;
                if (mode.equals(1)) {
                    List<OperationConfig> operationConfigList = BeanUtil.listCopyTo(list, OperationConfig.class);
                    ExcelUtils.exportExcel(operationConfigList, null, "sheet1", OperationConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<OperationConfigWrapper> operationConfigList = BeanUtil.listCopyTo(list, OperationConfigWrapper.class);
                    ExcelUtils.exportExcel(operationConfigList, null, "sheet1", OperationConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 7:
                fileName = "科室" + fileName;
                if (mode.equals(1)) {
                    List<DeptConfig> deptConfigList = BeanUtil.listCopyTo(list, DeptConfig.class);
                    ExcelUtils.exportExcel(deptConfigList, null, "sheet1", DeptConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<DeptConfigWrapper> deptConfigList = BeanUtil.listCopyTo(list, DeptConfigWrapper.class);
                    ExcelUtils.exportExcel(deptConfigList, null, "sheet1", DeptConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 8:
                fileName = "输血" + fileName;
                if (mode.equals(1)) {
                    List<TransfusionConfig> transfusionConfigList = BeanUtil.listCopyTo(list, TransfusionConfig.class);
                    ExcelUtils.exportExcel(transfusionConfigList, null, "sheet1", TransfusionConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<TransfusionConfigWrapper> transfusionConfigList = BeanUtil.listCopyTo(list, TransfusionConfigWrapper.class);
                    ExcelUtils.exportExcel(transfusionConfigList, null, "sheet1", TransfusionConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 10:
                fileName = "量表" + fileName;
                if (mode.equals(1)) {
                    List<ScaleConfig> scaleConfigList = BeanUtil.listCopyTo(list, ScaleConfig.class);
                    ExcelUtils.exportExcel(scaleConfigList, null, "sheet1", ScaleConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<ScaleConfigWrapper> scaleConfigList = BeanUtil.listCopyTo(list, ScaleConfigWrapper.class);
                    ExcelUtils.exportExcel(scaleConfigList, null, "sheet1", ScaleConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 11:
                fileName = "护理" + fileName;
                if (mode.equals(1)) {
                    List<NurseConfig> nurseConfigList = BeanUtil.listCopyTo(list, NurseConfig.class);
                    ExcelUtils.exportExcel(nurseConfigList, null, "sheet1", NurseConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<NurseConfigWrapper> nurseConfigList = BeanUtil.listCopyTo(list, NurseConfigWrapper.class);
                    ExcelUtils.exportExcel(nurseConfigList, null, "sheet1", NurseConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 12:
                fileName = "中医疾病" + fileName;
                if (mode.equals(1)) {
                    List<TcmdiseaseConfig> tcmdiseaseConfigList = BeanUtil.listCopyTo(list, TcmdiseaseConfig.class);
                    ExcelUtils.exportExcel(tcmdiseaseConfigList, null, "sheet1", TcmdiseaseConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<TcmdiseaseConfigWrapper> tcmdiseaseConfigList = BeanUtil.listCopyTo(list, TcmdiseaseConfigWrapper.class);
                    ExcelUtils.exportExcel(tcmdiseaseConfigList, null, "sheet1", TcmdiseaseConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 13:
                fileName = "中医证候" + fileName;
                if (mode.equals(1)) {
                    List<TcmsyndromeConfig> tcmsyndromeConfigList = BeanUtil.listCopyTo(list, TcmsyndromeConfig.class);
                    ExcelUtils.exportExcel(tcmsyndromeConfigList, null, "sheet1", TcmsyndromeConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<TcmsyndromeConfigWrapper> tcmsyndromeConfigList = BeanUtil.listCopyTo(list, TcmsyndromeConfigWrapper.class);
                    ExcelUtils.exportExcel(tcmsyndromeConfigList, null, "sheet1", TcmsyndromeConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 14:
                fileName = "麻醉" + fileName;
                if (mode.equals(1)) {
                    List<AnesthesiaConfig> anesthesiaConfigList = BeanUtil.listCopyTo(list, AnesthesiaConfig.class);
                    ExcelUtils.exportExcel(anesthesiaConfigList, null, "sheet1", AnesthesiaConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<AnesthesiaConfigWrapper> anesthesiaConfigList = BeanUtil.listCopyTo(list, AnesthesiaConfigWrapper.class);
                    ExcelUtils.exportExcel(anesthesiaConfigList, null, "sheet1", AnesthesiaConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            case 16:
                fileName = "给药途径" + fileName;
                if (mode.equals(1)) {
                    List<AdministrationRouteConfig> administrationRouteConfigList = BeanUtil.listCopyTo(list, AdministrationRouteConfig.class);
                    ExcelUtils.exportExcel(administrationRouteConfigList, null, "sheet1", AdministrationRouteConfig.class, fileName, response, 12.8f);
                } else if (mode.equals(2)) {
                    List<AdministrationRouteConfigWrapper> administrationRouteConfigList = BeanUtil.listCopyTo(list, AdministrationRouteConfigWrapper.class);
                    ExcelUtils.exportExcel(administrationRouteConfigList, null, "sheet1", AdministrationRouteConfigWrapper.class, fileName, response, 12.8f);
                }
                break;
            default:
                break;
        }
    }

    /**
     * 剂型说明
     *
     * @return
     */
    private String getForm() {
        String form = "药品模板——药品剂型填写说明[不填";
        //药品剂型
        List<DictionaryInfoDTO> dicTypeMappingList = dictionaryFacade.getListByGroupType(9);
        if (ListUtil.isNotEmpty(dicTypeMappingList)) {
            String formList = dicTypeMappingList.stream()
                    .filter(i -> StringUtil.isNotBlank(i.getName()))
                    .map(i -> i.getName())
                    .distinct()
                    .collect(Collectors.joining("、"));
            if (StringUtil.isNotBlank(formList)) {
                form += "、" + formList;
            }
        }
        form += "]";
        return form;
    }

    /**
     * 导入模板下载
     *
     * @param response
     */
    public void exportExcelModule(HttpServletResponse response, MappingConfigVO mappingConfigVO) {
        exportExcel(response, new ArrayList<>(), mappingConfigVO.getType(), "导入模板", 1);
    }

    /**
     * 数据导出
     *
     * @param response
     */
    public void exportExcel(HttpServletResponse response, MappingConfigPageVO mappingConfigPageVO) {
        if (mappingConfigPageVO.getHospitalId() == null) {
            mappingConfigPageVO.setHospitalId(Long.valueOf(SysUserUtils.getCurrentHospitalID()));
        }
        mappingConfigPageVO.setHisName("");
        mappingConfigPageVO.setHisDetailName("");
        mappingConfigPageVO.setUniqueName("");
        mappingConfigPageVO.setSize(-1L);

        IPage<MappingConfigWrapper> page = this.getPage(mappingConfigPageVO);

        exportExcel(response, page.getRecords(), mappingConfigPageVO.getType(), "映射", 2);
    }

    /**
     * 导出关联关系
     *
     * @param mappingConfigPageVO
     * @return
     */
    public List<MappingConfigWrapper> exportExcel_remote(MappingConfigPageVO mappingConfigPageVO) {
        if (mappingConfigPageVO.getHospitalId() == null) {
            mappingConfigPageVO.setHospitalId(Long.valueOf(SysUserUtils.getCurrentHospitalID()));
        }
        mappingConfigPageVO.setHisName("");
        mappingConfigPageVO.setHisDetailName("");
        mappingConfigPageVO.setUniqueName("");
        mappingConfigPageVO.setSize(-1L);

        IPage<MappingConfigWrapper> page = this.getPage(mappingConfigPageVO);
        return page.getRecords();
    }

    /**
     * 读取导入数据
     *
     * @param file
     * @param type
     * @param source 1-预匹配，2-导入
     * @return
     */
    public List<MappingConfigWrapper> readImportData(MultipartFile file, Integer type, Integer source) {
        List<MappingConfigWrapper> originList = Lists.newLinkedList();
        try {
            switch (type) {
                case 1:
                    List<LisConfig> lisConfigList = ExcelUtils.importExcel(file, 0, 1, LisConfig.class);
                    originList = BeanUtil.listCopyTo(lisConfigList, MappingConfigWrapper.class);
                    break;
                case 3:
                    List<PacsConfig> pacsConfigList = ExcelUtils.importExcel(file, 0, 1, PacsConfig.class);
                    originList = BeanUtil.listCopyTo(pacsConfigList, MappingConfigWrapper.class);
                    break;
                case 4:
                    List<DiseaseConfig> diseaseConfigList = ExcelUtils.importExcel(file, 0, 1, DiseaseConfig.class);
                    originList = BeanUtil.listCopyTo(diseaseConfigList, MappingConfigWrapper.class);
                    break;
                case 5:
                    List<DrugConfig> drugConfigList = ExcelUtils.importExcel(file, 1, 1, DrugConfig.class);
                    originList = BeanUtil.listCopyTo(drugConfigList, MappingConfigWrapper.class);
                    break;
                case 6:
                    List<OperationConfig> operationConfigList = ExcelUtils.importExcel(file, 0, 1, OperationConfig.class);
                    originList = BeanUtil.listCopyTo(operationConfigList, MappingConfigWrapper.class);
                    break;
                case 7:
                    List<DeptConfig> deptConfigList = ExcelUtils.importExcel(file, 0, 1, DeptConfig.class);
                    originList = BeanUtil.listCopyTo(deptConfigList, MappingConfigWrapper.class);
                    break;
                case 8:
                    List<TransfusionConfig> transfusionConfigList = ExcelUtils.importExcel(file, 0, 1, TransfusionConfig.class);
                    originList = BeanUtil.listCopyTo(transfusionConfigList, MappingConfigWrapper.class);
                    break;
                case 10:
                    List<ScaleConfig> scaleConfigList = ExcelUtils.importExcel(file, 0, 1, ScaleConfig.class);
                    originList = BeanUtil.listCopyTo(scaleConfigList, MappingConfigWrapper.class);
                    break;
                case 11:
                    List<NurseConfig> nurseConfigList = ExcelUtils.importExcel(file, 0, 1, NurseConfig.class);
                    originList = BeanUtil.listCopyTo(nurseConfigList, MappingConfigWrapper.class);
                    break;
                case 12:
                    List<TcmdiseaseConfig> tcmdiseaseConfigList = ExcelUtils.importExcel(file, 0, 1, TcmdiseaseConfig.class);
                    originList = BeanUtil.listCopyTo(tcmdiseaseConfigList, MappingConfigWrapper.class);
                    break;
                case 13:
                    List<TcmsyndromeConfig> tcmsyndromeConfigList = ExcelUtils.importExcel(file, 0, 1, TcmsyndromeConfig.class);
                    originList = BeanUtil.listCopyTo(tcmsyndromeConfigList, MappingConfigWrapper.class);
                    break;
                case 14:
                    List<AnesthesiaConfig> anesthesiaConfigList = ExcelUtils.importExcel(file, 0, 1, AnesthesiaConfig.class);
                    originList = BeanUtil.listCopyTo(anesthesiaConfigList, MappingConfigWrapper.class);
                    break;
                case 16:
                    List<AdministrationRouteConfig> administrationRouteConfigList = ExcelUtils.importExcel(file, 0, 1, AdministrationRouteConfig.class);
                    originList = BeanUtil.listCopyTo(administrationRouteConfigList, MappingConfigWrapper.class);
                    break;
                default:
                    break;
            }
        } catch (ExcelImportException e) {

        } catch (CommonException e) {
            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "校验失败，请使用模板进行数据" + (source == 1 ? "预匹配" : "导入"));
        } catch (Exception e) {

        }
        return originList;
    }

    /**
     * 预匹配导入术语校验
     *
     * @param file
     * @return
     */
    public Boolean dataVerify(MultipartFile file, Integer type) {
        List<MappingConfigWrapper> originList = readImportData(file, type, 1);
        List<MappingConfigWrapper> retList = precDataProcess(originList, type);
        return true;
    }

    /**
     * 导入数据预匹配
     *
     * @param file
     * @param type
     * @param response
     */
    public void precDataMatch(MultipartFile file, Integer type, HttpServletResponse response) {
        List<MappingConfigWrapper> originList = readImportData(file, type, 1);
        List<MappingConfigWrapper> retList = precDataProcess(originList, type);
        exportExcel(response, retList, type, "关联数据（预匹配）", 1);
    }

    /**
     * 远程调用预匹配接口
     *
     * @param file
     * @param type
     * @return
     */
    public List<MappingConfigWrapper> precDataMatch_remote(MultipartFile file, Integer type) {
        List<MappingConfigWrapper> originList = readImportData(file, type, 1);
        List<MappingConfigWrapper> retList = precDataProcess(originList, type);
        return retList;
    }

    /**
     * 预匹配（非文件匹配）
     *
     * @param precDataVO
     * @return
     */
    public List<MappingConfigWrapper> precData(PrecDataVO precDataVO) {
        if (ListUtil.isEmpty(precDataVO.getOriginList())) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "请确认术语列表不为空");
        }
        List<MappingConfigWrapper> originList = BeanUtil.listCopyTo(precDataVO.getOriginList(), MappingConfigWrapper.class);
        List<MappingConfigWrapper> data = precDataProcess(originList, precDataVO.getType());
        return data;
    }

    /**
     * 预匹配数据处理
     *
     * @param originList
     * @return
     */
    public List<MappingConfigWrapper> precDataProcess(List<MappingConfigWrapper> originList, Integer type) {
        List<MappingConfigWrapper> retList = Lists.newLinkedList();
        List<MappingConfigWrapper> dataList = Lists.newLinkedList();

        //数据完整性校验
        List<Integer> emptyNumList = Lists.newLinkedList();
        Integer rowId = 1;
        for (MappingConfigWrapper item : originList) {
            ++rowId;
            //过滤医院术语名称为空的条目
            if (type.equals(ConceptTypeEnum.LisPack.getKey())) {
                if (StringUtil.isBlank(item.getHisName())) {
                    if (StringUtil.isBlank(item.getHisDetailName())) {
                        continue;
                    } else {
                        emptyNumList.add(rowId);
                    }
                }
            } else if (type.equals(ConceptTypeEnum.Disease.getKey())
                    || type.equals(ConceptTypeEnum.Operation.getKey())
                    || type.equals(ConceptTypeEnum.Tcmdisease.getKey())
                    || type.equals(ConceptTypeEnum.Tcmsyndrome.getKey())) {
                if (StringUtil.isBlank(item.getHisName())) {
                    if (StringUtil.isBlank(item.getCode())) {
                        continue;
                    } else {
                        emptyNumList.add(rowId);
                    }
                }
            } else if (type.equals(ConceptTypeEnum.Drug.getKey())) {
                if (StringUtil.isBlank(item.getHisName())) {
                    if (StringUtil.isBlank(item.getApproval())) {
                        continue;
                    } else {
                        emptyNumList.add(rowId);
                    }
                }
            }

            if (StringUtil.isNotBlank(item.getHisName())) {
                item.setHisName(pattern.matcher(item.getHisName()).replaceAll(""));
                if (item.getHisName().length() > 255) {
                    throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "医院术语字符数超出最大数量，请修改后再试");
                }
                if (StringUtil.isNotBlank(item.getHisDetailName())) {
                    item.setHisDetailName(pattern.matcher(item.getHisDetailName()).replaceAll(""));
                    if (item.getHisDetailName().trim().length() > 255) {
                        throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "医院术语字符数超出最大数量，请修改后再试");
                    }
                } else {
                    item.setHisDetailName("");
                }
                if (StringUtil.isNotBlank(item.getCode())) {
                    item.setCode(pattern.matcher(item.getCode()).replaceAll(""));
                } else {
                    item.setCode("");
                }
                if (StringUtil.isNotBlank(item.getApproval())) {
                    item.setApproval(pattern.matcher(item.getApproval()).replaceAll(""));
                } else {
                    item.setApproval("");
                }
            } else {
                continue;
            }
            item.setUniqueName("");
            item.setIsMatch(0);
            item.setSource(null);
            dataList.add(item);
        }

        //医院术语名称不允许为空
        if (ListUtil.isNotEmpty(emptyNumList)) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "预匹配失败，上传文件内行（"
                    + emptyNumList.stream().map(Object::toString)
                    .collect(Collectors.joining("、"))
                    + "）医院术语" + (type.equals(ConceptTypeEnum.LisPack.getKey()) ? "的检验套餐项" : "") + "不可为空。\n");
        }

        if (ListUtil.isEmpty(dataList)) {
            return retList;
        }

        //重复数据去重
        dataList = dataList.stream().distinct().collect(Collectors.toList());
        if (ListUtil.isEmpty(dataList)) {
            return retList;
        }

        //国药准字匹配：药品
        if (type.equals(ConceptTypeEnum.Drug.getKey())) {
            dataList = matchWithApproval(dataList, type);
            dataList = checkStatus(dataList, type);
        }

        //标准词匹配
        dataList = matchWithStandWord(dataList, type);
        dataList = checkStatus(dataList, type);

        //同义词匹配
        dataList = matchWithSynonymsWord(dataList, type);
        dataList = checkStatus(dataList, type);

        //编码匹配：手术、中医疾病、中医证候
        if (type.equals(ConceptTypeEnum.Operation.getKey())
                || type.equals(ConceptTypeEnum.Tcmdisease.getKey())
                || type.equals(ConceptTypeEnum.Tcmsyndrome.getKey())) {
            dataList = matchWithCode(dataList, type);
            dataList = checkStatus(dataList, type);
        }

        //历史匹配
        dataList = matchWithHistory(dataList, type);
        dataList = checkStatus(dataList, type);

        //编码匹配：诊断
        if (type.equals(ConceptTypeEnum.Disease.getKey())) {
            dataList = matchWithCode(dataList, type);
            dataList = checkStatus(dataList, type);
        }

        //药品关联国药准字、标准词、同义词匹配数据增加历史数据剂型
        if (type.equals(ConceptTypeEnum.Drug.getKey())) {
            dataList = addDrugForm(dataList, type);
            dataList = checkStatus(dataList, type);
        }

        retList = BeanUtil.listCopyTo(dataList, MappingConfigWrapper.class);
        for (MappingConfigWrapper item : retList) {
            if (item.getIsMatch() == null) {
                item.setIsMatch(0);
            }
        }

        //添加编码
        retList = addCodes(retList, type, StatusEnum.Enable.getKey());
        retList = retList.stream().distinct().collect(Collectors.toList());
        return retList;
    }

    /**
     * 标准词匹配
     *
     * @param list
     * @param type
     * @return
     */
    public List<MappingConfigWrapper> matchWithStandWord(List<MappingConfigWrapper> list, Integer type) {
        List<MappingConfigWrapper> retList = Lists.newLinkedList();
        if (ListUtil.isEmpty(list) || null == type) {
            return list;
        }
        List<String> nameList = list.stream()
                .filter(i -> StringUtil.isBlank(i.getHisDetailName()))
                .filter(i -> (i.getIsMatch() == null || i.getIsMatch().equals(0)))
                .map(MappingConfigWrapper::getHisName)
                .distinct()
                .collect(Collectors.toList());
        List<String> subNameList = list.stream()
                .filter(i -> StringUtil.isNotBlank(i.getHisDetailName()))
                .filter(i -> (i.getIsMatch() == null || i.getIsMatch().equals(0)))
                .map(MappingConfigWrapper::getHisDetailName)
                .distinct()
                .collect(Collectors.toList());

        ConceptVO conceptVO = new ConceptVO();
        conceptVO.setSource(MatchSourceEnum.StandWord.getKey());
        conceptVO.setStatus(StatusEnum.Enable.getKey());
        conceptVO.setType(type);
        conceptVO.setNames(nameList);
        RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
        RespDTOUtil.respNGDealCover(respDTO, "标准术语校验失败");
        conceptVO.setType(ConceptTypeEnum.Lis.getKey());
        conceptVO.setNames(subNameList);
        RespDTO<List<IndexBatchDTO>> subRespDTO = cdssCoreClient.getConceptNames(conceptVO);
        RespDTOUtil.respNGDealCover(subRespDTO, "标准术语校验失败");
        Map<String, List<IndexBatchDTO>> nameMap = new HashMap<>();
        Map<String, List<IndexBatchDTO>> subNameMap = new HashMap<>();
        if (ListUtil.isNotEmpty(respDTO.data)) {
            nameMap = respDTO.data.stream().collect(Collectors.groupingBy(IndexBatchDTO::getName));
        }
        if (ListUtil.isNotEmpty(subRespDTO.data)) {
            subNameMap = subRespDTO.data.stream().collect(Collectors.groupingBy(IndexBatchDTO::getName));
        }
        for (MappingConfigWrapper item : list) {
            if (item.getIsMatch() != null && item.getIsMatch().equals(1)) {
                retList.add(item);
                continue;
            }
            List<IndexBatchDTO> indexList = Lists.newArrayList();
            if (type.equals(ConceptTypeEnum.LisPack.getKey()) && StringUtil.isNotBlank(item.getHisDetailName())) {
                if (subNameMap.containsKey(item.getHisDetailName())) {
                    indexList = subNameMap.get(item.getHisDetailName());
                }
            } else {
                if (nameMap.containsKey(item.getHisName())) {
                    indexList = nameMap.get(item.getHisName());
                }
            }

            if (ListUtil.isEmpty(indexList)) {
                retList.add(item);
                continue;
            }
            //标准词默认取第一个
            MappingConfigWrapper standardItem = new MappingConfigWrapper();
            BeanUtil.copyProperties(item, standardItem);
            standardItem.setUniqueName(indexList.get(0).getName());
            standardItem.setConceptId(indexList.get(0).getId());
            standardItem.setCode(indexList.get(0).getCode());
            standardItem.setIsMatch(1);
            standardItem.setSource(MatchSourceEnum.StandWord.getKey());
            retList.add(standardItem);
        }
        return retList;
    }

    /**
     * 同义词匹配
     *
     * @param list
     * @param type
     * @return
     */
    public List<MappingConfigWrapper> matchWithSynonymsWord(List<MappingConfigWrapper> list, Integer type) {
        List<MappingConfigWrapper> retList = Lists.newLinkedList();
        if (ListUtil.isEmpty(list) || null == type) {
            return list;
        }
        List<String> synonymsNameList = list.stream()
                .filter(i -> (i.getIsMatch() == null || i.getIsMatch().equals(0))
                        && StringUtil.isBlank(i.getHisDetailName()))
                .map(MappingConfigWrapper::getHisName)
                .distinct()
                .collect(Collectors.toList());
        List<String> synonymsSubNameList = list.stream()
                .filter(i -> (i.getIsMatch() == null || i.getIsMatch().equals(0))
                        && StringUtil.isNotBlank(i.getHisDetailName()))
                .map(MappingConfigWrapper::getHisDetailName)
                .distinct()
                .collect(Collectors.toList());
        ConceptVO conceptVO = new ConceptVO();
        conceptVO.setSource(MatchSourceEnum.SynonymsWord.getKey());
        conceptVO.setStatus(StatusEnum.Enable.getKey());
        conceptVO.setType(type);
        conceptVO.setNames(synonymsNameList);
        RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
        RespDTOUtil.respNGDealCover(respDTO, "标准术语校验失败");
        conceptVO.setType(ConceptTypeEnum.Lis.getKey());
        conceptVO.setNames(synonymsSubNameList);
        RespDTO<List<IndexBatchDTO>> subRespDTO = cdssCoreClient.getConceptNames(conceptVO);
        RespDTOUtil.respNGDealCover(subRespDTO, "标准术语校验失败");
        Map<String, List<IndexBatchDTO>> synonymsNameMap = new HashMap<>();
        Map<String, List<IndexBatchDTO>> synonymsSubNameMap = new HashMap<>();
        if (ListUtil.isNotEmpty(respDTO.data)) {
            synonymsNameMap = respDTO.data.stream().collect(Collectors.groupingBy(IndexBatchDTO::getSynonyms));
        }
        if (ListUtil.isNotEmpty(subRespDTO.data)) {
            synonymsSubNameMap = subRespDTO.data.stream().collect(Collectors.groupingBy(IndexBatchDTO::getSynonyms));
        }
        for (MappingConfigWrapper item : list) {
            if (item.getIsMatch() != null && item.getIsMatch().equals(1)) {
                retList.add(item);
                continue;
            }
            List<IndexBatchDTO> indexList = Lists.newLinkedList();
            if (type.equals(ConceptTypeEnum.LisPack.getKey()) && StringUtil.isNotBlank(item.getHisDetailName())) {
                if (synonymsSubNameMap.containsKey(item.getHisDetailName())) {
                    indexList = synonymsSubNameMap.get(item.getHisDetailName());
                }
            } else {
                if (synonymsNameMap.containsKey(item.getHisName())) {
                    indexList = synonymsNameMap.get(item.getHisName());
                }
            }

            if (ListUtil.isEmpty(indexList)) {
                retList.add(item);
                continue;
            }

            for (IndexBatchDTO index : indexList) {
                MappingConfigWrapper synonymsItem = new MappingConfigWrapper();
                BeanUtils.copyProperties(item, synonymsItem);
                synonymsItem.setUniqueName(index.getName());
                synonymsItem.setConceptId(index.getId());
                synonymsItem.setCode(index.getCode());
                synonymsItem.setIsMatch(1);
                synonymsItem.setSource(MatchSourceEnum.SynonymsWord.getKey());
                retList.add(synonymsItem);
            }
        }
        return retList;
    }

    /**
     * 编码匹配
     *
     * @param list
     * @param type
     * @return
     */
    public List<MappingConfigWrapper> matchWithCode(List<MappingConfigWrapper> list, Integer type) {
        List<MappingConfigWrapper> retList = Lists.newLinkedList();
        if (ListUtil.isEmpty(list) || null == type) {
            return list;
        }
        if (!(type.equals(ConceptTypeEnum.Disease.getKey())
                || type.equals(ConceptTypeEnum.Operation.getKey())
                || type.equals(ConceptTypeEnum.Tcmdisease.getKey())
                || type.equals(ConceptTypeEnum.Tcmsyndrome.getKey()))) {
            return list;
        }
        List<String> codes = list.stream()
                .filter(i -> (i.getIsMatch() == null || i.getIsMatch().equals(0))
                        && StringUtil.isNotBlank(i.getCode()))
                .map(MappingConfigWrapper::getCode)
                .distinct()
                .collect(Collectors.toList());
        if (ListUtil.isEmpty(codes)) {
            retList = BeanUtil.listCopyTo(list, MappingConfigWrapper.class);
        } else {
            ConceptVO conceptVO = new ConceptVO();
            conceptVO.setSource(MatchSourceEnum.Code.getKey());
            conceptVO.setStatus(StatusEnum.Enable.getKey());
            conceptVO.setType(type);
            conceptVO.setNames(codes);
            RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
            RespDTOUtil.respNGDealCover(respDTO, "标准术语校验失败");
            Map<String, List<IndexBatchDTO>> codeMap = new HashMap<>();
            if (ListUtil.isNotEmpty(respDTO.data)) {
                codeMap = respDTO.data.stream().collect(Collectors.groupingBy(IndexBatchDTO::getCode));
            }
            for (MappingConfigWrapper item : list) {
                if (item.getIsMatch() != null && item.getIsMatch().equals(1)) {
                    retList.add(item);
                    continue;
                }
                if (StringUtil.isNotBlank(item.getCode()) && codeMap.containsKey(item.getCode())) {
                    List<IndexBatchDTO> indexList = codeMap.get(item.getCode());
                    for (IndexBatchDTO index : indexList) {
                        MappingConfigWrapper codeItem = new MappingConfigWrapper();
                        BeanUtils.copyProperties(item, codeItem);
                        codeItem.setUniqueName(index.getName());
                        codeItem.setConceptId(index.getId());
                        codeItem.setCode(index.getCode());
                        codeItem.setIsMatch(1);
                        codeItem.setSource(MatchSourceEnum.Code.getKey());
                        retList.add(codeItem);
                    }
                } else {
                    retList.add(item);
                    continue;
                }
            }
        }
        return retList;
    }

    /**
     * 历史数据匹配（预匹配）
     *
     * @param list
     * @param type
     * @return
     */
    public List<MappingConfigWrapper> matchWithHistory(List<MappingConfigWrapper> list, Integer type) {
        List<MappingConfigWrapper> retList = Lists.newLinkedList();
        if (ListUtil.isEmpty(list) || null == type) {
            return list;
        }
        List<String> hisNames = list.stream()
                .filter(i -> i.getIsMatch() == null || i.getIsMatch().equals(0))
                .map(MappingConfigWrapper::getHisName)
                .distinct()
                .collect(Collectors.toList());
        if (ListUtil.isNotEmpty(hisNames)) {
            Map<String, Map<String, Map<String, List<String>>>> configMap = groupByHisNameWithName(hisNames, type, null, StatusEnum.Enable.getKey());

            for (MappingConfigWrapper item : list) {
                if (item.getIsMatch() != null && item.getIsMatch().equals(1)) {
                    retList.add(item);
                    continue;
                }
                if (configMap.containsKey(item.getHisName())) {
                    Map<String, Map<String, List<String>>> subMap = configMap.get(item.getHisName());
                    if (subMap != null && subMap.size() > 0) {
                        Map<String, List<String>> thirdMap = subMap.get(item.getHisDetailName());
                        if (thirdMap == null || thirdMap.size() == 0) {
                            retList.add(item);
                            continue;
                        }
                        for (Map.Entry<String, List<String>> thirdEntry : thirdMap.entrySet()) {
                            MappingConfigWrapper historyItem = new MappingConfigWrapper();
                            BeanUtils.copyProperties(item, historyItem);
                            historyItem.setUniqueName(thirdEntry.getKey());
                            historyItem.setIsMatch(1);
                            historyItem.setSource(MatchSourceEnum.History.getKey());
                            if (type.equals(ConceptTypeEnum.Drug.getKey())) {
                                List<String> forms = thirdEntry.getValue();
                                if (ListUtil.isEmpty(forms)) {
                                    retList.add(historyItem);
                                } else {
                                    for (String form : forms) {
                                        MappingConfigWrapper formItem = new MappingConfigWrapper();
                                        BeanUtil.copyProperties(historyItem, formItem);
                                        formItem.setForm(form);
                                        retList.add(formItem);
                                    }
                                }
                            } else {
                                retList.add(historyItem);
                            }
                        }
                    }
                } else {
                    retList.add(item);
                }
            }
        } else {
            retList = BeanUtil.listCopyTo(list, MappingConfigWrapper.class);
        }
        return retList;
    }

    /**
     * 国药准字匹配（药品）
     *
     * @param list
     * @param type
     * @return
     */
    public List<MappingConfigWrapper> matchWithApproval(List<MappingConfigWrapper> list, Integer type) {
        List<MappingConfigWrapper> retList = Lists.newLinkedList();
        if (ListUtil.isEmpty(list) || null == type) {
            return list;
        }
        IndexByApprovalVO indexByApprovalVO = new IndexByApprovalVO();
        indexByApprovalVO.setApprovalList(list.stream()
                .filter(i -> StringUtil.isNotBlank(i.getApproval()))
                .map(MappingConfigWrapper::getApproval)
                .distinct()
                .collect(Collectors.toList()));

        if(ListUtil.isEmpty(indexByApprovalVO.getApprovalList())){
            return list;
        }

        RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.indexByApproval(indexByApprovalVO);
        RespDTOUtil.respNGDealCover(respDTO, "标准术语校验失败");

        List<IndexBatchDTO> indexBatchDTOList = respDTO.data;

        //国药准字取字母+数字编码
        String regex = "[a-zA-Z]+\\d{8}";
        Pattern pattern = Pattern.compile(regex);

        Map<String, List<IndexBatchDTO>> approvalMap = new HashMap<>();
        approvalMap = indexBatchDTOList.stream().collect(Collectors.groupingBy(IndexBatchDTO::getApproval));
        /*for (IndexBatchDTO indexDTO : indexBatchDTOList) {
            Matcher matcher = pattern.matcher(indexDTO.getApproval());
            if (matcher.find()) {
                approvalMap.put(matcher.group(), indexDTO);
            }
        }*/

        for (MappingConfigWrapper item : list) {
            if (StringUtil.isBlank(item.getApproval())) {
                item.setIsMatch(0);
                retList.add(item);
                continue;
            }
            Matcher matcher = pattern.matcher(item.getApproval());
           /* String approval = "";
            if (matcher.find()) {
                approval = matcher.group();
            }*/
            if (StringUtils.isNotBlank(item.getApproval()) && approvalMap.containsKey(item.getApproval())) {
                List<IndexBatchDTO> dtoList = approvalMap.get(item.getApproval());
                for (IndexBatchDTO indexBatchDTO : dtoList) {
                    MappingConfigWrapper addItem = new MappingConfigWrapper();
                    BeanUtils.copyProperties(item, addItem);
                    addItem.setUniqueName(indexBatchDTO.getName());
                    addItem.setConceptId(indexBatchDTO.getId());
                    if (indexBatchDTO.getFormConceptId() != null) {
                        addItem.setForm(indexBatchDTO.getForm());
                        addItem.setFormConceptId(indexBatchDTO.getFormConceptId());
                    }
                    addItem.setSource(MatchSourceEnum.Approval.getKey());
                    addItem.setIsMatch(1);
                    retList.add(addItem);
                }
            } else {
                item.setIsMatch(0);
                retList.add(item);
            }
        }
        return retList;
    }

    /**
     * 药品关联标准词、同义词匹配数据增加历史数据剂型
     *
     * @param list
     * @param type
     * @return
     */
    public List<MappingConfigWrapper> addDrugForm(List<MappingConfigWrapper> list, Integer type) {
        List<MappingConfigWrapper> retList = Lists.newLinkedList();
        if (ListUtil.isEmpty(list) || null == type) {
            return list;
        }
        if (!type.equals(ConceptTypeEnum.Drug.getKey())) {
            return list;
        }
        List<String> hisDrugNames = list.stream()
                .filter(i -> i.getIsMatch() != null
                        && i.getIsMatch().equals(1)
                        && i.getSource() != null
                        && (i.getSource().equals(MatchSourceEnum.StandWord.getKey())
                        || i.getSource().equals(MatchSourceEnum.Approval.getKey())
                        || i.getSource().equals(MatchSourceEnum.SynonymsWord.getKey())))
                .map(MappingConfigWrapper::getHisName)
                .distinct()
                .collect(Collectors.toList());
        if (ListUtil.isNotEmpty(hisDrugNames)) {
            Map<String, Map<String, Map<String, List<String>>>> configMap
                    = groupByHisNameWithName(hisDrugNames, type, null, StatusEnum.Enable.getKey());
            for (MappingConfigWrapper item : list) {
                if (item.getIsMatch() != null && item.getIsMatch().equals(1)
                        && item.getSource() != null
                        && (item.getSource().equals(MatchSourceEnum.Approval.getKey())
                        || item.getSource().equals(MatchSourceEnum.StandWord.getKey())
                        || item.getSource().equals(MatchSourceEnum.SynonymsWord.getKey()))) {
                    if (item.getFormConceptId() != null && StringUtils.isNotBlank(item.getForm())) {
                        retList.add(item);
                        continue;
                    }
                    if (configMap.containsKey(item.getHisName())) {
                        Map<String, Map<String, List<String>>> subMap
                                = configMap.get(item.getHisName());
                        if (subMap != null && subMap.size() > 0) {
                            Map<String, List<String>> thirdMap = subMap.get(item.getHisDetailName());
                            if (thirdMap == null || thirdMap.size() == 0) {
                                retList.add(item);
                                continue;
                            }
                            List<String> forms = thirdMap.get(item.getUniqueName());
                            if (ListUtil.isEmpty(forms)) {
                                retList.add(item);
                            } else {
                                for (String form : forms) {
                                    MappingConfigWrapper formItem = new MappingConfigWrapper();
                                    BeanUtil.copyProperties(item, formItem);
                                    formItem.setForm(form);
                                    retList.add(formItem);
                                }
                            }
                        }
                    } else {
                        retList.add(item);
                    }
                } else {
                    retList.add(item);
                }
            }
        } else {
            retList = BeanUtil.listCopyTo(list, MappingConfigWrapper.class);
        }

        return retList;
    }

    /**
     * 启用禁用校验
     *
     * @param list
     * @param type
     * @return
     */
    public List<MappingConfigWrapper> checkStatus(List<MappingConfigWrapper> list, Integer type) {
        //校验标准词是否启用
        ConceptVO conceptVO = new ConceptVO();
        conceptVO.setSource(MatchSourceEnum.StandWord.getKey());
        conceptVO.setStatus(StatusEnum.Enable.getKey());
        List<String> uniqueNames = list.stream()
                .filter(i -> StringUtil.isBlank(i.getHisDetailName())
                        && StringUtil.isNotBlank(i.getUniqueName()))
                .map(MappingConfigWrapper::getUniqueName)
                .distinct()
                .collect(Collectors.toList());
        conceptVO.setType(type);
        conceptVO.setNames(uniqueNames);
        RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
        RespDTO<List<IndexBatchDTO>> listRespDTO = null;
        if (type.equals(ConceptTypeEnum.LisPack.getKey())) {
            List<String> lisUniqueNames = list.stream()
                    .filter(i -> StringUtil.isNotBlank(i.getHisDetailName())
                            && StringUtil.isNotBlank(i.getUniqueName()))
                    .map(MappingConfigWrapper::getUniqueName)
                    .distinct()
                    .collect(Collectors.toList());
            conceptVO.setType(ConceptTypeEnum.Lis.getKey());
            conceptVO.setNames(lisUniqueNames);
            listRespDTO = cdssCoreClient.getConceptNames(conceptVO);
        }

        Map<String, IndexBatchDTO> dtoMap = new HashMap<>();
        Map<String, IndexBatchDTO> lisDtoMap = new HashMap<>();
        if (RespDTOUtil.respIsOK(respDTO)) {
            dtoMap = respDTO.data.stream().collect(Collectors.toMap(IndexBatchDTO::getName, v -> v));
        }
        if (RespDTOUtil.respIsOK(listRespDTO)) {
            lisDtoMap = listRespDTO.data.stream().collect(Collectors.toMap(IndexBatchDTO::getName, v -> v));
        }
        for (MappingConfigWrapper item : list) {
            if (StringUtil.isNotBlank(item.getUniqueName())) {
                if (StringUtil.isNotBlank(item.getHisDetailName())) {
                    if (lisDtoMap == null || lisDtoMap.size() == 0) {
                        continue;
                    }
                    if (lisDtoMap.containsKey(item.getUniqueName())) {
                        item.setConceptId(lisDtoMap.get(item.getUniqueName()).getId());
                        item.setStatus(StatusEnum.Enable.getKey());
                    } else {
                        item.setUniqueName("");
                        item.setConceptId(null);
                        item.setStatus(StatusEnum.Disable.getKey());
                        item.setIsMatch(0);
                        item.setRemark("术语校验失败；");
                    }
                } else {
                    if (dtoMap == null || dtoMap.size() == 0) {
                        continue;
                    }
                    if (dtoMap.containsKey(item.getUniqueName())) {
                        item.setConceptId(dtoMap.get(item.getUniqueName()).getId());
                        item.setStatus(StatusEnum.Enable.getKey());
                    } else {
                        item.setUniqueName("");
                        item.setConceptId(null);
                        item.setStatus(StatusEnum.Disable.getKey());
                        item.setIsMatch(0);
                        item.setRemark("术语校验失败；");
                    }
                }
            } else {
                continue;
            }
        }

        //校验剂型是否启用
        if (type.equals(ConceptTypeEnum.Drug.getKey())) {
            List<String> forms = list.stream()
                    .filter(i -> StringUtil.isNotBlank(i.getForm()))
                    .map(MappingConfigWrapper::getForm)
                    .distinct()
                    .collect(Collectors.toList());

            conceptVO.setType(ConceptTypeEnum.Form.getKey());
            conceptVO.setNames(forms);
            conceptVO.setStatus(StatusEnum.Enable.getKey());
            respDTO = cdssCoreClient.getConceptNames(conceptVO);
            if (RespDTOUtil.respIsOK(respDTO)) {
                Map<String, IndexBatchDTO> formDtoMap = respDTO.data.stream().collect(Collectors.toMap(IndexBatchDTO::getName, v -> v));
                for (MappingConfigWrapper item : list) {
                    if (item.getIsMatch() != null && item.getIsMatch().equals(0)) {
                        continue;
                    }
                    if (StringUtil.isNotBlank(item.getForm())) {
                        if (formDtoMap.containsKey(item.getForm())) {
                            item.setFormConceptId(formDtoMap.get(item.getForm()).getId());
                            item.setFormStatus(StatusEnum.Enable.getKey());
                        } else {
                            item.setForm("");
                            item.setFormConceptId(null);
                            item.setFormStatus(StatusEnum.Disable.getKey());
                            item.setRemark(item.getRemark() + "剂型校验失败；");
                        }
                    }
                }
            }
        }
        return list;
    }

    /**
     * 数据导入
     *
     * @param file
     * @param hospitalId
     * @param type
     */
    public void importExcel(HttpServletResponse response, MultipartFile file, Long hospitalId, Integer type, String userId) {
        if (hospitalId == null) {
            hospitalId = Long.valueOf(SysUserUtils.getCurrentHospitalID());
        }
        if (StringUtil.isBlank(userId)) {
            userId = SysUserUtils.getCurrentPrincipleID();
        }
        if (StringUtil.isBlank(userId)) {
            userId = "0";
        }
        List<MappingConfigWrapper> originList = readImportData(file, type, 2);
        if (ListUtil.isEmpty(originList)) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "校验失败，导入数据不能为空");
        }
        List<MappingConfigWrapper> data = importDataProcess(originList, hospitalId, type, userId);
        if (ListUtil.isNotEmpty(data)) {
            exportExcel(response, data, type, "标准词校验错误（含非标和禁用）", 1);
        }
    }

    /**
     * 数据导入
     *
     * @param file
     * @param hospitalId
     * @param type
     */
    public List<MappingConfigWrapper> importExcel_remote(HttpServletResponse response, MultipartFile file, Long hospitalId, Integer type, String userId) {
        if (hospitalId == null) {
            hospitalId = Long.valueOf(SysUserUtils.getCurrentHospitalID());
        }
        if (StringUtil.isBlank(userId)) {
            userId = SysUserUtils.getCurrentPrincipleID();
        }
        if (StringUtil.isBlank(userId)) {
            userId = "0";
        }
        List<MappingConfigWrapper> originList = readImportData(file, type, 2);
        if (ListUtil.isEmpty(originList)) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "校验失败，导入数据不能为空");
        }
        List<MappingConfigWrapper> data = importDataProcess(originList, hospitalId, type, userId);
        return data;
    }

    /**
     * 数据导入
     *
     * @param file
     * @param hospitalId
     * @param type
     */
    public Boolean importExcelDataVerify(MultipartFile file, Long hospitalId, Integer type, String userId) {
        if (hospitalId == null) {
            hospitalId = Long.valueOf(SysUserUtils.getCurrentHospitalID());
        }
        if (StringUtil.isBlank(userId)) {
            userId = SysUserUtils.getCurrentPrincipleID();
        }
        if (StringUtil.isBlank(userId)) {
            userId = "0";
        }
        List<MappingConfigWrapper> originList = readImportData(file, type, 2);
        if (ListUtil.isEmpty(originList)) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "校验失败，导入数据不能为空");
        }
        Boolean data = importDataVerify(originList, hospitalId, type, userId);
        return data;
    }

    /**
     * 导入数据校验
     *
     * @param originList
     * @param hospitalId
     * @param type
     * @param userId
     * @return
     */
    public Boolean importDataVerify(List<MappingConfigWrapper> originList, Long hospitalId, Integer type, String userId) {
        //过滤空数据，保留重复数据，方便计行
        //去除空格、回车、换行符、制表符
        originList = originList.stream()
                .filter(MappingConfigWrapper::nonNull)
                .collect(Collectors.toList());
        if (ListUtil.isEmpty(originList)) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "校验失败，导入数据不能为空");
        }
        List<Integer> emptyNumList = Lists.newLinkedList();
        Integer rowId = 1;
        for (MappingConfigWrapper item : originList) {
            if (StringUtil.isBlank(item.getHisName())) {
                if (type.equals(ConceptTypeEnum.Drug.getKey())) {
                    emptyNumList.add(rowId + 2);
                } else {
                    emptyNumList.add(rowId + 1);
                }
            } else {
                item.setHisName(pattern.matcher(item.getHisName()).replaceAll(""));
            }
            if (StringUtil.isNotBlank(item.getHisCode())) {
                item.setHisCode(pattern.matcher(item.getHisCode()).replaceAll(""));
            } else {
                item.setHisCode("");
            }
            if (StringUtil.isNotBlank(item.getHisDetailName())) {
                item.setHisDetailName(pattern.matcher(item.getHisDetailName()).replaceAll(""));
            } else {
                item.setHisDetailName("");
            }
            if (StringUtil.isNotBlank(item.getUniqueName())) {
                item.setUniqueName(pattern.matcher(item.getUniqueName()).replaceAll(""));
                item.setIsMatch(1);
            } else {
                item.setUniqueName("");
                item.setIsMatch(0);
            }
            if (StringUtil.isNotBlank(item.getForm())) {
                item.setForm(pattern.matcher(item.getForm()).replaceAll(""));
            } else {
                item.setForm("");
            }
            if (StringUtil.isNotBlank(item.getCode())) {
                item.setCode(pattern.matcher(item.getCode()).replaceAll(""));
            } else {
                item.setCode("");
            }
            rowId++;
        }

        //医院术语名称不允许为空
        if (ListUtil.isNotEmpty(emptyNumList)) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "以下行数（不计入空行）医院术语为空："
                    + emptyNumList.stream().map(Object::toString)
                    .collect(Collectors.joining("、"))
                    + "。导入取消，请修改后再试。\n");
        }

        //标准术语校验
        List<Integer> errorNumList = Lists.newLinkedList();
        rowId = 1;
        ConceptVO conceptVO = new ConceptVO();
        conceptVO.setSource(MatchSourceEnum.StandWord.getKey());
        if (type.equals(ConceptTypeEnum.LisPack.getKey())) {
            conceptVO.setType(ConceptTypeEnum.LisPack.getKey());
            conceptVO.setNames(originList.stream()
                    .filter(i -> StringUtil.isBlank(i.getHisDetailName())
                            && StringUtil.isNotBlank(i.getUniqueName()))
                    .map(MappingConfigWrapper::getUniqueName)
                    .distinct()
                    .collect(Collectors.toList()));
            RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
            RespDTOUtil.respNGDealCover(respDTO, "标准术语校验失败");
            Map<String, List<Long>> packMap = respDTO.data.stream()
                    .collect(Collectors.groupingBy(IndexBatchDTO::getName,
                            Collectors.mapping(IndexBatchDTO::getId, Collectors.toList())));
            conceptVO.setType(ConceptTypeEnum.Lis.getKey());
            conceptVO.setNames(originList.stream()
                    .filter(i -> StringUtil.isNotBlank(i.getHisDetailName())
                            && StringUtil.isNotBlank(i.getUniqueName()))
                    .map(MappingConfigWrapper::getUniqueName)
                    .distinct()
                    .collect(Collectors.toList()));
            respDTO = cdssCoreClient.getConceptNames(conceptVO);
            RespDTOUtil.respNGDealCover(respDTO, "标准术语校验失败");
            Map<String, List<Long>> lisMap = respDTO.data.stream()
                    .collect(Collectors.groupingBy(IndexBatchDTO::getName,
                            Collectors.mapping(IndexBatchDTO::getId, Collectors.toList())));

            for (MappingConfigWrapper item : originList) {
                if (StringUtil.isBlank(item.getUniqueName())) {
                    continue;
                }
                if (StringUtil.isBlank(item.getHisDetailName())) {
                    if (packMap.containsKey(item.getUniqueName())) {
                    } else {
                        errorNumList.add(rowId + 1);
                    }
                } else {
                    if (lisMap.containsKey(item.getUniqueName())) {
                    } else {
                        errorNumList.add(rowId + 1);
                    }
                }
                rowId++;
            }
        } else {
            conceptVO.setType(type);
            conceptVO.setNames(originList.stream()
                    .filter(i -> StringUtil.isNotBlank(i.getUniqueName()))
                    .map(MappingConfigWrapper::getUniqueName)
                    .distinct()
                    .collect(Collectors.toList()));
            RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
            if (RespDTOUtil.respIsOK(respDTO)) {
                Map<String, List<Long>> map = respDTO.data.stream()
                        .collect(Collectors.groupingBy(IndexBatchDTO::getName,
                                Collectors.mapping(IndexBatchDTO::getId, Collectors.toList())));
                for (MappingConfigWrapper item : originList) {
                    if (StringUtil.isBlank(item.getUniqueName())) {
                        continue;
                    }
                    if (map.containsKey(item.getUniqueName())) {
                    } else {
                        if (type.equals(ConceptTypeEnum.Drug.getKey())) {
                            errorNumList.add(rowId + 2);
                        } else {
                            errorNumList.add(rowId + 1);
                        }
                    }
                    rowId++;
                }
            }
        }
        if (ListUtil.isNotEmpty(errorNumList)) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS, "以下行数（不计入空行）标准术语校验失败："
                    + errorNumList.stream().map(Object::toString)
                    .collect(Collectors.joining("、"))
                    + "。继续导入则错误术语将会丢失，请确认是否继续导入。\n");
        }
        return true;
    }

    /**
     * 导入数据处理
     *
     * @param originList
     * @param hospitalId
     * @param type
     */
    public List<MappingConfigWrapper> importDataProcess(List<MappingConfigWrapper> originList, Long hospitalId, Integer type, String userId) {
        List<MappingConfigWrapper> tempList = Lists.newLinkedList();
        List<MappingConfigWrapper> errorList = Lists.newLinkedList();

        Date now = DateUtil.now();

        //过滤空数据，保留重复数据，方便计行
        //去除空格、回车、换行符、制表符
        originList = originList.stream()
                .filter(MappingConfigWrapper::nonNull)
                .collect(Collectors.toList());
        if (ListUtil.isEmpty(originList)) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "校验失败，导入数据不能为空");
        }
        List<Integer> emptyNumList = Lists.newLinkedList();
        Integer rowId = 1;
        for (MappingConfigWrapper item : originList) {
            if (StringUtil.isBlank(item.getHisName())) {
                if (type.equals(ConceptTypeEnum.Drug.getKey())) {
                    emptyNumList.add(rowId + 2);
                } else {
                    emptyNumList.add(rowId + 1);
                }
            } else {
                item.setHisName(pattern.matcher(item.getHisName()).replaceAll(""));
                if (item.getHisName().length() > 255) {
                    throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "医院术语字符数超出最大数量，请修改后再试");
                }
            }
            if (StringUtil.isNotBlank(item.getHisCode())) {
                item.setHisCode(pattern.matcher(item.getHisCode()).replaceAll(""));
            } else {
                item.setHisCode("");
            }
            if (StringUtil.isNotBlank(item.getHisDetailName())) {
                item.setHisDetailName(pattern.matcher(item.getHisDetailName()).replaceAll(""));
                if (item.getHisDetailName().length() > 255) {
                    throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "医院术语字符数超出最大数量，请修改后再试");
                }
            } else {
                item.setHisDetailName("");
            }
            if (StringUtil.isNotBlank(item.getUniqueName())) {
                item.setUniqueName(pattern.matcher(item.getUniqueName()).replaceAll(""));
                item.setIsMatch(1);
            } else {
                item.setUniqueName("");
                item.setIsMatch(0);
                if (StringUtil.isNotBlank(item.getForm())) {
                    item.setForm("");
                }
            }
            if (StringUtil.isNotBlank(item.getForm())) {
                item.setForm(pattern.matcher(item.getForm()).replaceAll(""));
            } else {
                item.setForm("");
            }
            if (StringUtil.isNotBlank(item.getCode())) {
                item.setCode(pattern.matcher(item.getCode()).replaceAll(""));
            } else {
                item.setCode("");
            }
            rowId++;
        }

        //医院术语名称不允许为空
        if (ListUtil.isNotEmpty(emptyNumList)) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "以下行数（不计入空行）医院术语为空："
                    + emptyNumList.stream().map(Object::toString)
                    .collect(Collectors.joining("、"))
                    + "。导入取消，请修改后再试。\n");
        }

        originList = originList.stream().distinct().collect(Collectors.toList());
        //原始数据为空
        if (ListUtil.isEmpty(originList)) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "校验失败，导入数据不能为空");
        }

        //标准术语校验
        ConceptVO conceptVO = new ConceptVO();
        conceptVO.setSource(MatchSourceEnum.StandWord.getKey());
        conceptVO.setStatus(StatusEnum.Enable.getKey());
        if (type.equals(ConceptTypeEnum.LisPack.getKey())) {
            conceptVO.setType(ConceptTypeEnum.LisPack.getKey());
            conceptVO.setNames(originList.stream()
                    .filter(i -> StringUtil.isBlank(i.getHisDetailName())
                            && StringUtil.isNotBlank(i.getUniqueName()))
                    .map(MappingConfigWrapper::getUniqueName)
                    .distinct()
                    .collect(Collectors.toList()));
            RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
            RespDTOUtil.respNGDealCover(respDTO, "标准术语校验失败");
            Map<String, List<Long>> packMap = new HashMap<>();
            packMap = respDTO.data.stream()
                    .collect(Collectors.groupingBy(IndexBatchDTO::getName,
                            Collectors.mapping(IndexBatchDTO::getId, Collectors.toList())));

            conceptVO.setType(ConceptTypeEnum.Lis.getKey());
            conceptVO.setNames(originList.stream()
                    .filter(i -> StringUtil.isNotBlank(i.getHisDetailName())
                            && StringUtil.isNotBlank(i.getUniqueName()))
                    .map(MappingConfigWrapper::getUniqueName)
                    .distinct()
                    .collect(Collectors.toList()));
            Map<String, List<Long>> lisMap = new HashMap<>();
            if (ListUtil.isNotEmpty(conceptVO.getNames())) {
                respDTO = cdssCoreClient.getConceptNames(conceptVO);
                RespDTOUtil.respNGDealCover(respDTO, "标准术语校验失败");
                lisMap = respDTO.data.stream()
                        .collect(Collectors.groupingBy(IndexBatchDTO::getName,
                                Collectors.mapping(IndexBatchDTO::getId, Collectors.toList())));
            }

            for (MappingConfigWrapper item : originList) {
                if (StringUtil.isBlank(item.getUniqueName())) {
                    continue;
                }
                if (StringUtil.isBlank(item.getHisDetailName())) {
                    if (packMap.containsKey(item.getUniqueName())) {
                        item.setConceptId(packMap.get(item.getUniqueName()).get(0));
                        item.setIsMatch(1);
                    } else {
                        item.setIsMatch(0);
                        MappingConfigWrapper errorItem = new MappingConfigWrapper();
                        BeanUtils.copyProperties(item, errorItem);
                        errorItem.setIsMatch(null);
                        errorList.add(errorItem);
                        item.setUniqueName("");
                    }
                } else {
                    if (lisMap.containsKey(item.getUniqueName())) {
                        item.setConceptId(lisMap.get(item.getUniqueName()).get(0));
                        item.setIsMatch(1);
                    } else {
                        item.setIsMatch(0);
                        MappingConfigWrapper errorItem = new MappingConfigWrapper();
                        BeanUtils.copyProperties(item, errorItem);
                        errorItem.setIsMatch(null);
                        errorList.add(errorItem);
                        item.setUniqueName("");
                    }
                }
            }
        } else {
            conceptVO.setType(type);
            conceptVO.setNames(originList.stream()
                    .filter(i -> StringUtil.isNotBlank(i.getUniqueName()))
                    .map(MappingConfigWrapper::getUniqueName)
                    .distinct()
                    .collect(Collectors.toList()));
            RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
            if (RespDTOUtil.respIsOK(respDTO)) {
                Map<String, List<Long>> map = respDTO.data.stream()
                        .collect(Collectors.groupingBy(IndexBatchDTO::getName,
                                Collectors.mapping(IndexBatchDTO::getId, Collectors.toList())));
                for (MappingConfigWrapper item : originList) {
                    if (StringUtil.isBlank(item.getUniqueName())) {
                        continue;
                    }
                    if (map.containsKey(item.getUniqueName())) {
                        item.setConceptId(map.get(item.getUniqueName()).get(0));
                        item.setIsMatch(1);
                    } else {
                        item.setIsMatch(0);
                        MappingConfigWrapper errorItem = new MappingConfigWrapper();
                        BeanUtils.copyProperties(item, errorItem);
                        errorItem.setIsMatch(null);
                        errorList.add(errorItem);
                        item.setUniqueName("");
                        //标准词校验不通过，剂型置空
                        if (StringUtil.isNotBlank(item.getForm())) {
                            item.setForm("");
                        }
                    }
                }
            }
        }

        //剂型校验
        if (type.equals(ConceptTypeEnum.Drug.getKey())) {
            conceptVO.setType(ConceptTypeEnum.Form.getKey());
            conceptVO.setNames(originList.stream()
                    .filter(i -> StringUtil.isNotBlank(i.getForm()))
                    .map(MappingConfigWrapper::getForm)
                    .distinct()
                    .collect(Collectors.toList()));
            RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
            if (RespDTOUtil.respIsOK(respDTO)) {
                Map<String, List<Long>> formMap = respDTO.data.stream()
                        .collect(Collectors.groupingBy(IndexBatchDTO::getName,
                                Collectors.mapping(IndexBatchDTO::getId, Collectors.toList())));
                for (MappingConfigWrapper item : originList) {
                    if (StringUtil.isBlank(item.getForm())) {
                        continue;
                    }
                    if (formMap.containsKey(item.getForm())) {
                        item.setFormConceptId(formMap.get(item.getForm()).get(0));
                    } else {
                        //标准词已匹配，剂型未匹配，不做错误数据，不改变匹配标志，剂型置空
                        item.setForm("");
                    }
                }
            }
        }

        originList = originList.stream().distinct().collect(Collectors.toList());
        List<String> hisNames = originList
                .stream()
                .map(i -> i.getHisName())
                .distinct()
                .collect(Collectors.toList());

        List<MappingConfigWrapper> matchList
                = originList.stream().filter(i -> StringUtil.isNotBlank(i.getUniqueName())).collect(Collectors.toList());
        Map<String, List<MappingConfigWrapper>> matchMap
                = matchList.stream().collect(Collectors.groupingBy(i -> i.getHisName() + "_"
                + i.getHisCode() + "_"
                + i.getHisDetailName()));
        Map<String, List<MappingConfigWrapper>> fullMatchMap = matchList.stream()
                .collect(Collectors.groupingBy(i -> i.getHisName() + "_"
                        + i.getHisCode() + "_"
                        + i.getHisDetailName() + "_"
                        + i.getUniqueName() + "_"
                        + i.getForm()));
        List<MappingConfigWrapper> unMatchList
                = originList.stream().filter(i -> StringUtil.isBlank(i.getUniqueName())).collect(Collectors.toList());
        Map<String, List<MappingConfigWrapper>> unMatchMap
                = unMatchList.stream().collect(Collectors.groupingBy(i -> i.getHisName() + "_"
                + i.getHisCode() + "_"
                + i.getHisDetailName()));
        //导入文件中同时存在已匹配未匹配数据，删除未匹配数据
        Iterator<MappingConfigWrapper> it = unMatchList.iterator();
        while (it.hasNext()) {
            MappingConfigWrapper item = it.next();
            String matchKey = item.getHisName() + "_"
                    + item.getHisCode() + "_"
                    + item.getHisDetailName();
            if (matchMap.containsKey(matchKey)) {
                it.remove();
            }
        }

        // 验证数据是否已存在，已存在的先删除
        // 没id的删除重新插入，有id的更新
        List<MappingConfigWrapper> db_matchList = Lists.newLinkedList();
        List<MappingConfigWrapper> db_unMatchList = Lists.newLinkedList();
        Map<String, List<MappingConfigWrapper>> db_matchMap = new HashMap<>();
        Map<String, List<MappingConfigWrapper>> db_fullMatchMap = new HashMap<>();
        Map<String, List<MappingConfigWrapper>> db_unMatchMap = new HashMap<>();
        synchronized (this) {
            List<Long> deleteIds = Lists.newLinkedList();
            List<MappingConfig> dbList = this.list(new QueryWrapper<MappingConfig>()
                    .eq("is_deleted", IsDeleteEnum.N.getKey())
                    .eq("hospital_id", hospitalId)
                    .eq("type", type)
                    .in("his_name", hisNames));

            if (ListUtil.isNotEmpty(dbList)) {
                List<MappingConfigWrapper> dbWrapperList = BeanUtil.listCopyTo(dbList, MappingConfigWrapper.class);
                //保留所有原始数据（禁用的和启用的）
                dbWrapperList = addNames(dbWrapperList, null);
                for (MappingConfigWrapper item : dbWrapperList) {
                    if (StringUtil.isBlank(item.getHisDetailName())) {
                        item.setHisDetailName("");
                    }
                    if (StringUtil.isBlank(item.getUniqueName())) {
                        item.getUniqueName();
                    }
                    if (StringUtil.isBlank(item.getForm())) {
                        item.setForm("");
                    }
                    if (StringUtil.isBlank(item.getHisCode())) {
                        item.setHisCode("");
                    }
                }

                db_matchList = dbWrapperList.stream().filter(i -> i.getIsMatch().equals(1)).collect(Collectors.toList());
                db_matchMap = db_matchList.stream().collect(Collectors.groupingBy(i -> i.getHisName() + "_"
                        + i.getHisCode() + "_"
                        + i.getHisDetailName()));
                db_fullMatchMap = db_matchList.stream()
                        .collect(Collectors.groupingBy(i -> i.getHisName() + "_"
                                + i.getHisCode() + "_"
                                + i.getHisDetailName() + "_"
                                + i.getUniqueName() + "_"
                                + i.getForm()));
                db_unMatchList = dbWrapperList.stream().filter(i -> i.getIsMatch().equals(0)).collect(Collectors.toList());
                db_unMatchMap = db_unMatchList.stream().collect(Collectors.groupingBy(i -> i.getHisName() + "_"
                        + i.getHisCode() + "_"
                        + i.getHisDetailName()));

                for (MappingConfigWrapper item : db_matchList) {
                    //导入文件中与数据库中存在完全一致的已匹配数据，删除数据库中的，把导入文件中的新增到数据库
                    String matchKey = item.getHisName() + "_"
                            + item.getHisCode() + "_"
                            + item.getHisDetailName() + "_"
                            + item.getUniqueName() + "_"
                            + item.getForm();
                    if (fullMatchMap.containsKey(matchKey)) {
                        deleteIds.add(item.getId());
                    }
                }
                for (MappingConfigWrapper item : db_unMatchList) {
                    //导入文件中存在已匹配的数据，数据库中存在未匹配的，删除数据库中的，把导入文件中的新增到数据库
                    String matchKey = item.getHisName() + "_"
                            + item.getHisCode() + "_"
                            + item.getHisDetailName();
                    if (matchMap.containsKey(matchKey)
                            || db_matchMap.containsKey(matchKey)
                            || unMatchMap.containsKey(matchKey)) {
                        deleteIds.add(item.getId());
                    }
                }

                //数据库中已存在匹配项，去除导入文件中未匹配项
                it = unMatchList.iterator();
                while (it.hasNext()) {
                    MappingConfigWrapper item = it.next();
                    String matchKey = item.getHisName() + "_"
                            + item.getHisCode() + "_"
                            + item.getHisDetailName();
                    if (db_matchMap.containsKey(matchKey)) {
                        it.remove();
                    }
                }
            }

            //过滤后的导入结果集
            tempList.addAll(matchList);
            tempList.addAll(unMatchList);

            //重复数据过滤
            tempList = tempList
                    .stream()
                    .distinct()
                    .collect(Collectors.toList());

            //生成保存数据
            List<MappingConfig> saveList = Lists.newLinkedList();
            for (MappingConfigWrapper item : tempList) {
                item.setHospitalId(hospitalId);
                item.setType(type);
                item.setCreator(userId);
                item.setGmtCreate(now);
                item.setModifier(userId);
                item.setGmtModified(now);
                MappingConfig saveItem = new MappingConfig();
                BeanUtils.copyProperties(item, saveItem);
                saveList.add(saveItem);
            }

            //删除已存在映射关系
            IdListVO idListVO = new IdListVO();
            idListVO.setIds(deleteIds);
            deleteRecords(idListVO);
            saveList = saveList.stream().distinct().collect(Collectors.toList());
            if (ListUtil.isNotEmpty(saveList)) {
                mappingConfigService.saveOrUpdateBatch(saveList);
            }
        }
        return errorList;
    }

    /**
     * 删除记录-单条
     *
     * @param idVO
     * @return
     */
    public Boolean deleteRecord(IdVO idVO) {
        UpdateWrapper<MappingConfig> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", idVO.getId())
                .set("is_deleted", IsDeleteEnum.Y.getKey());
        mappingConfigService.removeById(idVO.getId());
        return true;
    }

    /**
     * 删除记录-批量
     *
     * @param idListVO
     * @return
     */
    public Boolean deleteRecords(IdListVO idListVO) {
        if (ListUtil.isEmpty(idListVO.getIds())) {
            return false;
        }
        UpdateWrapper<MappingConfig> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("id", idListVO.getIds())
                .set("is_deleted", IsDeleteEnum.Y.getKey());
        mappingConfigService.removeByIds(idListVO.getIds());
        return true;
    }

    /**
     * 获取记录-单条
     *
     * @param idVO
     * @return
     */
    public MappingConfigWrapper getRecord(IdVO idVO) {
        MappingConfig item = this.getById(idVO.getId());
        MappingConfigWrapper itemWrapper = new MappingConfigWrapper();
        BeanUtils.copyProperties(item, itemWrapper);
        List<MappingConfigWrapper> retList = Lists.newArrayList();
        retList.add(itemWrapper);
        retList = addNames(retList, null);

        return retList.get(0);
    }

    /**
     * 查询已关联关系
     *
     * @param mappingConfigVO
     * @return
     */
    public List<MappingConfigWrapper> getRelatedMapping(MappingConfigVO mappingConfigVO) {
        List<MappingConfigWrapper> retList = Lists.newLinkedList();
        if (mappingConfigVO.getHospitalId() == null) {
            mappingConfigVO.setHospitalId(Long.valueOf(SysUserUtils.getCurrentHospitalID()));
        }
        QueryWrapper<MappingConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("hospital_id", mappingConfigVO.getHospitalId())
                .eq("type", mappingConfigVO.getType())
                .eq("his_name", mappingConfigVO.getHisName())
                .eq("is_match", 1);
        if (StringUtil.isNotBlank(mappingConfigVO.getHisDetailName())) {
            queryWrapper.eq("his_detail_name", mappingConfigVO.getHisDetailName());
        } else {
            queryWrapper.and(i -> i.isNull("his_detail_name")
                    .or()
                    .eq("his_detail_name", ""));
        }

        List<MappingConfig> list = this.list(queryWrapper);

        if (ListUtil.isEmpty(list)) {
            return retList;
        }

        retList = BeanUtil.listCopyTo(list, MappingConfigWrapper.class);

        retList = addNames(retList, null);
        return retList;
    }

    /**
     * 判断是否已存在
     *
     * @param mappingConfig
     * @return
     */
    public Boolean isExistRecord(MappingConfig mappingConfig) {
        if (mappingConfig.getType() == null) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "请输入请输入术语类型：1-化验、3-辅检、4-诊断、5-药品、6-手术和操作、7-科室、8-输血、10-量表、11-护理、12-中医诊断、13-中医证候、14-麻醉、16-给药途径");
        }
        if (mappingConfig.getHospitalId() == null) {
            mappingConfig.setHospitalId(Long.valueOf(SysUserUtils.getCurrentHospitalID()));
        }
        QueryWrapper<MappingConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("hospital_id", mappingConfig.getHospitalId())
                .eq("type", mappingConfig.getType())
                .eq("his_name", mappingConfig.getHisName())
                .eq("concept_id", mappingConfig.getConceptId());
        if (StringUtil.isBlank(mappingConfig.getHisDetailName())) {
            queryWrapper.and(i -> i.isNull("his_detail_name")
                    .or()
                    .eq("his_detail_name", ""));
        } else {
            queryWrapper
                    .eq("his_detail_name", mappingConfig.getHisDetailName());
        }
        if (StringUtil.isBlank(mappingConfig.getHisCode())) {
            queryWrapper.and(i -> i.isNull("his_code")
                    .or()
                    .eq("his_code", ""));
        } else {
            queryWrapper
                    .eq("his_code", mappingConfig.getHisCode());
        }
        if (mappingConfig.getFormConceptId() != null) {
            queryWrapper.eq("form_concept_id", mappingConfig.getFormConceptId());
        } else {
            queryWrapper.isNull("form_concept_id");
        }
        if (mappingConfig.getFormConceptId() != null) {
            queryWrapper.eq("form_concept_id", mappingConfig.getFormConceptId());
        }
        MappingConfig oldRecord = this.getOne(queryWrapper, false);
        if (mappingConfig.getId() == null
                && oldRecord != null) {
            throw new CommonException(CommonErrorCode.IS_EXISTS, "该条关联已存在，无法保存");
        }
        if (mappingConfig.getId() != null
                && oldRecord != null
                && !mappingConfig.getId().equals(oldRecord.getId())) {
            throw new CommonException(CommonErrorCode.IS_EXISTS, "该条关联已存在，无法保存");
        }
        return false;
    }

    /**
     * 保存记录-单条
     *
     * @param mappingConfig
     * @return
     */
    public Boolean saveOrUpdateRecord(MappingConfig mappingConfig) {
        if (mappingConfig.getType() == null) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "请输入请输入术语类型：1-化验、3-辅检、4-诊断、5-药品、6-手术和操作、7-科室、8-输血、10-量表、11-护理、12-中医诊断、13-中医证候、14-麻醉、16-给药途径");
        }
        if (mappingConfig.getConceptId() == null) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "标准术语不允许为空，请输入标准术语id");
        }
        if (mappingConfig.getHospitalId() == null) {
            mappingConfig.setHospitalId(Long.valueOf(SysUserUtils.getCurrentHospitalID()));
        }
        String userId = "";
        if (StringUtil.isBlank(mappingConfig.getModifier())) {
            userId = SysUserUtils.getCurrentPrincipleID();
        }
        if (StringUtil.isBlank(userId)) {
            userId = "0";
        }
        Date now = DateUtil.now();
        mappingConfig.setModifier(userId);
        mappingConfig.setGmtModified(now);
        QueryWrapper<MappingConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("hospital_id", mappingConfig.getHospitalId())
                .eq("type", mappingConfig.getType())
                .eq("his_name", mappingConfig.getHisName())
                .eq("concept_id", mappingConfig.getConceptId());
        if (StringUtil.isBlank(mappingConfig.getHisDetailName())) {
            queryWrapper.and(i -> i.isNull("his_detail_name")
                    .or()
                    .eq("his_detail_name", ""));
        } else {
            queryWrapper.eq("his_detail_name", mappingConfig.getHisDetailName());
        }
        if (StringUtil.isBlank(mappingConfig.getHisCode())) {
            queryWrapper.and(i -> i.isNull("his_code")
                    .or()
                    .eq("his_code", ""));
        } else {
            queryWrapper
                    .eq("his_code", mappingConfig.getHisCode());
        }
        if (mappingConfig.getFormConceptId() != null) {
            queryWrapper.eq("form_concept_id", mappingConfig.getFormConceptId());
        } else {
            queryWrapper.isNull("form_concept_id");
        }
        MappingConfig oldRecord = this.getOne(queryWrapper, false);
        if (mappingConfig.getId() == null
                && oldRecord != null) {
            throw new CommonException(CommonErrorCode.IS_EXISTS, "该条关联已存在，无法保存");
        }
        if (mappingConfig.getId() != null
                && oldRecord != null
                && !mappingConfig.getId().equals(oldRecord.getId())) {
            throw new CommonException(CommonErrorCode.IS_EXISTS, "该条关联已存在，无法保存");
        }
        //标准术语校验
        ConceptVO conceptVO = new ConceptVO();
        conceptVO.setSource(-1);
        conceptVO.setStatus(StatusEnum.Enable.getKey());
        List<Long> conceptIds = Lists.newLinkedList();
        conceptIds.add(mappingConfig.getConceptId());
        if (mappingConfig.getFormConceptId() != null) {
            conceptIds.add(mappingConfig.getFormConceptId());
        }
        conceptVO.setIds(conceptIds);

        RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
        if (RespDTOUtil.respIsOK(respDTO)) {
            Map<Long, IndexBatchDTO> dtoMap = respDTO.data.stream().collect(Collectors.toMap(IndexBatchDTO::getId, v -> v));
            if (!dtoMap.containsKey(mappingConfig.getConceptId())) {
                throw new CommonException(CommonErrorCode.NOT_EXISTS, "标准术语校验失败");
            }
            if (mappingConfig.getFormConceptId() != null && (!dtoMap.containsKey(mappingConfig.getFormConceptId()))) {
                throw new CommonException(CommonErrorCode.NOT_EXISTS, "剂型校验失败");
            }
        } else {
            throw new CommonException(CommonErrorCode.NOT_EXISTS, "标准术语校验失败");
        }

        //新增数据
        if (mappingConfig.getId() == null) {
            mappingConfig.setCreator(userId);
            mappingConfig.setGmtCreate(now);
        }
        if (mappingConfig.getIsDeleted() == null) {
            mappingConfig.setIsDeleted(IsDeleteEnum.N.getKey());
        }

        saveOrUpdateMappingConfig(mappingConfig);
        return true;
    }

    @Transactional
    private void saveOrUpdateMappingConfig(MappingConfig mappingConfig){
        //删除未匹配的关系
        QueryWrapper<MappingConfig> qwUnMaptch = new QueryWrapper<>();
        qwUnMaptch.eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("hospital_id", mappingConfig.getHospitalId())
                .eq("type", mappingConfig.getType())
                .eq("his_name", mappingConfig.getHisName())
                .isNull("concept_id")
                .eq("is_match", 0);
        if (StringUtil.isBlank(mappingConfig.getHisDetailName())) {
            qwUnMaptch.and(i -> i.isNull("his_detail_name")
                    .or()
                    .eq("his_detail_name", ""));
        } else {
            qwUnMaptch.eq("his_detail_name", mappingConfig.getHisDetailName());
        }
        if (StringUtil.isBlank(mappingConfig.getHisCode())) {
            qwUnMaptch.and(i -> i.isNull("his_code")
                    .or()
                    .eq("his_code", ""));
        } else {
            qwUnMaptch
                    .eq("his_code", mappingConfig.getHisCode());
        }
        this.remove(qwUnMaptch);

        mappingConfig.setIsMatch(1);
        this.saveOrUpdate(mappingConfig);
    }


    /**
     * 根据医院名称分组-返回id
     *
     * @param hisNames
     * @param type
     * @return
     */
    public Map<String, Map<String, Map<Long, List<Long>>>> groupByHisNameWithId(List<String> hisNames, Integer type, Long hospitalId) {
        Map<String, Map<String, Map<Long, List<Long>>>> retMap = new HashMap<>();
        QueryWrapper<MappingConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("is_match", 1)
                .eq("type", type);
        if (hospitalId != null) {
            queryWrapper.eq("hospital_id", hospitalId);
        }
        if (ListUtil.isNotEmpty(hisNames)) {
            queryWrapper.in("his_name", hisNames);
        }
        List<MappingConfig> list = this.list(queryWrapper);

        if (ListUtil.isEmpty(list)) {
            return retMap;
        }

        for (MappingConfig item : list) {
            if (StringUtil.isBlank(item.getHisDetailName())) {
                item.setHisDetailName("");
            }
            item.setId(null);
            item.setHospitalId(null);
        }

        list = list.stream().distinct().collect(Collectors.toList());

        Map<String, List<MappingConfig>> hisMap = list.stream()
                .filter(i -> StringUtil.isNotBlank(i.getHisName()))
                .collect(Collectors.groupingBy(MappingConfig::getHisName));
        for (Map.Entry<String, List<MappingConfig>> entry : hisMap.entrySet()) {
            Map<String, Map<Long, List<Long>>> subMap = new HashMap<>();
            Map<String, List<MappingConfig>> detailMap = entry.getValue().stream()
                    .collect(Collectors.groupingBy(MappingConfig::getHisDetailName));
            for (Map.Entry<String, List<MappingConfig>> subEntry : detailMap.entrySet()) {
                subMap.put(subEntry.getKey(),
                        subEntry.getValue()
                                .stream()
                                .collect(Collectors.groupingBy(MappingConfig::getConceptId,
                                        Collectors.mapping(MappingConfig::getFormConceptId, Collectors.toList()))));
            }
            retMap.put(entry.getKey(), subMap);
        }
        return retMap;
    }

    /**
     * 根据医院名称分组-返回名称
     *
     * @param hisNames
     * @param type
     * @param hospitalId
     * @param status     标准术语启用禁用标志
     * @return
     */
    public Map<String, Map<String, Map<String, List<String>>>> groupByHisNameWithName(List<String> hisNames, Integer type, Long hospitalId, Integer status) {
        Map<String, Map<String, Map<String, List<String>>>> retMap = new HashMap<>();
        Map<String, Map<String, Map<Long, List<Long>>>> idMap = groupByHisNameWithId(hisNames, type, hospitalId);

        //conceptIds
        List<Long> ids = idMap.values()
                .stream()
                .flatMap(i -> i.values().stream())
                .map(i -> i.keySet())
                .flatMap(Collection::stream)
                .filter(i -> i != null)
                .distinct()
                .collect(Collectors.toList());

        //formConceptId
        ids.addAll(idMap.values()
                .stream()
                .flatMap(i -> i.values().stream())
                .flatMap(i -> i.values().stream())
                .flatMap(Collection::stream)
                .filter(i -> i != null)
                .distinct()
                .collect(Collectors.toList()));

        ConceptVO conceptVO = new ConceptVO();
        conceptVO.setSource(-1);
        conceptVO.setType(type);
        conceptVO.setIds(ids);
        conceptVO.setStatus(status);
        RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
        RespDTOUtil.respNGDealCover(respDTO, "标准术语校验失败");
        List<IndexBatchDTO> indexList = respDTO.data;
        if (ListUtil.isNotEmpty(indexList)) {
            Map<Long, String> idNameMap
                    = indexList.stream().collect(Collectors.toMap(IndexBatchDTO::getId, IndexBatchDTO::getName));
            for (Map.Entry<String, Map<String, Map<Long, List<Long>>>> entry : idMap.entrySet()) {
                Map<String, Map<String, List<String>>> subMap = new HashMap<>();
                for (Map.Entry<String, Map<Long, List<Long>>> subEntry : entry.getValue().entrySet()) {
                    Map<String, List<String>> thirdMap = new HashMap<>();
                    for (Map.Entry<Long, List<Long>> thirdEntry : subEntry.getValue().entrySet()) {
                        List<Long> formConceptIds = thirdEntry.getValue();
                        List<String> forms = Lists.newArrayList();
                        if (ListUtil.isNotEmpty(formConceptIds)) {
                            for (Long formConceptId : formConceptIds) {
                                if (formConceptId == null) {
                                    forms.add("");
                                } else {
                                    if (idNameMap.containsKey(formConceptId)) {
                                        forms.add(idNameMap.get(formConceptId));
                                    } else {
                                        forms.add("");
                                    }
                                }
                            }
                            forms = forms.stream().distinct().collect(Collectors.toList());
                            if (idNameMap.containsKey(thirdEntry.getKey())) {
                                thirdMap.put(idNameMap.get(thirdEntry.getKey()), forms);
                            } /*else {
                                thirdMap.put("", Lists.newLinkedList());
                            }*/
                        }
                    }
                    subMap.put(subEntry.getKey(), thirdMap);
                }
                if (subMap != null && subMap.size() > 0) {
                    retMap.put(entry.getKey(), subMap);
                }
            }
        }
        return retMap;
    }


    /**
     * 根据标准名称分组-返回名称
     *
     * @param uniqueNames
     * @param type
     * @param hospitalId
     * @return uniqueName, form, hisName, hisDetailName
     */
    public Map<String, Map<String, Map<String, List<String>>>> groupByUniqueNameWithName(List<String> uniqueNames, Integer type, Long hospitalId, Integer status) {
        Map<String, Map<String, Map<String, List<String>>>> retMap = new HashMap<>();

        List<Long> conceptIds = Lists.newArrayList();

        ConceptVO conceptVO = new ConceptVO();
        RespDTO<List<IndexBatchDTO>> respDTO = null;
        List<IndexBatchDTO> indexList = Lists.newArrayList();
        if (ListUtil.isNotEmpty(uniqueNames)) {
            conceptVO.setType(type);
            conceptVO.setNames(uniqueNames);
            conceptVO.setSource(MatchSourceEnum.StandWord.getKey());
            respDTO = cdssCoreClient.getConceptNames(conceptVO);
            if (RespDTOUtil.respIsOK(respDTO)) {
                indexList.addAll(respDTO.data);
            }

            if (type.equals(ConceptTypeEnum.LisPack.getKey())) {
                conceptVO.setType(ConceptTypeEnum.Lis.getKey());
                respDTO = cdssCoreClient.getConceptNames(conceptVO);
                if (RespDTOUtil.respIsOK(respDTO)) {
                    indexList.addAll(respDTO.data);
                }
            }
        }

        if (ListUtil.isNotEmpty(indexList)) {
            conceptIds = indexList.stream().map(IndexBatchDTO::getId).distinct().collect(Collectors.toList());
        }

        QueryWrapper<MappingConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("is_match", 1)
                .eq("type", type);
        if (hospitalId != null) {
            queryWrapper.eq("hospital_id", hospitalId);
        }
        if (ListUtil.isNotEmpty(conceptIds)) {
            queryWrapper.in("concept_id", conceptIds);
        }
        List<MappingConfig> list = this.list(queryWrapper);

        if (ListUtil.isEmpty(list)) {
            return retMap;
        }

        List<MappingConfigWrapper> wrapperList = BeanUtil.listCopyTo(list, MappingConfigWrapper.class);
        wrapperList = addNames(wrapperList, status);
        wrapperList.forEach(item -> {
            if (StringUtil.isBlank(item.getForm())) {
                item.setForm("");
            }
            if (StringUtil.isBlank(item.getHisDetailName())) {
                item.setHisDetailName("");
            }
        });


        Map<String, List<MappingConfigWrapper>> map = wrapperList.stream()
                .filter(i -> StringUtil.isNotBlank(i.getUniqueName()))
                .collect(Collectors.groupingBy(MappingConfigWrapper::getUniqueName));

        for (Map.Entry<String, List<MappingConfigWrapper>> entry : map.entrySet()) {
            Map<String, Map<String, List<String>>> subMap = new HashMap<>();
            Map<String, List<MappingConfigWrapper>> formMap
                    = entry.getValue().stream().collect(Collectors.groupingBy(MappingConfigWrapper::getForm));
            for (Map.Entry<String, List<MappingConfigWrapper>> subEntry : formMap.entrySet()) {
                subMap.put(subEntry.getKey(), subEntry.getValue().stream().collect(Collectors.groupingBy(MappingConfigWrapper::getHisName,
                        Collectors.mapping(MappingConfigWrapper::getHisDetailName, Collectors.toList()))));
            }
            retMap.put(entry.getKey(), subMap);
        }

        return retMap;
    }

    /**
     * 返回结果添加标准术语，药品剂型
     *
     * @param list
     * @return
     */
    public List<MappingConfigWrapper> addNames(List<MappingConfigWrapper> list, Integer status) {
        if (ListUtil.isEmpty(list)) {
            return list;
        }

        List<Long> ids = Lists.newArrayList();
        ids.addAll(list.stream()
                .filter(i -> i.getConceptId() != null)
                .map(MappingConfigWrapper::getConceptId)
                .collect(Collectors.toList()));
        ids.addAll(list.stream()
                .filter(i -> i.getFormConceptId() != null)
                .map(MappingConfigWrapper::getFormConceptId)
                .collect(Collectors.toList()));

        ConceptVO conceptVO = new ConceptVO();
        conceptVO.setSource(-1);
        conceptVO.setIds(ids);
        conceptVO.setStatus(status);
        RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
        if (RespDTOUtil.respIsOK(respDTO)) {
            Map<Long, IndexBatchDTO> conceptMap
                    = respDTO.data.stream().collect(Collectors.toMap(IndexBatchDTO::getId, v -> v));
            for (MappingConfigWrapper record : list) {
                if (record.getConceptId() != null && conceptMap.containsKey(record.getConceptId())) {
                    record.setUniqueName(conceptMap.get(record.getConceptId()).getName());
                    record.setCode(conceptMap.get(record.getConceptId()).getCode());
                    record.setStatus(conceptMap.get(record.getConceptId()).getStatus());
                }
                if (record.getFormConceptId() != null && conceptMap.containsKey(record.getFormConceptId())) {
                    record.setForm(conceptMap.get(record.getFormConceptId()).getName());
                    record.setFormStatus(conceptMap.get(record.getFormConceptId()).getStatus());
                }
            }
        }
        return list;
    }


    /**
     * 返回结果添加编码
     *
     * @param list
     * @return
     */
    public List<MappingConfigWrapper> addCodes(List<MappingConfigWrapper> list, Integer type, Integer status) {
        List<MappingConfigWrapper> retList = Lists.newLinkedList();
        if (ListUtil.isEmpty(list)) {
            return list;
        }

        if (!(type.equals(ConceptTypeEnum.Operation.getKey())
                || type.equals(ConceptTypeEnum.Disease.getKey())
                || type.equals(ConceptTypeEnum.Tcmdisease.getKey())
                || type.equals(ConceptTypeEnum.Tcmsyndrome.getKey()))) {
            return list;
        }

        List<String> names = list.stream()
                .filter(i -> StringUtil.isNotBlank(i.getUniqueName()))
                .map(MappingConfigWrapper::getUniqueName)
                .collect(Collectors.toList());

        ConceptVO conceptVO = new ConceptVO();
        conceptVO.setSource(MatchSourceEnum.StandWord.getKey());
        conceptVO.setType(type);
        conceptVO.setNames(names);
        conceptVO.setStatus(status);
        RespDTO<List<IndexBatchDTO>> respDTO = cdssCoreClient.getConceptNames(conceptVO);
        if (RespDTOUtil.respIsOK(respDTO)) {
            Map<String, List<String>> conceptMap
                    = respDTO.data.stream().collect(Collectors.groupingBy(IndexBatchDTO::getName,
                    Collectors.mapping(IndexBatchDTO::getCode, Collectors.toList())));
            for (MappingConfigWrapper record : list) {
                if (StringUtil.isNotBlank(record.getUniqueName())
                        && conceptMap.containsKey(record.getUniqueName())) {
                    for (String code : conceptMap.get(record.getUniqueName())) {
                        MappingConfigWrapper tempRecord = new MappingConfigWrapper();
                        BeanUtils.copyProperties(record, tempRecord);
                        tempRecord.setCode(code);
                        retList.add(tempRecord);
                    }
                } else {
                    retList.add(record);
                }
            }
        }
        return retList;
    }


    /**
     * 医院术语检索
     *
     * @param retrievalVO
     * @return
     */
    public List<String> getHisNames(RetrievalVO retrievalVO) {
        List<MappingConfig> records = this.hisNameIndex(retrievalVO);
        List<String> hisNames
                = records.stream().map(MappingConfig::getHisName).distinct().collect(Collectors.toList());
        return hisNames;
    }

    /**
     * 医院术语-细项检索
     *
     * @param retrievalVO
     * @return
     */
    public List<LisDetailDTO> getHisDetailNames(RetrievalVO retrievalVO) {
        retrievalVO.setType(ConceptTypeEnum.LisPack.getKey());
        List<LisDetailDTO> lisDetailNames = new ArrayList<>();
        List<MappingConfig> records = this.hisDetailNameIndex(retrievalVO);
        if (ListUtil.isNotEmpty(records)) {
            List<Long> conceptIds = records.stream()
                    .filter(i -> i.getConceptId() != null)
                    .map(MappingConfig::getConceptId).distinct().collect(Collectors.toList());
            ConceptVO conceptVO = new ConceptVO();
            conceptVO.setSource(-1);
            conceptVO.setIds(conceptIds);
            conceptVO.setType(ConceptTypeEnum.Lis.getKey());
            RespDTO<List<IndexBatchDTO>> indexRespDTO = cdssCoreClient.getConceptNames(conceptVO);
            if (RespDTOUtil.respIsOK(indexRespDTO)) {
                List<String> names = indexRespDTO.data.stream().map(IndexBatchDTO::getName).distinct().collect(Collectors.toList());
                Map<Long, List<String>> indexMap = indexRespDTO.data.stream().collect(Collectors.groupingBy(IndexBatchDTO::getId,
                        Collectors.mapping(IndexBatchDTO::getName, Collectors.toList())));
                KllisDetailVO kllisDetailVO = new KllisDetailVO();
                kllisDetailVO.setNames(names);
                RespDTO<Map<String, KllisDetailDTO>> respDTO = cdssCoreClient.getLisDetaisByNames(kllisDetailVO);
                Map<String, KllisDetailDTO> map = new HashMap<>();
                if (null != respDTO && null != respDTO.data) {
                    map = respDTO.data;
                }
                for (MappingConfig record : records) {
                    LisDetailDTO lisDetailDTO = new LisDetailDTO();
                    lisDetailDTO.setName(record.getHisName());
                    lisDetailDTO.setUniqueName(record.getHisDetailName());
                    if (null != record.getConceptId()
                            && indexMap.containsKey(record.getConceptId())
                            && (null != map.get(indexMap.get(record.getConceptId()).get(0)))) {
                        KllisDetailDTO kllisDetailDTO = map.get(indexMap.get(record.getConceptId()).get(0));
                        lisDetailDTO.setMaxValue(kllisDetailDTO.getMaxValue());
                        lisDetailDTO.setMinValue(kllisDetailDTO.getMinValue());
                        lisDetailDTO.setUnits(kllisDetailDTO.getUnit());
                        lisDetailDTO.setRange(kllisDetailDTO.getType());
                    }
                    lisDetailNames.add(lisDetailDTO);
                }
            }
        }
        return lisDetailNames;
    }
}