package com.lantone.facade.med;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lantone.dto.med.IndexBatchDTO;
import com.lantone.dto.med.KllisDetailDTO;
import com.lantone.entity.med.KlConcept;
import com.lantone.entity.med.KlDisease;
import com.lantone.entity.med.KlLibraryInfo;
import com.lantone.entity.med.KlOperation;
import com.lantone.entity.med.TcmDisease;
import com.lantone.entity.med.TcmSyndrome;
import com.lantone.enums.med.ConceptTypeEnum;
import com.diagbot.enums.IsDeleteEnum;
import com.lantone.enums.med.LexiconEnum;
import com.lantone.enums.med.MatchSourceEnum;
import com.lantone.enums.med.StatusEnum;
import com.lantone.service.med.impl.KlConceptServiceImpl;
import com.diagbot.util.EntityUtil;
import com.diagbot.util.ListUtil;
import com.lantone.vo.med.ConceptVO;
import com.lantone.vo.med.FilterVO;
import com.lantone.vo.med.IndexByApprovalVO;
import com.lantone.vo.med.KllisDetailVO;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description:
 * @author: gaodm
 * @time: 2021/1/26 13:05
 */
@Component
public class KlConceptFacade extends KlConceptServiceImpl {

    //////////////
    @Autowired
    private KlDiseaseFacade klDiseaseFacade;

    //////////////
    @Autowired
    private KlOperationFacade klOperationFacade;
    @Autowired
    private TcmDiseaseFacade tcmDiseaseFacade;

    ///////////////////////////
    @Autowired
    private TcmSyndromeFacade tcmSyndromeFacade;

    ////////////
    @Autowired
    private KlLibraryInfoFacade klLibraryInfoFacade;


    //////////////////////////////////
    /**
     * 批量校验标准术语
     *
     * @param conceptVO
     * @return
     */
    public List<IndexBatchDTO> getConceptNames(ConceptVO conceptVO) {
        List<IndexBatchDTO> retList = Lists.newLinkedList();
        Integer type = convertType(conceptVO.getType(), false);

        if (conceptVO.getSource().equals(-1)) {
            if (ListUtil.isEmpty(conceptVO.getIds())) {
                return retList;
            }
            //根据id检索
            List<KlConcept> concepts = Lists.newLinkedList();
            List<KlConcept> tempList = Lists.newLinkedList();
            QueryWrapper<KlConcept> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey());
            if (conceptVO.getStatus() != null) {
                queryWrapper.eq("status", conceptVO.getStatus());
                if (conceptVO.getStatus().equals(StatusEnum.Disable.getKey())) {
                    tempList = this.list(queryWrapper);
                    if (ListUtil.isNotEmpty(tempList)) {
                        Map<Long, KlConcept> tempMap = tempList.stream().collect(Collectors.toMap(KlConcept::getId, v -> v));
                        for (Map.Entry<Long, KlConcept> entry : tempMap.entrySet()) {
                            if (conceptVO.getIds().contains(entry.getKey())) {
                                concepts.add(entry.getValue());
                            }
                        }
                    }
                }
            }
            if (conceptVO.getStatus() == null || conceptVO.getStatus().equals(StatusEnum.Enable.getKey())) {
                queryWrapper.in("id", conceptVO.getIds());
                concepts = this.list(queryWrapper);
            }
            for (KlConcept concept : concepts) {
                IndexBatchDTO dto = new IndexBatchDTO();
                dto.setId(concept.getId());
                dto.setName(concept.getLibName());
                dto.setStatus(concept.getStatus());
                dto.setType(convertType(concept.getLibType(), true));
                retList.add(dto);
            }
        } else if (conceptVO.getSource().equals(MatchSourceEnum.StandWord.getKey())) {
            QueryWrapper<KlConcept> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey());
            if (conceptVO.getStatus() != null) {
                queryWrapper.eq("status", conceptVO.getStatus());
            }
            if (ListUtil.isNotEmpty(conceptVO.getNames())) {
                queryWrapper.in("lib_name", conceptVO.getNames());
            }
            if (conceptVO.getType().equals(ConceptTypeEnum.Pacs.getKey())) {
                //辅检同时检索辅检项目和辅检子项
                queryWrapper.in("lib_type", Arrays.asList(LexiconEnum.PacsName.getKey(), LexiconEnum.PacsSubName.getKey()));
            } else {
                queryWrapper.eq("lib_type", type);
            }
            List<KlConcept> concepts = this.list(queryWrapper);

