package com.ynxbd.common.helper.his;
import com.ynxbd.common.action.pay.PEnum;
import com.ynxbd.common.bean.pay.Order;
import com.ynxbd.common.helper.ProperHelper;
import com.ynxbd.common.helper.common.CodeHelper;
import com.ynxbd.common.helper.common.ErrorHelper;
import com.ynxbd.common.helper.common.SoapHelper;
import com.ynxbd.common.result.JsonResult;
import com.ynxbd.common.result.JsonResultEnum;
import com.ynxbd.common.result.ResultEnum;
import com.ynxbd.common.result.ServiceException;
import com.ynxbd.common.service.PayService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public class HisHelper {
    public static final String SOAP_ENV = " getHisTradeNo(String prefix, List ids, PEnum pEnum) {
        if (pEnum == null) {
            return null;
        }
        return CodeHelper.getOutTradeNo(prefix, pEnum.ORDER_CODE.toUpperCase(), ids);
    }
    /**
     * HIS订单号
     */
    public static String getHisTradeNo(String prefix, PEnum pEnum) {
        if (pEnum == null) {
            return null;
        }
        return prefix + pEnum.ORDER_CODE.toUpperCase() + "001";
    }
    /**
     * 根据订单号获取类型
     *
     * @param bankTransNo 交易流水号
     * @param tradeNo     HIS订单号
     * @return 类型
     */
    public static String getTypeByPEnum(String bankTransNo, String tradeNo) throws ServiceException {
        if (!PayService.isNewOrder(bankTransNo, tradeNo)) {
            throw new ServiceException(ResultEnum.REFUND_IS_OLD_ORDER_NUM);
        }
        String middle = tradeNo.substring(tradeNo.length() - 4, tradeNo.length() - 3);
        for (PEnum item : PEnum.values()) {
            if (item.ORDER_CODE.equals(middle)) {
                return item.CODE;
            }
        }
        return null;
    }
    /**
     * webService请求工具类(枚举版)
     *
     * @param hisEnum 枚举
     * @param params  发送的参数
     * @return 响应的xml数据
     */
    public static String getResponseXml(HisEnum hisEnum, Map params) {
        return getResponseXml(hisEnum, HIS_SOAP_URL, params);
    }
    /**
     * 医保环境
     *
     * @param hisEnum 枚举
     * @param params  发送的参数
     * @return 响应的xml数据
     */
    public static String getMdResponseXml(HisEnum hisEnum, Map params) {
        return getResponseXml(hisEnum, HIS_SOAP_MD_URL, params);
    }
    /**
     * 医保环境
     *
     * @param hisEnum 枚举
     * @param params  发送的参数
     * @return 响应的xml数据
     */
    public static String getDevResponseXml(HisEnum hisEnum, Map params) {
        return getResponseXml(hisEnum, HIS_SOAP_DEV_URL, params);
    }
    /**
     * webService请求工具类(枚举版)
     *
     * @param hisEnum 枚举
     * @param params  发送的参数
     * @return 响应的xml数据
     */
    public static String getResponseXml(HisEnum hisEnum, String soapUrl, Map params) {
        String method = hisEnum.METHOD;
        String transactionCode = hisEnum.CODE;
        if (params == null || transactionCode == null || method == null) {
            log.info("WebService-{ map | transactionCode | method 为空 }");
            return null;
        }
        Object callNo = params.get("CallNo");
        if (params.get("CallNo") == null || "".equals(callNo)) {
            params.put("CallNo", CALL_NO);
        }
        params.put("TransactionCode", transactionCode);
        String result = null;
        try {
            long begTime = System.currentTimeMillis(); // 开始时间
            String hisResponse = SoapHelper.post("HIS", soapUrl, null, SOAP_ENV +
                    "xmlns:urn=\"urn:Interface_ABIntf-IInterface_AB\">" +
                    "" +
                    "" +
                    "" + SoapHelper.requestParams("HIS", params) + "" +
                    ""
            );
            long endTime = System.currentTimeMillis(); // 结束时间
            String takeTime = (endTime - begTime) + "ms"; // 耗时
            if (hisResponse == null) {
                log.info("HIS请求无响应[{}]-耗时:[{}]", transactionCode, takeTime);
                return null;
            }
            //解析响应消息,使用SAXReader对象
            org.dom4j.Document document = DocumentHelper.parseText(hisResponse);
            if (document == null) {
                log.info("HIS响应内容解析失败[{}]-耗时:[{}]-返回xml={}", transactionCode, takeTime, hisResponse);
                return null;
            }
            List nodes = document.selectNodes("//return");
            if (nodes.size() == 0) {
                log.info("HIS请求失败[{}]-耗时:[{}]-返回xml={}", transactionCode, takeTime, hisResponse);
                return null;
            }
            Element element = (Element) nodes.get(0);
            result = element.getText();
            if (hisEnum.IS_LOG_RESP) { // 是否打印返回的xml
                log.info("HIS请求成功[{}]-耗时:[{}]-返回xml={}", transactionCode, takeTime, result);
            } else {
                if (IS_LOG_RESP) { // 配置文件强制要求打印xml
                    if (!HisEnum.AP_Query_Statement.equals(hisEnum))
                        log.info("[强制打印]HIS请求成功[{}]-耗时:[{}]-返回xml={}", transactionCode, takeTime, result);
                }
            }
        } catch (DocumentException e) {
            ErrorHelper.println(e);
        }
        return result;
    }
