package com.yihu.hos.crawler.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.yihu.hos.core.datatype.StringUtil;
import com.yihu.hos.core.encrypt.MD5;
import com.yihu.hos.core.httpclient.HttpClientUtil;
import com.yihu.hos.core.httpclient.HttpHelper;
import com.yihu.hos.core.httpclient.HttpResponse;
import com.yihu.hos.core.log.Logger;
import com.yihu.hos.core.log.LoggerFactory;
import com.yihu.hos.crawler.model.adapter.AdapterDataSet;
import com.yihu.hos.crawler.model.config.SysConfig;
import com.yihu.hos.crawler.model.patient.Patient;
import com.yihu.hos.crawler.model.transform.EhrCondition;
import com.yihu.hos.web.framework.constrant.SqlConstants;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;
import sun.misc.BASE64Encoder;

import java.io.File;
import java.util.*;

/**
 * Created by hzp on 2016/3/10.
 */
public class EsbHttp {

    private static Logger logger = LoggerFactory.getLogger(EsbHttp.class);

    /***************************** 用户接口 *********************************************/
    /**
     * 用户登录验证
     */
    public static HttpResponse loginAction(String user, String password) throws Exception{
        String loginAction = HttpHelper.defaultHttpUrl+"/authorizations/users/" + user;
        Map<String,Object> header = new HashMap<>();
        String auth  = new BASE64Encoder().encode((user+":"+password).getBytes());
        header.put("Authorization","Basic "+auth);
        return HttpHelper.put(loginAction, null, header);
    }

    /*
    *   获取用户信息
    * */
    public static HttpResponse getUserInfo(String user,String token)
    {
        String url = HttpHelper.defaultHttpUrl+"/users/" + user;
        Map<String,Object> params = new HashMap<>();
        params.put("token",token);
        params.put("user",user);
        return HttpHelper.get(url, params);
    }

    /***************************** 应用接口 *********************************************/

    /**
     * 获取本机指纹
     * @return
     */
    private static String GetFingerprint(){
        try {
            return UUID.randomUUID().toString();
        }
        catch (Exception e)
        {
            System.out.print(e.getMessage());
            return "";
        }
    }

    /**
     * 应用登录验证
     */
    public static String getToken(){
        try {
            String loginAction = HttpHelper.defaultHttpUrl + "/authorizations/clients/" + HttpHelper.clientId;
            Map<String, Object> header = new HashMap<>();
            header.put("Authorization", "Basic " + HttpHelper.clientKey);
            //本地指纹
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("info", "{\"fingerprint\": \"" + GetFingerprint() + "\"}");

            HttpResponse response = HttpHelper.put(loginAction, params, header);
            if (response != null && response.getStatusCode() == HttpStatus.SC_OK) {
                JSONObject obj = new JSONObject(response.getBody());
                //判断是否成功
                if (obj.has("token")) {
                    return obj.getString("token");
                } else {
                    logger.info("返回未包含token。");
                    return null;
                }
            } else {
                String msg = "获取Token失败。";

                if (response != null) {
                    msg += "(错误代码:" + response.getStatusCode() + ",错误信息:" + response.getBody() + ")";
                }
                logger.info(msg);
                return null;
            }
        }
        catch (Exception ex)
        {
            logger.info("获取Token失败," + ex.getMessage());
            return null;
        }
    }

    /**
     * 获取病人列表
     */
    public static String getPatientList(AdapterDataSet adapterDataSet, List<EhrCondition> queryParams){
        try {
            ObjectMapper mapper = new ObjectMapper();
            ObjectNode paramsNode = mapper.createObjectNode();

            paramsNode.put("tableCode", adapterDataSet.getAdapterDataSetT().getStdDatasetCode());
            paramsNode.put("condition", mapper.writeValueAsString(queryParams));

            List<NameValuePair> formParams = new ArrayList<>();
            formParams.add(new BasicNameValuePair("api", "collectionData"));
            String params = mapper.writeValueAsString(paramsNode);
            formParams.add(new BasicNameValuePair("param", params));
            HttpResponse response = HttpClientUtil.postForm(HttpHelper.httpGateway, formParams);
            if (response == null || response.getStatusCode() != 200) {
                logger.error("获取病人列表错误,请求HTTP错误,请检查配置或HTTP是否可用.");
                return "";
            }

            JsonNode responseNode = mapper.readValue(response.getBody(), JsonNode.class);
            String code = responseNode.path("responseCode").asText();
            if (StringUtil.isEmpty(code) || !code.equals("10000")) {
                logger.error("获取病人列表错误,请求HTTP错误,请检查集成平台网关是否可用.");
                return "";
            }

            String rootStr = responseNode.path("responseResult").asText();
            if ("".equals(rootStr)) {
                logger.error("获取病人列表错误,集成平台获取病人列表失败.");
                return "";
            }
            return rootStr;
        } catch (Exception e) {
            logger.error("获取病人列表失败！", e);
            return "";
        }
    }

