package com.ywt.outpatient.service.web;

import com.ywt.biz.common.util.CacheUtil;
import com.ywt.biz.common.util.Checker;
import com.ywt.biz.common.util.StringHelper;
import com.ywt.gapi.ResultCode;
import com.ywt.gapi.drug.DrugService;
import com.ywt.gapi.drug.GetIcdListRequest;
import com.ywt.gapi.drug.GetIcdListResponse;
import com.ywt.gapi.drug.Icd;
import com.ywt.outpatient.core.structs.TrieTree;
import com.ywt.outpatient.core.Constant;
import com.ywt.outpatient.service.rpc.common.ServiceResult;
import com.ywt.outpatient.service.web.prescription.DrugInfo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

@Service
public class DrugSrv {
    private final static Logger logger = LoggerFactory.getLogger(DrugSrv.class);
    // 太和疾病分类列表缓存键
    private final String TH_ICD_LIST_KEY = "TH_ICD_LIST";
    // 太和疾病分类字典树缓存键
    private final String TH_ICD_TRIE_TREE_KEY = "TH_ICD_TRIE_TREE";
    // 白云分院疾病分类字典树缓存键
    private final String NFYYBYFY_ICD_TRIE_TREE_KEY = "NFYYBYFY_ICD_TRIE_TREE";
    // 白云分院疾病分类列表缓存键
    private final String NFYYBYFY_ICD_LIST_KEY = "NFYYBYFY_ICD_LIST";

    @DubboReference
    private DrugService drugServiceBlockingStub;

    /**
     * 根据名称关键词搜索诊断结果
     */
    public List<Icd> getIcdByName(String name, int hospitalId) {
        List<Icd> list = getIcdListFromCache(hospitalId);
        return list.stream().filter(p -> p.getDiseaseName().contains(name)).collect(Collectors.toList());
    }

    /**
     * 根据名称拼音搜索诊断结果
     *
     * @param pinyin 名称拼音
     */
    public List<Icd> getIcdByPinYin(String pinyin, int hospitalId) {
        if (StringHelper.isNullOrWhiteSpace(pinyin)) {
            return new LinkedList<>();
        }
        TrieTree<Icd> trieTree = getIcdTrieTree(hospitalId);
        return trieTree.searchByPrefix(pinyin.toUpperCase());
    }

    /**
     * 获取国际疾病分类，按首字母拼音构建的Trie Tree
     */
    public TrieTree<Icd> getIcdTrieTreeFromCache(int hospitalId) {
        String key;
        switch (hospitalId) {
            case Constant.TAIHE_HOSPITAL_ID:
                key = TH_ICD_TRIE_TREE_KEY;//太和诊断结果
                break;
            case Constant.NFYYBYFY_HOSPITAL_ID:
                key = NFYYBYFY_ICD_TRIE_TREE_KEY;
                break;
            default:
                throw new IllegalArgumentException("source is not found");
        }
        try {
            return (TrieTree<Icd>) CacheUtil.getInstance().get(key, () -> getIcdTrieTree(hospitalId));
        } catch (ExecutionException e) {
            logger.error("DrugSrv#getIcdTrieTreeFromCache(hospitalId={} ):\n {}", hospitalId, e.getMessage(), e);
        }
        return new TrieTree<>();
    }

    /**
     * 获取国际疾病分类，按首字母拼音构建的Trie Tree
     */
    public TrieTree<Icd> getIcdTrieTree(int hospitalId) {
        try {
            TrieTree<Icd> trieTree = new TrieTree<>();
            List<Icd> lst = getIcdListFromCache(hospitalId);
            if (lst == null || lst.size() == 0) {
                return trieTree;
            }
            for (Icd code : lst) {
                trieTree.insert(code.getPyCode().toUpperCase(), code);
            }
            return trieTree;
        } catch (Exception e) {
            logger.error("DrugSrv#getIcdTrieTree(hospitalId={} ):\n {}", hospitalId, e.getMessage(), e);
        }

        return new TrieTree<>();
    }

    /**
     * 获取国际疾病分类
     *
     * @return
     */
    public List<Icd> getIcdListFromCache(int hospitalId) {
        try {
            String key = null;
            switch (hospitalId) {
                case Constant.TAIHE_HOSPITAL_ID:
                    //太和诊断结果
                    key = TH_ICD_LIST_KEY;
                    break;
                case Constant.NFYYBYFY_HOSPITAL_ID:
                    key = NFYYBYFY_ICD_LIST_KEY;
                    break;
                default:
                    throw new IllegalArgumentException("source is not found");
            }
            return (List<Icd>) CacheUtil.getInstance().get(key, () -> getIcdList(hospitalId));
        } catch (Exception e) {
            logger.error("DrugSrv#getIcdListFromCache(hospitalId={} ):\n {}", hospitalId, e.getMessage(), e);
        }
        return new LinkedList<>();
    }

    /**
     * 获取国际疾病分类
     *
     * @return
     */
    public List<Icd> getIcdList(int hospitalId) {
        try {
            GetIcdListRequest req = GetIcdListRequest.newBuilder().setHospitalId(hospitalId).build();
            GetIcdListResponse res = drugServiceBlockingStub.getIcdList(req);
            logger.info("===================>DrugSrv#getIcdList(): Fetch from api");
            if (res.getCode() == ResultCode.SUCCEED_VALUE) {
                return res.getIcdList();
            }
        } catch (Exception e) {
            logger.error("getIcdCodeList(): {}", e.getMessage(), e);
        }
        return new LinkedList<>();
    }

    public ServiceResult validateDrugInfo(DrugInfo drugInfo) {
        ServiceResult result = new ServiceResult();
        if (drugInfo == null) return result.failed("drugInfo 不能为空");
        String drugName = Checker.getStringValue(drugInfo.getDrugName());
        if (Checker.isNone(drugInfo.getUsage())) return result.failed(String.format("药品%s用法不能为空", drugName));
        if (Checker.isNone(drugInfo.getUsageCode())) return result.failed(String.format("药品%s用法编码不能为空", drugName));
        if (Checker.isNone(drugInfo.getFrequency())) return result.failed(String.format("药品%s频率不能为空", drugName));
        if (Checker.isNone(drugInfo.getFrequencyCode())) return result.failed(String.format("药品%s频率编码不能为空", drugName));
        if (Checker.getIntegerValue(drugInfo.getDays()) <= 0)
            return result.failed(String.format("药品%s使用天数不能小于或等于 0", drugName));
        return result.succeed();
    }
}
