package com.lantone.qc.kernel.web.controller;

import com.google.common.collect.Lists;
import com.lantone.qc.kernel.analysis.QCAnalysis;
import com.lantone.qc.kernel.util.CacheFileManager;
import com.lantone.qc.dbanaly.util.KernelConstants;
import com.lantone.qc.pub.jdbc.MysqlJdbc;
import com.lantone.qc.pub.model.OutputInfo;
import com.lantone.qc.pub.model.vo.MedrecVo;
import com.lantone.qc.pub.model.vo.QueryVo;
import com.lantone.qc.pub.res.Response;
import com.lantone.qc.pub.util.FastJsonUtils;
import com.lantone.qc.pub.util.PropertiesUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;

/**
 * @ClassName : QCTestController
 * @Description : 测试
 * @Author : 楼辉荣
 * @Date: 2020-03-11 16:03
 */
@Api(value = "质控测试接口", tags = { "质控测试接口" })
@RestController
@RequestMapping(value = "test")
public class QCTestController {
    @Autowired
    private QCAnalysis qCAnalysis;

    private Map<String, List<String>> inputLabelMap = new HashMap<>();

    {
        inputLabelMap.put("入院记录", Lists.newArrayList("姓名", "性别", "年龄", "民族", "职业", "出生地", "婚姻", "联系地址", "病史陈述者", "出生日期", "户口地址", "电话", "入院日期", "记录日期", "主诉", "现病史", "既往史", "个人史", "婚育史", "月经史", "家族史", "体格检查（一）", "体格检查（二）", "辅助检查", "初步诊断", "修正诊断", "医师签名", "补充诊断"));
    }

    @ApiOperation(value = "质控测试接口，无需token信息", notes = "")
    @PostMapping("qc_test")
    public Response<OutputInfo> qc(String cid, String caseNumber, String hospitalId) throws Exception {
        Response response = new Response();
        if (StringUtils.isEmpty(hospitalId)) {
            response.setData("未填写医院流水号（hospitalId）......");
        }
        if (StringUtils.isEmpty(cid)) {
            response.setData("未填写医院缩写（cid）......");
        }
        //key = 患者就诊号
        Map<String, QueryVo> queryVoMap = createQueryVo(cid, hospitalId, caseNumber);
//        ModelDataUtil modelDataUtil = new ModelDataUtil();
        //key = 患者就诊号
        Map<String, Map<String, String>> inputCaseMappingMap = createInputCaseMapping(hospitalId, caseNumber);

        List<Map<String, Object>> updates = new ArrayList<>();
        List<Map<String, Object>> wheres = new ArrayList<>();
//        modelDataUtil.truncateDB("qc_model_input_info");//清空表
        for (Map.Entry<String, QueryVo> entry : queryVoMap.entrySet()) {
            System.out.println("患者就诊号：" + entry.getKey() + "..........");
//            modelDataUtil.executor(entry.getKey(), entry.getValue());//AI所需模块数据存入DB
            long start = System.currentTimeMillis();
            OutputInfo outputInfo = qCAnalysis.anlysis(entry.getValue());
            System.out.println("耗时......." + (System.currentTimeMillis() - start));
            Map<String, String> passMap = inputCaseMappingMap.get(entry.getKey());
            if (passMap != null) {
                for (Map.Entry<String, String> e : passMap.entrySet()) {
                    Map<String, Object> m = new HashMap<>();
                    Map<String, Object> w = new HashMap<>();
                    if (outputInfo.getResult().get(e.getKey()) != null) {
                        m.put("check_label", outputInfo.getResult().get(e.getKey()).get("status"));
                    } else {
                        m.put("check_label", "0");
                    }
                    w.put("id", e.getValue());

                    updates.add(m);
                    wheres.add(w);
                }
            }
        }
        PropertiesUtil propertiesUtil = new PropertiesUtil("kernel.properties");
        MysqlJdbc mysqlJdbc = new MysqlJdbc(propertiesUtil.getProperty("mysql.test.user"),
                propertiesUtil.getProperty("mysql.test.password"),
                propertiesUtil.getProperty("mysql.test.url"));
        if(caseNumber == null){
            mysqlJdbc.update("update qc_inputcases_mapping_all set check_label=null");
        }
        mysqlJdbc.update("qc_inputcases_mapping_all", updates, wheres);
        return response;
    }


