package cn.sh.stc.sict.theme.hphy.wd;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.HttpRequest;
import cn.sh.stc.sict.cloud.common.core.constant.Constant;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import javax.xml.xpath.XPathConstants;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@UtilityClass
public class WanDaHttpUtil {
    String URL = "http://173.18.1.29:7001/yyzlWS/webservice/ss";
    String CODE_XPATH = "//Response/MessageHeader/code";

    /**
     * 调用万达 webservice 接口获取医院信息
     *
     * @param hospInfo
     * @return
     */
    public List<HosInfo> getHospitalInfo(HosInfo hospInfo) {
        String xml = WanDaUtil.GetHospitalInfoServiceXML(hospInfo);
        System.out.println(xml);
        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("获取医院信息失败");
            return null;
        }
        log.info("获取医院信息：body = {}", body);
        String returnStr = getReturn(body, "GetHospitalInfoService");
        if (StrUtil.isNotBlank(returnStr)) {
            if (Constant.STRING_NO.equals(getCode(returnStr))) {
                Document document = XmlUtil.readXML(returnStr);
                NodeList nodeList = document.getElementsByTagName("HosInfo");
                List<HosInfo> list = new ArrayList<>();
                if (null != nodeList && nodeList.getLength() > 0) {
                    for (int i = 0; i < nodeList.getLength(); i++) {
                        list.add(XmlUtil.xmlToBean(nodeList.item(i), HosInfo.class));
                    }
                }
                return list;
            }
        }
        return null;
    }

    /**
     * 调用万达 webservice 接口获取一级科室信息
     *
     * @param hospInfo
     * @return
     */
    public List<DeptInfo> getDeptInfoTop(HosInfo hospInfo) {
        String xml = WanDaUtil.GetDeptInfoTopServiceXML(hospInfo);

        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("获取一级科室信息失败");
            return null;
        }
        log.info("获取一级科室信息：body = {}", body);
        String returnXml = getReturn(body, "GetDeptInfoTopService");
        return serialDeptInfos(returnXml);
    }

    /**
     * 调用万达 webservice 接口获取二级科室信息
     *
     * @param deptInfo
     * @return
     */
    public List<DeptInfo> getDeptInfoTwo(DeptInfo deptInfo) {
        String xml = WanDaUtil.GetDeptInfoTwoServiceXML(deptInfo);

        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("获取二级科室信息失败");
            return null;
        }
        log.info("获取二级科室信息：body = {}", body);
        String returnXml = getReturn(body, "GetDeptInfoTwoService");
        return serialDeptInfos(returnXml);
    }

    /**
     * 获取医生信息
     *
     * @param deptInfo
     * @return
     */
    public List<DoctInfo> getDoctInfo(DeptInfo deptInfo) {
        String xml = WanDaUtil.GetDoctInfoServiceXML(deptInfo);

        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("获取医生信息失败");
            return null;
        }
        log.info("获取医生信息：body = {}", body);
        String returnXml = getReturn(body, "GetDoctInfoService");
        return serialDoctInfo(returnXml);
    }

    /**
     * 查询门诊信息(所有)
     *
     * @param deptInfo
     * @return
     */
    public List<OutPatInfo> getOutPatInfo(DeptInfo deptInfo) {
        String xml = WanDaUtil.GetOutPatInfoServiceXML(deptInfo);
        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("查询门诊信息失败");
            return null;
        }
        log.info("查询门诊信息：body = {}", body);
        String returnXml = getReturn(body, "GetOutPatInfoService");
        return serialOutPatInfo(returnXml);
    }

    /**
     * 号源查询
     *
     * @param numSourceInfo
     * @return
     */
    public List<NumSourceInfo> getOrderNumInfo(NumSourceInfo numSourceInfo) {
        String xml = WanDaUtil.GetOrderNumInfoServiceXML(numSourceInfo);
        System.out.println(xml);
        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("号源查询 失败");
            return null;
        }
        log.info("号源查询：body = {}", body);
        String returnXml = getReturn(body, "GetOrderNumInfoService");
        if (Constant.STRING_NO.equals(getCode(returnXml))) {
            Document document = XmlUtil.readXML(returnXml);
            NodeList nodeList = document.getElementsByTagName("NumSourceInfo");
            List<NumSourceInfo> list = new ArrayList<>();
            if (null != nodeList && nodeList.getLength() > 0) {
                for (int i = 0; i < nodeList.getLength(); i++) {
                    list.add(XmlUtil.xmlToBean(nodeList.item(i), NumSourceInfo.class));
                }
            }
            return list;
        } else {
            return null;
        }
    }


    /**
     * 号源预约
     *
     * @param orderInfo
     * @return
     */
    public AppResult submitOrderByUserInfo(OrderInfo orderInfo) {
        String xml = WanDaUtil.SubmitOrderByUserInfoServiceXML(orderInfo);

        log.error("预约xml = {}", xml);
        String body = "";
        // TODO 测试环境
//        String body = HttpRequest.post(URL)
//                .body(xml)
//                .execute()
//                .body();

        if (StrUtil.isBlank(body)) {
            log.error("号源预约 失败");
            return null;
        }
        log.info("号源预约：body = {}", body);
        String returnXml = getReturn(body, "SubmitOrderByUserInfoService");
        if (Constant.STRING_NO.equals(getCode(returnXml))) {
            Document document = XmlUtil.readXML(returnXml);
            NodeList list = document.getElementsByTagName("OrderInfo");
            if (list.getLength() > 0) {
                return XmlUtil.xmlToBean(list.item(0), AppResult.class);
            }
        }
        return null;
    }

    /**
     * 取消预约
     *
     * @param cancelOrderInfo
     * @return
     */
    public boolean orderCancelInfo(CancelOrderInfo cancelOrderInfo) {
        String xml = WanDaUtil.OrderCancelInfoServiceXML(cancelOrderInfo);

        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("取消预约 失败");
            return false;
        }
        log.info("取消预约：body = {}", body);
        String returnXml = getReturn(body, "OrderCancelInfoService");
        if (Constant.STRING_NO.equals(getCode(returnXml))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 查询预约单列表
     *
     * @param orderInfo
     * @return
     */
    public List<OrderInfo> getOrderList(OrderInfo orderInfo) {
        String xml = WanDaUtil.GetOrderListServiceXML(orderInfo);

        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("查询预约单列表 失败");
            return null;
        }
        log.info("查询预约单列表：body = {}", body);
        String returnXml = getReturn(body, "GetOrderListService");
        if (Constant.STRING_NO.equals(getCode(returnXml))) {
            Document document = XmlUtil.readXML(returnXml);
            NodeList nodeList = document.getElementsByTagName("OrderInfo");
            List<OrderInfo> list = new ArrayList<>();
            if (null != nodeList && nodeList.getLength() > 0) {
                for (int i = 0; i < nodeList.getLength(); i++) {
                    list.add(XmlUtil.xmlToBean(nodeList.item(i), OrderInfo.class));
                }
            }
            return list;
        } else {
            return null;
        }
    }

    /**
     * 查询预约单详细信息
     *
     * @param orderInfo
     * @return
     */
    public OrderInfo getOrderDetailInfo(OrderInfo orderInfo) {
        String xml = WanDaUtil.GetOrderDetailInfoServiceXML(orderInfo);

        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("查询预约单详细信息 失败");
            return null;
        }
        log.info("查询预约单详细信息：body = {}", body);
        String returnXml = getReturn(body, "GetOrderDetailInfoService");
        if (Constant.STRING_NO.equals(getCode(returnXml))) {
            Document document = XmlUtil.readXML(returnXml);
            NodeList list = document.getElementsByTagName("OrderInfo");
            if (list.getLength() > 0) {
                return XmlUtil.xmlToBean(list.item(0), OrderInfo.class);
            }
        }
        return null;
    }

    /**
     * 验证患者就诊卡信息
     *
     * @param orderInfo
     * @return
     */
    public boolean checkPatientInfo(OrderInfo orderInfo) {
        String xml = WanDaUtil.CheckPatientInfoServiceXML(orderInfo);

        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("验证患者就诊卡信息 失败");
            return false;
        }
        log.info("验证患者就诊卡信息：body = {}", body);
        String returnXml = getReturn(body, "CheckPatientInfoService");
        if (Constant.STRING_NO.equals(getCode(returnXml))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 查询医疗机构配置信息
     *
     * @param hosInfo
     * @return
     */
    public HospitalCfg getHospitalCfg(HosInfo hosInfo) {
        String xml = WanDaUtil.GetHospitalCfgServiceXML(hosInfo);
        System.out.println(xml);
        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("查询医疗机构配置信息 失败");
            return null;
        }
        log.info("查询医疗机构配置信息：body = {}", body);
        String returnXml = getReturn(body, "GetHospitalCfgService");
        if (Constant.STRING_NO.equals(getCode(returnXml))) {
            Document document = XmlUtil.readXML(returnXml);
            NodeList list = document.getElementsByTagName("HosInfo");
            if (list.getLength() > 0) {
                return XmlUtil.xmlToBean(list.item(0), HospitalCfg.class);
            }
        }
        return null;
    }

    /**
     * 获取可预约医生信息
     *
     * @param deptInfo
     * @return
     */
    public List<DoctInfo> getResourceDoctInfo(DeptInfo deptInfo) {
        String xml = WanDaUtil.GetResourceDoctInfoServiceXML(deptInfo);

        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("获取可预约医生信息 失败");
            return null;
        }
        log.info("获取可预约医生信息：body = {}", body);
        String returnXml = getReturn(body, "GetResourceDoctInfoService");
        return serialDoctInfo(returnXml);
    }

    /**
     * 获取可预约门诊信息
     *
     * @param deptInfo
     * @return
     */
    public List<OutPatInfo> getResourceOutPatInfo(DeptInfo deptInfo) {
        String xml = WanDaUtil.GetResourceOutPatInfoServiceXML(deptInfo);

        String body = HttpRequest.post(URL)
                .body(xml)
                .execute()
                .body();

        if (StrUtil.isBlank(body)) {
            log.error("查询门诊信息失败");
            return null;
        }
        log.info("查询门诊信息：body = {}", body);
        String returnXml = getReturn(body, "GetResourceOutPatInfoService");
        return serialOutPatInfo(returnXml);
    }


    private static List<DeptInfo> serialDeptInfos(String returnXml) {
        if (StrUtil.isNotBlank(returnXml)) {
            if (Constant.STRING_NO.equals(getCode(returnXml))) {
                Document document = XmlUtil.readXML(returnXml);
                NodeList nodeList = document.getElementsByTagName("DeptInfo");
                List<DeptInfo> list = new ArrayList<>();
                if (null != nodeList && nodeList.getLength() > 0) {
                    for (int i = 0; i < nodeList.getLength(); i++) {
                        list.add(XmlUtil.xmlToBean(nodeList.item(i), DeptInfo.class));
                    }
                }
                return list;
            }
        }
        return null;
    }

    private static List<DoctInfo> serialDoctInfo(String returnXml) {
        if (StrUtil.isNotBlank(returnXml)) {
            if (Constant.STRING_NO.equals(getCode(returnXml))) {
                Document document = XmlUtil.readXML(returnXml);
                NodeList nodeList = document.getElementsByTagName("ResourceInfo");
                List<DoctInfo> list = new ArrayList<>();
                if (null != nodeList && nodeList.getLength() > 0) {
                    for (int i = 0; i < nodeList.getLength(); i++) {
                        list.add(XmlUtil.xmlToBean(nodeList.item(i), DoctInfo.class));
                    }
                }
                return list;
            }
        }
        return null;

    }

    private static List<OutPatInfo> serialOutPatInfo(String returnXml) {
        if (StrUtil.isNotBlank(returnXml)) {
            if (Constant.STRING_NO.equals(getCode(returnXml))) {
                Document document = XmlUtil.readXML(returnXml);
                NodeList nodeList = document.getElementsByTagName("ResourceInfo");
                List<OutPatInfo> list = new ArrayList<>();
                if (null != nodeList && nodeList.getLength() > 0) {
                    for (int i = 0; i < nodeList.getLength(); i++) {
                        list.add(XmlUtil.xmlToBean(nodeList.item(i), OutPatInfo.class));
                    }
                }
                return list;
            }
        }
        return null;
    }

    private String getCode(String returnStr) {
        String code = Constant.STRING_NO;
        try {
            Document returnDoc = XmlUtil.readXML(returnStr);
            code = (String) XmlUtil.getByXPath(CODE_XPATH, returnDoc, XPathConstants.STRING);
        } catch (Exception ex) {
            log.error("获取code失败！");
            log.error(ex.getMessage(), ex);
        }
        return code;
    }

    private static String getReturn(String body, String response) {
        String returnStr = "";
        try {
            Document document = XmlUtil.readXML(body);

            returnStr = (String) XmlUtil.getByXPath(getReturnPath(response), document, XPathConstants.STRING);

        } catch (Exception ex) {
            log.error("获取 returnStr 失败！");
            log.error(ex.getMessage(), ex);
        }
        return returnStr;
    }

    private String getReturnPath(String response) {

        return "//soap:Envelope/soap:Body/ns2:" + response + "Response/return";
    }
}
