package thyyxxk.webserver.service.heliyongyao;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import thyyxxk.webserver.config.exception.BizException;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.Capacity;
import thyyxxk.webserver.dao.his.heliyongyao.RationalUseDao;
import thyyxxk.webserver.dao.his.zhuyuanyisheng.YiZhuLuRuDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.heliyongyao.RationalUsePatient;
import thyyxxk.webserver.entity.heliyongyao.XunHuanJieDian;
import thyyxxk.webserver.entity.heliyongyao.YaoPin;
import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.XinZhenYiZhu;
import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.XinZhenYzActOrder;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.service.externalhttp.RationalUseSrvc;
import thyyxxk.webserver.utils.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 描述： 合理用药
 * </p>
 *
 * @author xc
 * @date 2022-03-29 11:27
 */
@Service
@Slf4j
public class RationalUseServer {

    private final RationalUseDao dao;
    private final RationalUseSrvc http;
    private final YiZhuLuRuDao yiZhuLuRuDao;
    private final PublicServer publicServer;

    public RationalUseServer(RationalUseDao dao, RationalUseSrvc http, YiZhuLuRuDao yiZhuLuRuDao, PublicServer publicServer) {
        this.dao = dao;
        this.http = http;
        this.yiZhuLuRuDao = yiZhuLuRuDao;
        this.publicServer = publicServer;
    }