    @ApiOperation(value = "质控单个病历测试，无需token信息", notes = "")
    @PostMapping("qc_test_single")
    public Response<OutputInfo> qc_test_single(String cid, String caseNumber, String hospitalId) throws Exception {
        Response response = new Response();
        if (StringUtils.isEmpty(hospitalId)) {
            response.setData("未填写医院流水号（hospitalId）......");
        }
        if (StringUtils.isEmpty(cid)) {
            response.setData("未填写医院缩写（cid）......");
        }
        //key = 患者就诊号
        Map<String, QueryVo> queryVoMap = createQueryVo(cid, hospitalId, caseNumber);
        //key = 患者就诊号
        OutputInfo outputInfo = qCAnalysis.anlysis(queryVoMap.get(caseNumber));
        response.setData(outputInfo);
        return response.success();
    }


    public Map<String, QueryVo> createQueryVo(String cid, String hospitalId, String caseNumber) {
        PropertiesUtil propertiesUtil = new PropertiesUtil("kernel.properties");
        MysqlJdbc mysqlJdbc = new MysqlJdbc(propertiesUtil.getProperty("mysql.test.user"),
                propertiesUtil.getProperty("mysql.test.password"),
                propertiesUtil.getProperty("mysql.test.url"));
        Connection conn = mysqlJdbc.connect();
        Statement st = null;
        ResultSet rs = null;
        String r1, r2, r3, r4, r5;

        Map<String, QueryVo> queryVoMap = new HashMap<>();
        QueryVo queryVo = new QueryVo();
        List<MedrecVo> medrec = new ArrayList<>();
        try {
            st = conn.createStatement();
            String sql = "select case_number from qc_cases_number where hospital_id = " + hospitalId;   //查询医院所有病历号
            rs = st.executeQuery(sql);
            List<String> numbers = new ArrayList<>();
            while (rs.next()) {
                r1 = rs.getString(1);
                numbers.add(r1);
            }

            sql = "select id from qc_mode";   //查询数据模块
            rs = st.executeQuery(sql);
            List<String> modeIds = new ArrayList<>();
            while (rs.next()) {
                r1 = rs.getString(1);
                modeIds.add(r1);
            }

            sql = "select code, name, precond from qc_cases_entry q1, qc_cases_entry_hospital q2 where q1.id = q2.cases_entry_id and q2.is_used = 1 ";   //查询所有条目
            if (StringUtils.isNotEmpty(hospitalId)) {
                sql = sql + " and q2.hospital_id = " + hospitalId;
            }
            rs = st.executeQuery(sql);
            Map<String, Map<String, String>> inputCatalogueMap = new HashMap<>();
            while (rs.next()) {
                r1 = rs.getString(1);
                r2 = rs.getString(2);
                r3 = rs.getString(3);
                Map<String, String> m = new HashMap<>();
                m.put("precond", r3);
                m.put("name", r2);
                m.put("code", r1);
                inputCatalogueMap.put(r1, m);
            }

            sql = "SELECT h.code, n.case_number, q.name, qmm.origin_text " +
                    "FROM qc_model_mapping qmm, qc_mode q, qc_cases_number n, qc_hospital_info h " +
                    "where qmm.case_number_id = n.id and qmm.mode_id = q.id and n.hospital_id = h.id and n.is_deleted = 'N' ";
            if (StringUtils.isNotEmpty(caseNumber)) {
                sql = sql + " and n.case_number = '" + caseNumber + "'";
            }
            if (StringUtils.isNotEmpty(hospitalId)) {
                sql = sql + " and n.hospital_id = " + hospitalId;
            }
            sql = sql + " and qmm.case_number_id in (select distinct case_number_id from qc_inputcases_mapping_all) ";
            sql = sql + " order by n.id, q.id";
            rs = st.executeQuery(sql);
            String tempCaseNumber = "", label = "";
            List<String> details = new ArrayList<>();
            while (rs.next()) {
                r1 = rs.getString(1);
                r2 = rs.getString(2);
                r3 = rs.getString(3);
                r4 = rs.getString(4);

                if (!tempCaseNumber.equals(String.valueOf(r2)) && StringUtils.isNotEmpty(tempCaseNumber)) {
                    queryVo.setCid(cid);
                    queryVo.setMedrec(medrec);
                    queryVo.setInputCatalogueMap(inputCatalogueMap);
                    queryVoMap.put(r2, queryVo);
                    //新的一份病历记录
                    medrec = new ArrayList<>();
                    queryVo = new QueryVo();
                }
                if (label.equals("病案首页") && !label.equals(String.valueOf(r3)) && StringUtils.isNotEmpty(label)) {
                    MedrecVo medrecVo = new MedrecVo();
                    medrecVo.setTitle(label);
                    String jsonString = details.get(0);
//                    if ("1".equals(hospitalId)) {
                        medrecVo.setContent(FastJsonUtils.getJsonToMap(jsonString));
//                    } else {
//                        Map<String, Object> m = new HashMap<>();
//                        m.put("content", details);
//                        medrecVo.setContent(m);
//                    }
                    medrec.add(medrecVo);
                    details = new ArrayList<>();
                } else if (!label.equals(String.valueOf(r3)) && StringUtils.isNotEmpty(label) && (label.equals("会诊记录") || label.equals("会诊申请单") || label.equals("会诊结果单"))) {
                    MedrecVo medrecVo = createLevelMedrecVo(medrec, details, "会诊", label);
                    medrec.add(medrecVo);
                    details = new ArrayList<>();
                }  else if (!label.equals(String.valueOf(r3)) && StringUtils.isNotEmpty(label)
                        && (label.equals("术后首次病程及谈话记录") || label.equals("手术记录") || label.equals("术前讨论、术前小结") || label.equals("手术知情同意书") || label.equals("手术安全核查表"))) {
                    MedrecVo medrecVo = createLevelMedrecVo(medrec, details, "手术", label);
                    medrec.add(medrecVo);
                    details = new ArrayList<>();
                } else if (!label.equals(String.valueOf(r3)) && StringUtils.isNotEmpty(label)) {
                    MedrecVo medrecVo = new MedrecVo();
                    medrecVo.setTitle(label);
                    Map<String, Object> m = new HashMap<>();
                    m.put("content", details);
                    medrecVo.setContent(m);
                    medrec.add(medrecVo);
                    details = new ArrayList<>();
                }
                details.add(r4);
                label = r3;
                tempCaseNumber = r2;
            }

            //最后一条记录
            if (label.equals("术后首次病程及谈话记录") || label.equals("手术记录") || label.equals("术前讨论、术前小结") || label.equals("手术知情同意书") || label.equals("手术安全核查表")) {
                MedrecVo medrecVo = createLevelMedrecVo(medrec, details, "手术", label);
                medrec.add(medrecVo);
            } else if (label.equals("会诊记录") || label.equals("会诊申请单") || label.equals("会诊结果单")) {
                MedrecVo medrecVo = createLevelMedrecVo(medrec, details, "会诊", label);
                medrec.add(medrecVo);
            } else {
                MedrecVo medrecVo = new MedrecVo();
                medrecVo.setTitle(label);
                Map<String, Object> m = new HashMap<>();
                m.put("content", details);
                medrecVo.setContent(m);
                medrec.add(medrecVo);
            }

            queryVo.setCid(cid);
            queryVo.setMedrec(medrec);
            queryVo.setInputCatalogueMap(inputCatalogueMap);
            queryVoMap.put(tempCaseNumber, queryVo);

        } catch (SQLException sqle) {
            sqle.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            mysqlJdbc.close(rs, st, conn);
        }
        return queryVoMap;
    }