//    /**
//     * xml响应数据组装成为JSON数据
//     *
//     * @param xml xml
//     * @return 封装好的对象
//     */
//    public static HisResult xmlToBean(String xml) {
//        if (xml == null || "".equals(xml)) {
//            log.info("HIS response xml is null");
//            return HisResult.createErrorHisResult("[HIS]获取xml数据失败");
//        }
//
//        JSONObject respObj;
//        try {
//            Document document = DocumentHelper.parseText(xml);
//            Element root = document.getRootElement(); // 获取根节点元素对象
//            respObj = HisResult.nodeToJsonObject(root);
//            Map map = new HashMap<>();
//            Set keys = respObj.keySet();
//            for (String key : keys) {
//                if (!key.equals("TransactionCode") && !key.equals("ResponseCode") && !key.equals("ResponseMessage") && !key.equals("PatientName")) {
//                    map.put(key, respObj.getString(key));
//                }
//            }
//            respObj.put("DataMap", map);
//        } catch (DocumentException e) {
//            ErrorHelper.println(e);
//            return HisResult.createErrorHisResult(e.getMessage());
//        }
//        HisResult hisResult = JSON.toJavaObject(respObj, HisResult.class);
//        if (hisResult.getResponseCode() != 0) {
//            log.info("HIS Error Message:[{}]", hisResult.getResponseMessage());
//        }
//        return hisResult;
//    }
    /**
     * xml响应数据组装成为JSON数据
     *
     * @return 封装好的对象
     */
    public static JsonResult getJsonResult(HisEnum hisEnum, Map params) {
        JsonResult result = JsonResult.xmlToBean(getResponseXml(hisEnum, params), JsonResultEnum.SYS_HIS);
        if (result == null) { // 如果返回为空可能为超时
            return createTimeoutResult();
        }
        return result;
    }
    /**
     * xml响应数据组装成为JSON数据
     *
     * @return 封装好的对象
     */
    public static JsonResult getJsonResult(HisEnum hisEnum, JsonResult.MapParams params) {
        Map requestParams = new HashMap<>();
        if (params != null) {
            params.setParams(requestParams);
        }
        return getJsonResult(hisEnum, requestParams);
    }
    // 医保-------------------------------------------------------------------------------------------------------------
    /**
     * xml响应数据组装成为JSON数据
     *
     * @return 封装好的对象
     */
    public static JsonResult getMdJsonResult(HisEnum hisEnum, Map params) {
        JsonResult result = JsonResult.xmlToBean(getMdResponseXml(hisEnum, params), JsonResultEnum.SYS_HIS);
        if (result == null) { // 如果返回为空可能为超时
            return createTimeoutResult();
        }
        return result;
    }
    /**
     * xml响应数据组装成为JSON数据
     *
     * @return 封装好的对象
     */
    public static JsonResult getMdJsonResult(HisEnum hisEnum, JsonResult.MapParams params) {
        Map requestParams = new HashMap<>();
        if (params != null) {
            params.setParams(requestParams);
        }
        return getMdJsonResult(hisEnum, requestParams);
    }
    // ---------------------------------------------------------------------------
    // 测试环境
    /**
     * xml响应数据组装成为JSON数据
     *
     * @return 封装好的对象
     */
    public static JsonResult getDevJsonResult(HisEnum hisEnum, Map params) {
        JsonResult result = JsonResult.xmlToBean(getDevResponseXml(hisEnum, params), JsonResultEnum.SYS_HIS);
        if (result == null) { // 如果返回为空可能为超时
            return createTimeoutResult();
        }
        return result;
    }
    /**
     * xml响应数据组装成为JSON数据
     *
     * @return 封装好的对象
     */
    public static JsonResult getDevJsonResult(HisEnum hisEnum, JsonResult.MapParams params) {
        Map requestParams = new HashMap<>();
        if (params != null) {
            params.setParams(requestParams);
        }
        return getDevJsonResult(hisEnum, requestParams);
    }
    /**
     * xml响应数据组装成为JSON数据
     *
     * @return 封装好的对象
     */
    public static JsonResult createErrorResult(String message) {
        if (ObjectUtils.isEmpty(message)) {
            message = "【HIS】请求参数缺失";
        }
        return JsonResult.createErrorResult(message, JsonResultEnum.SYS_HIS);
    }
    /**
     * xml响应数据组装成为JSON数据
     *
     * @return 封装好的对象
     */
    private static JsonResult createTimeoutResult() {
        return JsonResult.createTimeoutResult("【HIS】请求超时", JsonResultEnum.SYS_HIS);
    }
}