    public ResultVo<JSONObject> jiaoYan(XinZhenYiZhu param) {
        log.info("数据：{}", JSON.toJSONString(param));
        String userCode = "99999".equals(TokenUtil.getTokenUserId()) ? param.getUserCode() : TokenUtil.getTokenUserId();
        // 医生信息
        Map<String, String> doctMap = yiShenXinXi(userCode);
        String baseXml = doctMap.get("baseXml");
        String doct = doctMap.get("doct");
        List<XinZhenYzActOrder> yp = new ArrayList<>();
        QueryWrapper<?> qw = new QueryWrapper<>();
        List<String> yaoPinBianMa = new ArrayList<>();
        for (XinZhenYzActOrder item : param.getList()) {
            if (StringUtil.notBlank(item.getSerial())) {
                if (!"00".equals(item.getSerial())) {
                    yp.add(item);
                    String key = item.getOrderCode().trim() + item.getSerial().trim();
                    if (!yaoPinBianMa.contains(key)) {
                        yaoPinBianMa.add(key);
                    }
                }
            }
        }
        qw.in("rtrim(code) + rtrim(serial)", yaoPinBianMa);
        Map<String, YaoPin> yaoPinMap = dao.yaoPingXinXi(qw).stream().collect(
                Collectors.toMap(YaoPin::getId, a -> a, (k1, k2) -> k1)
        );
        String detailsXml = yaoPinXinXi(param.getInpatientNo(), param.getAdmissTimes(), param.getCfType(), yp, doct, yaoPinMap);
        String js = String.format("{\"BaseXml\": \"%s\", \"DetailsXml\" : \"%s\"}", baseXml, detailsXml);
        log.info("上传数据：{} ", js);
        try {
            JSONObject fanHuiXinXi = http.rationalUse(js);
            log.info("返回的数据:{}", fanHuiXinXi);
            return ResultVoUtil.success(fanHuiXinXi);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "网络错误");
        }
    }

    public Map<String, String> yiShenXinXi(String code) {
        Map<String, String> yiShenXinXi = dao.yiShenXinXi(code);
        if (yiShenXinXi == null || yiShenXinXi.isEmpty()) {
            yiShenXinXi = new HashMap<>(Capacity.TWO);
        }

        Map<String, String> map = new HashMap<>(Capacity.TWO);

        String baseXml = "<base_xml>" +
                "<source>HIS</source>" +
                "<hosp_code>H43010500370</hosp_code>" +
                "<hosp_name>湖南泰和医院</hosp_name>" +
                "<dept_code>" + nullToBlank(yiShenXinXi.get("dept_code")) + "</dept_code>" +
                "<dept_name>" + nullToBlank(yiShenXinXi.get("dept_name")) + "</dept_name>" +
                "<doct>" +
                "<code>" + nullToBlank(yiShenXinXi.get("code")) + "</code>" +
                "<name>" + nullToBlank(yiShenXinXi.get("name")) + "</name>" +
                "<type>" + nullToBlank(yiShenXinXi.get("type")) + "</type>" +
                "<type_name>" + nullToBlank(yiShenXinXi.get("type_name")) + "</type_name>" +
                "</doct>" +
                "</base_xml>";
        map.put("baseXml", baseXml);
        String sb = "<dept_code>" + nullToBlank(yiShenXinXi.get("dept_code")) + "</dept_code>" +
                "<dept_name>" + nullToBlank(yiShenXinXi.get("dept_name")) + "</dept_name>" +
                "<doct_code>" + nullToBlank(yiShenXinXi.get("code")) + "</doct_code>" +
                "<doct_name>" + nullToBlank(yiShenXinXi.get("name")) + "</doct_name>";
        map.put("doct", sb);
        return map;
    }

    public String nullToBlank(String str) {
        if (StringUtil.isBlank(str)) {
            return "";
        }
        return str.trim();
    }

    public String yaoPinXinXi(String patNo,
                              Integer times,
                              String cfType,
                              List<XinZhenYzActOrder> yaoPinShuZu,
                              String doct,
                              Map<String, YaoPin> yaoPinMap) {
        log.info("数据:{}", JSON.toJSONString(yaoPinShuZu));
        StringBuilder sb = new StringBuilder();
        RationalUsePatient patient = dao.huanZheXinXi(patNo, times);
        if (patient == null) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "没有找到对应患者的信息。");
        }
        XinZhenYiZhu patient1 = yiZhuLuRuDao.huoQuHuanZheXinXi(patNo, times);
        // 中西药处方/医嘱类型标识
        // 就诊类型
        // 就诊号
        sb.append("<details_xml>")
                .append("<hosp_code>H43010500370</hosp_code>")
                .append("<his_time>").append(DateUtil.formatDatetime(new Date())).append("</his_time>")
                .append("<hosp_flag>ip</hosp_flag>")
                // 中西药处方/医嘱类型标识
                .append("<cf_type>").append(cfType).append("</cf_type>")
                // 就诊类型
                .append("<treat_type>").append("400").append("</treat_type>")
                // 就诊号
                .append("<treat_code>").append(patNo).append("_").append(times).append(DateUtil.formatDatetime(new Date(), "YYYYMMDD")).append("</treat_code>")
                .append("<is_repeat>").append("1").append("</is_repeat>")
                .append("<bed_no>").append(nullToBlank(patient1.getBedNo())).append("</bed_no>")
                .append("<patient>")
                .append("<pati_id>").append(patNo).append("_").append(times).append("</pati_id>")
                .append("<name>").append(nullToBlank(patient.getName())).append("</name>")
                .append("<is_infant>").append(publicServer.getInfantFlag(patNo)).append("</is_infant>")
                .append("<birth>").append(nullToBlank(patient.getBirth())).append("</birth>")
                .append("<sex>").append(nullToBlank(patient.getSex())).append("</sex>")
                .append("<weight>").append("").append("</weight>")
                .append("<height>").append("").append("</height>")
                .append("<id_card>").append(patient.getIdCard()).append("</id_card>")
                .append("<medical_record>").append("").append("</medical_record>")
                .append("<card_type>").append("").append("</card_type>")
                .append("<card_code>").append("").append("</card_code>")
                .append("<pregnant_unit>").append("").append("</pregnant_unit>")
                .append("<pregnant>").append("").append("</pregnant>");
        //  过敏节点，可循环
        sb.append("<allergic_data>");

        List<XunHuanJieDian> guoMinShuZu = dao.guoMin(patNo);
        xunHuanJieDian(sb, guoMinShuZu, "allergic");
        sb.append("</allergic_data>");
        // 皮试节点，可循环
        sb.append("<skintest_data>");
        List<XunHuanJieDian> piShiShuZu = new ArrayList<>();
        if (ListUtil.isBlank(piShiShuZu)) {
            XunHuanJieDian piShi = new XunHuanJieDian();
            piShi.setCode("").setName("").setResult("");
            piShiShuZu.add(piShi);
        }
        for (XunHuanJieDian item : piShiShuZu) {
            sb.append("<skintest>")
                    .append("<name>").append(nullToBlank(item.getName())).append("</name>")
                    .append("<code>").append(nullToBlank(item.getCode())).append("</code>")
                    .append("<result>").append(nullToBlank(item.getResult())).append("</result>")
                    .append("</skintest>");
        }
        sb.append("</skintest_data>");
        // 诊断
        sb.append("<diagnose_data>");

        List<XunHuanJieDian> zhenDuanShuJu = dao.zhenDuan(patNo, times);
        // 诊断节点
        xunHuanJieDian(sb, zhenDuanShuJu, "diagnose");
        sb.append("</diagnose_data>")
                .append("</patient>");

        // 处方信息
        sb.append("<prescription_data>")
                .append("<prescription>")
                .append("<id>").append("0").append("</id>")
                .append("<reason>").append("").append("</reason>")
                .append("<is_current>").append("1").append("</is_current>")
                .append("<pres_type>").append("T").append("</pres_type>")
                .append("<pres_time>").append(DateUtil.formatDatetime(new Date())).append("</pres_time>")
                // 药品信息节点，可循环
                .append("<medicine_data>");
        for (XinZhenYzActOrder item : yaoPinShuZu) {
            YaoPin yp = yaoPinMap.get(item.getOrderCode().trim() + item.getSerial().trim());
            if (null == yp) {
                yp = new YaoPin();
                yp.setPackRetprice(BigDecimal.valueOf(1));
            }
            item.setRationalDrugUseId(SnowFlakeId.instance().nextId());
            // 因为我要入库才能生成医嘱号所以这里用雪花算法
            sb.append("<medicine>")
                    .append("<cf_id>").append("0").append("</cf_id>")
                    // 因为我要入库才能生成医嘱号所以这里用雪花算法
                    .append("<oeridid>").append(item.getRationalDrugUseId()).append("</oeridid>")
                    .append("<is_current>").append("1").append("</is_current>")
                    .append("<pres_type>").append("ONCE".equals(item.getFrequCode()) ? "T" : "L").append("</pres_type>")
                    .append("<pres_time>").append(DateUtil.formatDatetime(item.getOrderTime())).append("</pres_time>")
                    .append("<name>").append(item.getOrderName()).append("</name>")
                    .append("<his_code>").append(nullToBlank(item.getOrderCode() + "_" + item.getSerial())).append("</his_code>")
                    .append("<insur_code>").append(nullToBlank(yp.getNationalCode())).append("</insur_code>")
                    .append("<approval>").append(nullToBlank(yp.getPzwh())).append("</approval>")
                    .append("<spec>").append(nullToBlank(item.getDrugSpecification())).append("</spec>")
                    .append("<quantity>").append(nullToBlank(item.getDrugQuan() + item.getMiniUnitName())).append("</quantity>")
                    .append("<group>").append(publicServer.getGroupNo()).append("</group>")
                    .append("<reason>").append("").append("</reason>")
                    .append("<dose_unit>").append(nullToBlank(item.getDoseUnitName())).append("</dose_unit>")
                    .append("<dose>").append(item.getDose()).append("</dose>")
                    .append("<kyzl>").append("").append("</kyzl>")
                    .append("<zl_unit>").append("").append("</zl_unit>")
                    .append("<freq>").append("ZY").append(nullToBlank(item.getFrequCode())).append("</freq>")
                    .append("<administer>").append("ZY").append(item.getSupplyCode()).append("</administer>")
                    .append("<begin_time>").append(DateUtil.formatDatetime(item.getStartTime())).append("</begin_time>")
                    .append("<end_time>").append(DateUtil.formatDatetime(item.getEndTime())).append("</end_time>")
                    .append("<days>").append("").append("</days>")
                    .append(doct)
                    .append("<PREVENTIVE_TYPE>").append("2").append("</PREVENTIVE_TYPE>")
                    .append("<money>").append(yp.getPackRetprice().multiply(item.getDrugQuan())).append("</money>")
                    .append("</medicine>");
        }
        sb.append("</medicine_data></prescription></prescription_data></details_xml>");
        return sb.toString();
    }

    public void xunHuanJieDian(StringBuilder sb, List<XunHuanJieDian> jieDian, String name) {
        if (ListUtil.isBlank(jieDian)) {
            XunHuanJieDian zhenDuan = new XunHuanJieDian();
            zhenDuan.setType("").setCode("").setName("");
            jieDian.add(zhenDuan);
        }

        for (XunHuanJieDian item : jieDian) {
            sb.append("<").append(name).append(">").
                    append("<type>").append(nullToBlank(item.getType())).append("</type>")
                    .append("<name>").append(nullToBlank(item.getName())).append("</name>")
                    .append("<code>").append(nullToBlank(item.getCode())).append("</code>")
                    .append("</").append(name).append(">");
        }
    }
}