    private MedrecVo createLevelMedrecVo(List<MedrecVo> medrec, List<String> details, String label, String level_1) {
        MedrecVo medrecVo = null;
        for (MedrecVo mv : medrec) {
            if (label.equals(mv.getTitle())) {
                medrecVo = mv;
            }
        }
        Map<String, List<String>> m = null;
        if (medrecVo == null) {
            m = new HashMap<>();
            medrecVo = new MedrecVo();
            medrecVo.setTitle(label);
        } else {
            m = (Map) medrecVo.getContent().get("content");
        }
        m.put(level_1, details);
        Map<String, Object> cur = new HashMap<>();
        cur.put("content", m);
        medrecVo.setContent(cur);
        return medrecVo;
    }

    public int number(List<String> labels,String lab){
        int initNume = 0;
        if(labels != null && labels.size()>0){
            for (String label:labels) {
                if(label.equals(lab)){
                    initNume++;
                }
            }
        }
        return initNume;
    }
    public Map<String, Map<String, String>> createInputCaseMapping(String hospitalId, String caseNumber) {
        Map<String, Map<String, String>> result = new HashMap<>();
        PropertiesUtil propertiesUtil = new PropertiesUtil("kernel.properties");
        MysqlJdbc mysqlJdbc = new MysqlJdbc(propertiesUtil.getProperty("mysql.test.user"),
                propertiesUtil.getProperty("mysql.test.password"),
                propertiesUtil.getProperty("mysql.test.url"));
        Connection conn = mysqlJdbc.connect();
        Statement st = null;
        ResultSet rs = null;
        String r1, r2, r3, r4, r5;
        try {
            st = conn.createStatement();
            String sql = "SELECT qim.id, q.case_number, qc.code FROM qc_inputcases_mapping_all qim, qc_cases_number q, qc_cases_entry qc, qc_cases_entry_hospital h " +
                    "where qim.case_number_id = q.id and qim.cases_entry_id = qc.id and qc.id = h.cases_entry_id and q.hospital_id = h.hospital_id and q.is_deleted = 'N' and h.is_used = 1 " +
                    "and q.hospital_id = " + hospitalId;
            if (StringUtils.isNotEmpty(caseNumber)) {
                sql = sql + " and q.case_number = '" + caseNumber + "' ";
            }
            sql = sql + " order by q.id, qim.cases_id ";
            rs = st.executeQuery(sql);

            String caseNumberId = "";
            Map<String, String> m = new HashMap<>();
            while (rs.next()) {
                r1 = rs.getString(1);
                r2 = rs.getString(2);
                r3 = rs.getString(3);
                if (!caseNumberId.equals(String.valueOf(r2)) && StringUtils.isNotEmpty(caseNumberId)) {
                    result.put(r2, m);
                    m = new HashMap<>();
                }
                m.put(r3, r1);
                caseNumberId = r2;
            }
            result.put(caseNumberId, m);
        } catch (SQLException sqle) {
            sqle.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            mysqlJdbc.close(rs, st, conn);
        }
        return result;
    }

