package io.renren.common.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

import io.renren.common.security.LLianPayAccpSignature;

/**
 * HttpClient4.3工具类
 * @author lsy
 * @version 1.0.0
 */
public class HttpClientUtil {

    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class); // 日志记录

    private static RequestConfig requestConfig = null;

    static {
        // 设置请求和传输超时时间
        requestConfig = RequestConfig.custom().setSocketTimeout(20000).setConnectTimeout(20000).build();
    }

    /**
     * POST请求传输JSON参数
     * @param url
     * @param jsonParam
     * @return JSONObject
     */
    public static String post(String url, JSONObject param) {
        String result = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        try {
            if (null != param) {
                StringEntity entity = new StringEntity(param.toString(), "utf-8");
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }
//            logger.info("POST请求:" + httpPost);
            CloseableHttpResponse response = httpClient.execute(httpPost);
//            logger.info("POST返回:" + response);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                try {
                    result = EntityUtils.toString(response.getEntity(), "utf-8");
                } catch (Exception e) {
                    logger.error("POST请求提交失败:" + url, e);
                }
            }
        } catch (IOException e) {
            logger.error("POST请求提交失败:" + url, e);
        } finally {
            httpPost.releaseConnection();
        }
        return result;
    }

    /**
     * POST请求传输JSON参数
     *
     * @param url
     * @param jsonParam
     * @return JSONObject
     */
    public static String postToZijie(String url, JSONObject param) {
        String result = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        try {
            if (null != param) {
                StringEntity entity = new StringEntity(param.toString(), "utf-8");
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }
//            logger.info("POST请求:" + httpPost);
            CloseableHttpResponse response = httpClient.execute(httpPost);
//            logger.info("POST返回:" + response);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                try {
                    result = EntityUtils.toString(response.getEntity(), "utf-8");
                } catch (Exception e) {
                    logger.error("POST请求提交失败:" + url, e);
                }
            }
        } catch (IOException e) {
            logger.error("POST请求提交失败:" + url, e);
        } finally {
            httpPost.releaseConnection();
        }
        return result;
    }

    /**
     * POST请求传输String参数
     * 例如：name=jack&sex=1&type=2
     *
     * @param url
     * @param strParam
     * @return String
     */
    public static String post(String url, String param) {
        String result = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        try {
            if (null != param) {
                StringEntity entity = new StringEntity(param, "utf-8");
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/x-www-form-urlencoded");
                httpPost.setEntity(entity);
            }
            CloseableHttpResponse response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                try {
                    result = EntityUtils.toString(response.getEntity(), "utf-8");
                } catch (Exception e) {
                    logger.error("POST请求提交失败:" + url, e);
                }
            }
        } catch (IOException e) {
            logger.error("POST请求提交失败:" + url, e);
        } finally {
            httpPost.releaseConnection();
        }
        return result;
    }

    /**
     * 发送GET请求
     *
     * @param url
     * @return String
     */
    public static String get(String url) {
        String result = null;
        CloseableHttpClient client = HttpClients.createDefault();
        HttpGet request = new HttpGet(url);
        request.setConfig(requestConfig);
        try {
            CloseableHttpResponse response = client.execute(request);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                result = EntityUtils.toString(entity, "utf-8");
            } else
                logger.error("GET请求提交失败:" + url);
        } catch (IOException e) {
            logger.error("GET请求提交失败:" + url, e);
        } finally {
            request.releaseConnection();
        }
        return result;
    }


    /**
     * 获取url中指定的参数值
     * @param url
     * @param param
     * @return
     */
    public static String getUrlParam(String url,String param) {
        if(StringUtils.isEmpty(url)) {
            return "";
        }
        if (StringUtils.indexOf(url,"?")==-1) {
            return "";
        }
        url= StringUtils.substringAfter(url,"?");
        Map<String, String> mapRequest = new HashMap<String, String>();
        String[] arrSplit = url.split("[&]");
        for (String strSplit : arrSplit) {
            String[] arrSplitEqual = null;
            arrSplitEqual = strSplit.split("[=]");
            //解析出键值
            if (arrSplitEqual.length > 1) {
                //正确解析
                mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);
            } else {
                if (arrSplitEqual[0] != "") {
                    //只有参数没有值，不加入
                    mapRequest.put(arrSplitEqual[0], "");
                }
            }
        }
        return mapRequest.get(param);
    }

    /**
     * @param url
     * @param body
     * @param priKey
     * @param pubKey
     * @return
     */
    public static String sendRequest(String url, String body,String priKey,String pubKey) {
        if (url == null || "".equals(url)) {
            throw new RuntimeException("请求URL非法");
        }
        String sign = LLianPayAccpSignature.getInstance().sign(body,priKey);
        logger.info(String.format("请求URL：%s", url));
        logger.info(String.format("请求签名值：%s", sign));
        logger.info(String.format("请求参数：%s", body));

        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost post = new HttpPost(url);
        post.setConfig(requestConfig);
        post.setHeader("Content-Type", "application/json;charset=utf-8");
        post.setHeader("Signature-Type", "RSA");
        post.setHeader("Signature-Data", sign);
        try {
            StringEntity stringEntity = new StringEntity(body, "UTF-8");
            stringEntity.setContentEncoding(new BasicHeader(HTTP.CONTENT_ENCODING, "UTF-8"));
            post.setEntity(stringEntity);
            CloseableHttpResponse resp = httpClient.execute(post);
            int ret = resp.getStatusLine().getStatusCode();
            if (ret == HttpStatus.SC_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(resp.getEntity().getContent(), "UTF-8"));
                StringBuffer responseString = new StringBuffer();
                String result = br.readLine();
                while (result != null) {
                    responseString.append(result);
                    result = br.readLine();
                }
                String resSignatureData = "";
                Header headers[] = resp.getAllHeaders();
                int i = 0;
                while (i < headers.length) {
                    if ("Signature-Data".equals(headers[i].getName())) {
                        resSignatureData = headers[i].getValue();
                    }
                    i++;
                }
                logger.info(String.format("响应结果：%s", responseString));
                if (!"".equalsIgnoreCase(resSignatureData)) {
                    logger.info(String.format("响应签名：%s", resSignatureData));
                    boolean checksign = LLianPayAccpSignature.getInstance().checkSign(responseString.toString(), resSignatureData,pubKey);
                    if (!checksign) {
                        logger.error("返回响应验证签名异常，请核实！");
                    } else {
                        logger.info(String.format("响应验签通过！"));
                    }
                }
                return responseString.toString();
            }
            throw new RuntimeException("请求结果异常，响应状态码为：" + ret);
        } catch (ConnectTimeoutException cte) {
            logger.error(cte.getMessage());
            throw new RuntimeException(cte);
        } catch (SocketTimeoutException cte) {
            logger.error(cte.getMessage());
            throw new RuntimeException(cte);
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }
}