            if (ListUtil.isNotEmpty(concepts)) {
                for (KlConcept concept : concepts) {
                    IndexBatchDTO dto = new IndexBatchDTO();
                    dto.setId(concept.getId());
                    dto.setName(concept.getLibName());
                    dto.setStatus(concept.getStatus());
                    retList.add(dto);
                }
            }
        } else if (conceptVO.getSource().equals(MatchSourceEnum.SynonymsWord.getKey())) {
            if (ListUtil.isEmpty(conceptVO.getNames())) {
                return retList;
            }
            QueryWrapper<KlLibraryInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey())
                    .eq("is_concept", 0)
                    .in("name", conceptVO.getNames());
            if (conceptVO.getType().equals(ConceptTypeEnum.Pacs.getKey())) {
                //辅检同时检索辅检项目和辅检子项
                queryWrapper.in("type_id", Arrays.asList(LexiconEnum.PacsName.getKey(), LexiconEnum.PacsSubName.getKey()));
            } else {
                queryWrapper.eq("type_id", type);
            }
            List<KlLibraryInfo> libratyInfos = klLibraryInfoFacade.list(queryWrapper);
            if (ListUtil.isEmpty(libratyInfos)) {
                return retList;
            }
            Map<Long, List<KlLibraryInfo>> libraryInfoMap
                    = libratyInfos.stream().collect(Collectors.groupingBy(KlLibraryInfo::getConceptId));
            List<Long> synonymsRelatedConceptIds
                    = libratyInfos.stream().map(KlLibraryInfo::getConceptId).collect(Collectors.toList());
            QueryWrapper<KlConcept> conceptQueryWrapper = new QueryWrapper<>();
            conceptQueryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey())
                    .in("id", synonymsRelatedConceptIds);
            if (conceptVO.getStatus() != null) {
                conceptQueryWrapper.eq("status", conceptVO.getStatus());
            }
            List<KlConcept> synonymsRelatedConcepts = this.list(conceptQueryWrapper);
            Map<Long, KlConcept> conceptMap
                    = synonymsRelatedConcepts.stream().collect(Collectors.toMap(KlConcept::getId, v -> v));

            if (conceptMap != null && conceptMap.size() > 0) {
                for (Map.Entry<Long, KlConcept> entry : conceptMap.entrySet()) {
                    KlConcept concept = entry.getValue();
                    if (libraryInfoMap.containsKey(entry.getKey())) {
                        for (KlLibraryInfo libraryInfo : libraryInfoMap.get(entry.getKey())) {
                            if (!conceptVO.getNames().contains(libraryInfo.getName())) {
                                continue;
                            }
                            IndexBatchDTO indexBatchDTO = new IndexBatchDTO();
                            indexBatchDTO.setId(concept.getId());
                            indexBatchDTO.setName(concept.getLibName());
                            indexBatchDTO.setStatus(concept.getStatus());
                            indexBatchDTO.setSynonyms(libraryInfo.getName());
                            retList.add(indexBatchDTO);
                        }
                    }
                }
            }
        } else if (conceptVO.getSource().equals(MatchSourceEnum.Code.getKey())) {
            if (ListUtil.isEmpty(conceptVO.getNames())) {
                return retList;
            }
            List<Long> conceptIds = Lists.newArrayList();
            Map<Long, List<String>> codeMap = new HashMap<>();
            if (type.equals(LexiconEnum.Disease.getKey())) {
                List<KlDisease> diseases = klDiseaseFacade.list(new QueryWrapper<KlDisease>()
                        .eq("is_deleted", IsDeleteEnum.N.getKey())
                        .in("icd10_code", conceptVO.getNames()));
                if (ListUtil.isNotEmpty(diseases)) {
                    conceptIds = diseases.stream().map(KlDisease::getConceptId).distinct().collect(Collectors.toList());
                    codeMap = diseases.stream()
                            .collect(Collectors.groupingBy(KlDisease::getConceptId,
                                    Collectors.mapping(KlDisease::getIcd10Code, Collectors.toList())));
                }
            } else if (type.equals(LexiconEnum.Operation.getKey())) {
                List<KlOperation> operations = klOperationFacade.list(new QueryWrapper<KlOperation>()
                        .eq("is_deleted", IsDeleteEnum.N.getKey())
                        .in("operation_code", conceptVO.getNames()));
                if (ListUtil.isNotEmpty(operations)) {
                    conceptIds = operations.stream().map(KlOperation::getConceptId).distinct().collect(Collectors.toList());
                    codeMap = operations.stream()
                            .collect(Collectors.groupingBy(KlOperation::getConceptId,
                                    Collectors.mapping(KlOperation::getOperationCode, Collectors.toList())));
                }
            } else if (type.equals(LexiconEnum.Tcmdisease.getKey())) {
                List<TcmDisease> tcmDiseases = tcmDiseaseFacade.list(new QueryWrapper<TcmDisease>()
                        .eq("is_deleted", IsDeleteEnum.N.getKey())
                        .in("code", conceptVO.getNames()));
                if (ListUtil.isNotEmpty(tcmDiseases)) {
                    conceptIds = tcmDiseases.stream().map(TcmDisease::getConceptId).distinct().collect(Collectors.toList());
                    codeMap = tcmDiseases.stream().collect(Collectors.groupingBy(TcmDisease::getConceptId,
                            Collectors.mapping(TcmDisease::getCode, Collectors.toList())));
                }
            } else if (type.equals(LexiconEnum.Tcmsyndrome.getKey())) {
                List<TcmSyndrome> tcmSyndromes = tcmSyndromeFacade.list(new QueryWrapper<TcmSyndrome>()
                        .eq("is_deleted", IsDeleteEnum.N.getKey())
                        .in("code", conceptVO.getNames()));
                if (ListUtil.isNotEmpty(tcmSyndromes)) {
                    conceptIds = tcmSyndromes.stream().map(TcmSyndrome::getConceptId).distinct().collect(Collectors.toList());
                    codeMap = tcmSyndromes.stream().collect(Collectors.groupingBy(TcmSyndrome::getConceptId,
                            Collectors.mapping(TcmSyndrome::getCode, Collectors.toList())));
                }
            }
            if (ListUtil.isEmpty(conceptIds)) {
                return retList;
            }
            QueryWrapper<KlConcept> qw = new QueryWrapper<KlConcept>()
                    .eq("is_deleted", IsDeleteEnum.N.getKey())
                    .in("id", conceptIds);
            if (conceptVO.getStatus() != null) {
                qw.eq("status", conceptVO.getStatus());
            }
            List<KlConcept> concepts = this.list(qw);
            Map<Long, KlConcept> conceptMap
                    = concepts.stream().collect(Collectors.toMap(KlConcept::getId, v -> v));
            if (conceptMap != null && conceptMap.size() > 0) {
                for (Map.Entry<Long, KlConcept> entry : conceptMap.entrySet()) {
                    KlConcept concept = entry.getValue();
                    if (codeMap.containsKey(entry.getKey())) {
                        for (String code : codeMap.get(entry.getKey())) {
                            if (!conceptVO.getNames().contains(code)) {
                                continue;
                            }
                            IndexBatchDTO indexBatchDTO = new IndexBatchDTO();
                            indexBatchDTO.setId(concept.getId());
                            indexBatchDTO.setName(concept.getLibName());
                            indexBatchDTO.setCode(code);
                            indexBatchDTO.setStatus(concept.getStatus());
                            retList.add(indexBatchDTO);
                        }
                    }
                }
            }
        }

        if (ListUtil.isEmpty(retList)) {
            return retList;
        }
        //关联编码
        List<Long> conceptIds = retList.stream().map(IndexBatchDTO::getId).collect(Collectors.toList());
        //诊断关联编码
        List<KlDisease> diseases = klDiseaseFacade.list(new QueryWrapper<KlDisease>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .in("concept_id", conceptIds));
        if (ListUtil.isNotEmpty(diseases)) {
            Map<Long, KlDisease> idMap = diseases.stream().collect(Collectors.toMap(KlDisease::getConceptId, v -> v));
            for (IndexBatchDTO dto : retList) {
                if (idMap.containsKey(dto.getId())) {
                    dto.setCode(idMap.get(dto.getId()).getIcd10Code());
                }
            }
        }
        //手术关联编码
        List<KlOperation> operations = klOperationFacade.list(new QueryWrapper<KlOperation>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .in("concept_id", conceptIds));
        if (ListUtil.isNotEmpty(operations)) {
            Map<Long, KlOperation> idMap = operations.stream().collect(Collectors.toMap(KlOperation::getConceptId, v -> v));
            for (IndexBatchDTO dto : retList) {
                if (idMap.containsKey(dto.getId())) {
                    dto.setCode(idMap.get(dto.getId()).getOperationCode());
                }
            }
        }
        //中医疾病关联编码
        List<TcmDisease> tcmDiseases = tcmDiseaseFacade.list(new QueryWrapper<TcmDisease>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .in("concept_id", conceptIds));
        if (ListUtil.isNotEmpty(tcmDiseases)) {
            Map<Long, TcmDisease> idMap = tcmDiseases.stream().collect(Collectors.toMap(TcmDisease::getConceptId, v -> v));
            for (IndexBatchDTO dto : retList) {
                if (idMap.containsKey(dto.getId())) {
                    dto.setCode(idMap.get(dto.getId()).getCode());
                }
            }
        }
        //中医证候关联编码
        List<TcmSyndrome> tcmSyndromes = tcmSyndromeFacade.list(new QueryWrapper<TcmSyndrome>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .in("concept_id", conceptIds));
        if (ListUtil.isNotEmpty(tcmSyndromes)) {
            Map<Long, TcmSyndrome> idMap = tcmSyndromes.stream().collect(Collectors.toMap(TcmSyndrome::getConceptId, v -> v));
            for (IndexBatchDTO dto : retList) {
                if (idMap.containsKey(dto.getId())) {
                    dto.setCode(idMap.get(dto.getId()).getCode());
                }
            }
        }
        return retList;
    }


    ///////////////////////////////////////
    /**
     * 术语模糊检索
     *
     * @param filterVO
     * @return
     */
    public List<IndexBatchDTO> filter(FilterVO filterVO) {
        List<IndexBatchDTO> retList = Lists.newArrayList();
        QueryWrapper<KlConcept> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey())
                .like("lib_name", filterVO.getInputStr());
        if (filterVO.getStatus() != null) {
            queryWrapper.eq("status", filterVO.getStatus());
        }
        List<KlConcept> klConcepts = this.list(queryWrapper);
        for (KlConcept concept : klConcepts) {
            IndexBatchDTO indexBatchDTO = new IndexBatchDTO();
            indexBatchDTO.setId(concept.getId());
            indexBatchDTO.setName(concept.getLibName());
            indexBatchDTO.setStatus(concept.getStatus());
            Integer type = convertType(concept.getLibType(), true);
            if (type != null) {
                indexBatchDTO.setType(type);
                retList.add(indexBatchDTO);
            }
        }
        return retList;
    }


    //////////////////////////////////
    /**
     * 国药准字校验
     *
     * @param indexByApprovalVO
     * @return
     */
    @Override
    public List<IndexBatchDTO> indexByApproval(IndexByApprovalVO indexByApprovalVO) {
        if (ListUtil.isEmpty(indexByApprovalVO.getApprovalList())) {
            return new ArrayList<>();
        }
        return super.indexByApproval(indexByApprovalVO);
    }


    //////////////////////////////////
    /**
     * 类型互转
     *
     * @param type
     * @param reverse
     * @return
     */
    public Integer convertType(Integer type, Boolean reverse) {
        Integer retType = null;
        if (type == null) {
            return retType;
        }
        if (reverse) {
            if (type.equals(LexiconEnum.LisName.getKey())
                    || type.equals(LexiconEnum.LisSubName.getKey())) {
                retType = ConceptTypeEnum.LisPack.getKey();
            } else if (type.equals(LexiconEnum.PacsName.getKey())
                    || type.equals(LexiconEnum.PacsSubName.getKey())) {
                retType = ConceptTypeEnum.Pacs.getKey();
            } else if (type.equals(LexiconEnum.Disease.getKey())) {
                retType = ConceptTypeEnum.Disease.getKey();
            } else if (type.equals(LexiconEnum.Medicine.getKey())) {
                retType = ConceptTypeEnum.Drug.getKey();
            } else if (type.equals(LexiconEnum.Operation.getKey())) {
                retType = ConceptTypeEnum.Operation.getKey();
            } else if (type.equals(LexiconEnum.Dept.getKey())) {
                retType = ConceptTypeEnum.Dept.getKey();
            } else if (type.equals(LexiconEnum.Transfusion.getKey())) {
                retType = ConceptTypeEnum.Transfusion.getKey();
            } else if (type.equals(LexiconEnum.Scale.getKey())) {
                retType = ConceptTypeEnum.Scale.getKey();
            } else if (type.equals(LexiconEnum.Nurse.getKey())) {
                retType = ConceptTypeEnum.Nurse.getKey();
            } else if (type.equals(LexiconEnum.Tcmdisease.getKey())) {
                retType = ConceptTypeEnum.Tcmdisease.getKey();
            } else if (type.equals(LexiconEnum.Tcmsyndrome.getKey())) {
                retType = ConceptTypeEnum.Tcmsyndrome.getKey();
            } else if (type.equals(LexiconEnum.Anesthesia.getKey())) {
                retType = ConceptTypeEnum.Anesthesia.getKey();
            } else if (type.equals(LexiconEnum.Form.getKey())) {
                retType = ConceptTypeEnum.Form.getKey();
            } else if (type.equals(LexiconEnum.AdministrationRoute.getKey())) {
                retType = ConceptTypeEnum.AdministrationRoute.getKey();
            }
        } else {
            switch (type) {
                case 1:
                    retType = LexiconEnum.LisName.getKey();
                    break;
                case 2:
                    retType = LexiconEnum.LisSubName.getKey();
                    break;
                case 3:
                    retType = LexiconEnum.PacsName.getKey();
                    break;
                case 4:
                    retType = LexiconEnum.Disease.getKey();
                    break;
                case 5:
                    retType = LexiconEnum.Medicine.getKey();
                    break;
                case 6:
                    retType = LexiconEnum.Operation.getKey();
                    break;
                case 7:
                    retType = LexiconEnum.Dept.getKey();
                    break;
                case 8:
                    retType = LexiconEnum.Transfusion.getKey();
                    break;
                case 10:
                    retType = LexiconEnum.Scale.getKey();
                    break;
                case 11:
                    retType = LexiconEnum.Nurse.getKey();
                    break;
                case 12:
                    retType = LexiconEnum.Tcmdisease.getKey();
                    break;
                case 13:
                    retType = LexiconEnum.Tcmsyndrome.getKey();
                    break;
                case 14:
                    retType = LexiconEnum.Anesthesia.getKey();
                    break;
                case 15:
                    retType = LexiconEnum.Form.getKey();
                    break;
                case 16:
                    retType = LexiconEnum.AdministrationRoute.getKey();
                default:
                    break;
            }
        }
        return retType;
    }





    /////////////////////////////////////////
    public Map<String, KllisDetailDTO> getLisDetaisByNamesFac(KllisDetailVO kllisDetailVO) {
        List<KllisDetailDTO> list = this.getLisDetaisByNames(kllisDetailVO);
        Map<String, KllisDetailDTO> res = EntityUtil.makeEntityMap(list, "libName");
        return res;
    }

}