    @ApiOperation(value = "质控测试接口，无需token信息", notes = "")
    @PostMapping("rec_test")
    public Response<OutputInfo> extract(String caseIds, int length, String cid, String txtId, String hospitalId) {
        Response response = new Response();
        PropertiesUtil propertiesUtil = new PropertiesUtil("kernel.properties");

        MysqlJdbc mysqlJdbc = new MysqlJdbc(propertiesUtil.getProperty("mysql.test.user"),
                propertiesUtil.getProperty("mysql.test.password"),
                propertiesUtil.getProperty("mysql.test.url"));
        Connection conn = mysqlJdbc.connect();
        Statement st = null;
        ResultSet rs = null;
        String r1, r2, r3, r4, r5;
        List<Map<String, Object>> updates = new ArrayList<>();
        List<Map<String, Object>> wheres = new ArrayList<>();
        try {
            String textSql = "select id, text from qc_inputcases where 1 = 1 ";
            if (StringUtils.isNotEmpty(txtId)) {
                textSql = textSql + " and id >= " + txtId;
            }
            if (StringUtils.isNotEmpty(hospitalId)) {
                textSql = textSql + " and hospital_id = " + hospitalId;
            }
            textSql = textSql + " order by id limit 0, " + length;
            //更新pass状态
            mysqlJdbc.update("update qc_inputcases_mapping_all qim, " +
                    "(" + textSql + ") qi\n" +
                    "set qim.check_label = 0 where qim.text_id = qi.id");

            st = conn.createStatement();
            //测试数据查询
            String sql = "SELECT qmap.id, qi.id text_id, qi.text, ca.name, entry.code FROM " +
                    "qc_inputcases_mapping_all qmap, (" + textSql + ") qi, qc_cases_entry entry, qc_cases ca " +
                    "where qmap.text_id = qi.id and qmap.cases_entry_id = entry.id and entry.cases_id = ca.id and qmap.is_deleted = 'N' ";

            if (StringUtils.isNotEmpty(caseIds)) {
                sql = sql + " and entry.cases_id in (" + caseIds + ")";
            }

            sql = sql + " order by qi.id, entry.code";

            Map<String, String> map = new HashMap<>();
            rs = st.executeQuery(sql);
            //条目数据结构， Key = 条目Code value = 条目属性{"precode":"BEH0002,BEH0003","title":"症状缺少时间描述"}
            Map<String, Map<String, String>> catalogueMap = new HashMap<>();
            //测试条目编码和qc_inputcases_mapping_all 的id，为了更新每个条目是否验证通过
            Map<String, String> updateMap = new HashMap<>();

            List<Map<String, Map<String, String>>> catalogueList = new ArrayList<>();
            List<String> textList = new ArrayList<>();
            List<String> caseList = new ArrayList<>();
            List<Map<String, String>> updateList = new ArrayList<>();
            List<String> textIdList = new ArrayList<>();
            String textId = "";
            int index = 0;
            String text = "";
            String caseName = "";
            while (rs.next()) {
                r1 = rs.getString(1);
                r2 = rs.getString(2);
                r3 = rs.getString(3);
                r4 = rs.getString(4);
                r5 = rs.getString(5);
                if (!textId.equals(String.valueOf(r2))) {
                    if (StringUtils.isNotEmpty(textId)) {
                        catalogueList.add(catalogueMap);
                        updateList.add(updateMap);
                        textList.add(text);
                        caseList.add(caseName);
                        textIdList.add(textId);

                        catalogueMap = new HashMap<>();
                        updateMap = new HashMap<>();
                    }
                    catalogueMap = new HashMap<>();
                }
                catalogueMap.put(r5, new HashMap<>());
                updateMap.put(r5, r1);
                textId = r2;
                text = r3;
                caseName = r4;
            }
            //最后一份病历无法在循环中写入 需要填回
            if (StringUtils.isNotEmpty(textId)) {
                catalogueList.add(catalogueMap);
                updateList.add(updateMap);
                textList.add(text);
                caseList.add(caseName);
                textIdList.add(textId);
            }

            for (int i = 0; i < textList.size(); i++) {
                System.out.println("**************************" + textIdList.get(i));
                MedrecVo medrecVo = new MedrecVo();
                medrecVo.setTitle(caseList.get(i));
                Map<String, Object> content = new HashMap<>();
                content.put("content", textList.get(i));
                medrecVo.setContent(content);
                if (caseList.get(i).equals("入院记录")) {
                    medrecVo.setLabel(Lists.newArrayList("姓名", "性别", "年龄", "民族", "职业", "出生地", "婚姻", "联系地址", "病史陈述者", "出生日期", "户口地址", "电话", "入院日期", "记录日期", "主诉", "现病史", "既往史", "个人史", "婚育史", "月经史", "家族史", "体格检查（一）", "体格检查（二）", "辅助检查", "初步诊断", "修正诊断", "医师签名", "补充诊断"));
                }


                List<MedrecVo> medrec = new ArrayList<>();
                medrec.add(medrecVo);

                QueryVo queryVo = new QueryVo();
                queryVo.setMedrec(medrec);
                queryVo.setCid(cid);
                queryVo.setInputCatalogueMap(catalogueList.get(i));

                OutputInfo outputInfo = qCAnalysis.anlysis(queryVo);

                Map<String, String> catalogue_map = updateList.get(i);
                for (Map.Entry<String, String> entry : catalogue_map.entrySet()) {
                    Map<String, Object> m = new HashMap<>();
                    Map<String, Object> w = new HashMap<>();
                    if (outputInfo.getResult().get(entry.getKey()) == null) {
                        m.put("check_label", "-2");
                    } else {
                        m.put("check_label", outputInfo.getResult().get(entry.getKey()).get("status"));
                    }
                    w.put("id", catalogue_map.get(entry.getKey()));

                    updates.add(m);
                    wheres.add(w);
                }
            }


            mysqlJdbc.update("qc_inputcases_mapping_all", updates, wheres);


            CacheFileManager cacheFileManager = new CacheFileManager();
            cacheFileManager.insertFeature(KernelConstants.clinicModificationList, "kl_modification", "name");
            cacheFileManager.insertFeature(KernelConstants.clinicNameList, "kl_clinic", "name");
            cacheFileManager.insertFeature(KernelConstants.hospitalDiagNameList, "kl_disease", "name");

        } catch (SQLException sqle) {
            sqle.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            mysqlJdbc.close(rs, st, conn);
        }
        return response;
    }
}