    public static String getFecthData(List<NameValuePair> formParams) {
        try {
            HttpResponse response = HttpClientUtil.postForm(HttpHelper.httpGateway, formParams);
            if (response == null || response.getStatusCode() != 200) {
                logger.info("获取病人数据错误,请求HTTP错误,请检查配置或HTTP是否可用.");
                return SqlConstants.EMPTY;
            }
            ObjectMapper mapper = new ObjectMapper();
            JsonNode responseNode = mapper.readValue(response.getBody(), JsonNode.class);
            String code = responseNode.path("responseCode").asText();
            if (StringUtil.isEmpty(code) || !code.equals("10000")) {
                logger.info("获取病人数据错误,请求HTTP错误,请检查集成平台网关是否可用.");
                return SqlConstants.EMPTY;
            }

            String rootStr = responseNode.path("responseResult").asText();
            if (SqlConstants.EMPTY.equals(rootStr)) {
                logger.info("获取病人数据错误,集成平台获取病人数据失败.");
                return SqlConstants.EMPTY;
            }
            return rootStr;
        } catch (Exception e) {
            logger.error("获取病人数据失败.", e);
            return SqlConstants.EMPTY;
        }
    }
        /**
         * 获取公钥
         */
    public static String getPublicKey(String orgCode){
        try {
            String token = getToken();
            if (!StringUtil.isEmpty(SysConfig.getInstance().getPublicKeyMap().get(orgCode))) {
                return SysConfig.getInstance().getPublicKeyMap().get(orgCode);
            }
            Map<String, Object> header = new HashMap<>();
            header.put("Authorization", "Basic " + HttpHelper.clientKey);
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("org_code", orgCode);
            paramMap.put("token", token);
            String publicKeyMethod = HttpHelper.defaultHttpUrl + "/organizations/"+orgCode+"/key";
            HttpResponse response = HttpHelper.get(publicKeyMethod, paramMap, header);
            if (response != null && response.getStatusCode() == HttpStatus.SC_OK) {
                JSONObject json = new JSONObject(response.getBody());
                if(json.has("publicKey"))
                {
                    String publicKey = json.getString("publicKey");
                    SysConfig.getInstance().getPublicKeyMap().put(orgCode, publicKey);
                    return publicKey;
                }
                else{
                    logger.info("获取公钥失败，返回未包含publicKey。");
                    return null;
                }
            }
            else{
                String msg = "获取公钥失败。";

                if (response != null)
                {
                    msg +="(错误代码:"+ response.getStatusCode() + ",错误信息:"+response.getBody()+")";
                }
                logger.info(msg);
                return null;
            }
        } catch (Exception e) {
            logger.info(e.getMessage());
            return null;
        }
    }

    /**
     * 获取健康云平台标准版本号
     */
    public static String getRemoteVersion(String orgCode) {
        try {
            String token = getToken();
            String versionMethod = HttpHelper.defaultHttpUrl + "/adaptions/org_plan/version";
            Map<String, Object> header = new HashMap<>();
            header.put("Authorization", "Basic " + HttpHelper.clientKey);
            Map<String, Object> params = new HashMap<>();
            params.put("org_code", orgCode);
            params.put("token", token);
            HttpResponse response = HttpHelper.get(versionMethod, params, header);
            if (response != null && response.getStatusCode() == HttpStatus.SC_OK) {
                return response.getBody();
            }
            else{
                String msg = "获取健康云平台标准版本号失败";

                if (response != null)
                {
                    msg +="(错误代码:"+ response.getStatusCode() + ",错误信息:"+response.getBody()+")";
                }
                logger.info(msg);

                return null;
            }
        } catch (Exception e) {
            logger.info("获取远程版本号异常");
            logger.error(e.getCause().toString());
            return null;
        }
    }


    /**
     * 注册病人
     */
    public static Boolean register(Patient patient, String data, String token) {
        try {
            JSONObject json = new JSONObject(data);
            String colName = SysConfig.registerIdCardNo;
            Map<String, Object> header = new HashMap<>();
            header.put("Authorization", "Basic " + HttpHelper.clientKey);
            header.put("User-Agent", "client " + HttpHelper.clientId);
            if(json!=null && json.has("data")) {
                JSONObject p = (JSONObject)json.getJSONArray("data").get(0);
                if(!p.has(colName) || StringUtil.isEmpty(p.get(colName))) {
                    logger.info("注册病人信息请求失败:身份证号码为空，patient_id=" + patient.getPatientId() + ", event_no=" + patient.getEventNo());
                    return false;
                }
                else{
                    String idCord = p.getString(colName);
                    String registerMethod = HttpHelper.defaultHttpUrl + "/patients/"+idCord;
                    if (StringUtil.isEmpty(data)) {
                        logger.info("注册病人信息请求失败:无具体病人信息，patient_id=" + patient.getPatientId() + ", event_no=" + patient.getEventNo());
                        return false;
                    }
                    Map<String, Object> paramMap = new HashMap<>();
                    paramMap.put("demographic_id", idCord);
                    paramMap.put("json", data);
                    paramMap.put("token", token);
                    HttpResponse response = HttpHelper.post(registerMethod, paramMap, header);

                    if (response != null && response.getStatusCode() == HttpStatus.SC_OK) {
                        logger.info("注册病人信息成功。patient_id:" + patient.getPatientId() + ", event_no:" + patient.getEventNo());
                        return true;
                    }
                    else{
                        String msg = "注册病人信息请求失败。patient_id:" + patient.getPatientId() + ", event_no:" + patient.getEventNo();
                        if(response != null)
                        {
                            msg +="(错误代码:"+ response.getStatusCode() + ",错误信息:"+response.getBody()+")";
                        }
                        logger.info(msg);
                        return false;
                    }
                }

            }
            else{
                logger.info("注册病人信息请求失败:传入数据无效，patient_id=" + patient.getPatientId() + ", event_no=" + patient.getEventNo());
                return false;
            }
        }
        catch (Exception e)
        {
            logger.info("注册病人信息请求失败." + e.getMessage());
            return false;
        }
    }

    /**
     * 上传病人档案
     */
    public static boolean upload(Patient patient, File file, String encryptPwd, String token) {
        try {
            String uploadMethod = HttpHelper.defaultHttpUrl + "/packages";
            String fileMd5= MD5.getMd5ByFile(file);
            List<NameValuePair> formParams = new ArrayList<>();
            formParams.add(new BasicNameValuePair("md5", fileMd5));
            formParams.add(new BasicNameValuePair("package_crypto", encryptPwd));
            formParams.add(new BasicNameValuePair("org_code", patient.getOrgCode()));
            formParams.add(new BasicNameValuePair("token", token));
            Map<String, Object> header = new HashMap<>();
            header.put("Authorization", "Basic " + HttpHelper.clientKey);
            header.put("User-Agent", "client " + HttpHelper.clientId);
            HttpResponse response = HttpHelper.postFile(uploadMethod, formParams, file.getAbsolutePath(), header);

            if (response != null && response.getStatusCode() == HttpStatus.SC_OK) {
                logger.info("上传病人档案成功,patient_id:" + patient.getPatientId() + ",event_no:" + patient.getEventNo());
                return true;
            }
            else {
                String msg = "上传病人档案请求失败,patient_id:" + patient.getPatientId() + ",event_no:" + patient.getEventNo();

                if (response != null)
                {
                    msg +="(错误代码:"+ response.getStatusCode() + ",错误信息:"+response.getBody()+")";
                }
                logger.info(msg);
                return false;
            }
        }
        catch (Exception e) {
            logger.info("上传病人档案异常,patient_id:" + patient.getPatientId() + ",event_no:" + patient.getEventNo());
            logger.error(e.getCause().toString());
            return false;
        }
    }


    /**
     * 下载标准包
     */
    public static HttpResponse download(String remoteVersion, String orgCode) {
        try {
            String token = getToken();
            String downLoadMethod = HttpHelper.defaultHttpUrl + "/adaptions/"+orgCode+"/source";
            Map<String, Object> params = new HashMap<>();
            params.put("version_code", remoteVersion);
            params.put("org_code", orgCode);
            params.put("token", token);
            Map<String, Object> header = new HashMap<>();
            header.put("Authorization", "Basic " + HttpHelper.clientKey);
            HttpResponse response = HttpHelper.get(downLoadMethod, params, header);
            return response;
        } catch (Exception e) {
            logger.info("下载标准包异常:");
            logger.error(e.getCause().toString());
            return null;
        }
    }

}
