package com.xhpc.common.core.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
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.client.methods.HttpRequestBase;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * http相关操作
 *
 * @author fengjundan on 2018/5/12.
 */
public class HttpUtils {

    /**
     * 连接池管理
     */
    private static PoolingHttpClientConnectionManager poolConnManager = null;

    private static CloseableHttpClient httpClient = null;
    /**
     * 请求器的配置
     */
    private static RequestConfig requestConfig;

    static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);

    static {
        try {
            logger.info("httpClient init...");
            SSLContextBuilder builder = new SSLContextBuilder();
            builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
            // 配置同时支持 HTTP 和 HTPPS
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register(
                    "http", PlainConnectionSocketFactory.getSocketFactory()).register(
                    "https", sslsf).build();
            // 初始化连接管理器
            poolConnManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            // 将最大连接数增加到200
            poolConnManager.setMaxTotal(200);
            // 设置最大路由
            poolConnManager.setDefaultMaxPerRoute(2);
            // 根据默认超时限制初始化requestConfig
            int socketTimeout = 100000;
            int connectTimeout = 100000;
            int connectionRequestTimeout = 100000;
            requestConfig = RequestConfig.custom().setConnectionRequestTimeout(
                    connectionRequestTimeout).setSocketTimeout(socketTimeout).setConnectTimeout(
                    connectTimeout).build();
            // 初始化httpClient
            httpClient = getConnection();
            logger.info("HttpClient inited.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static CloseableHttpClient getConnection() {
        CloseableHttpClient closeableHttpClient = HttpClients.custom()
                // 设置连接池管理
                .setConnectionManager(poolConnManager)
                // 设置请求配置
                .setDefaultRequestConfig(requestConfig)
                // 设置重试次数
                .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
                .build();
        return closeableHttpClient;
    }


    /**
     * get请求
     *
     * @param url 请求地址
     * @return
     * @author fengjundan
     * @date 2018/5/12
     */
    public static String get(String url) {
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            destroy(httpGet, response);
        }
        return null;
    }

    /**
     * get请求(带header)
     *
     * @author fengjundan
     * @date 2019/12/30 11:45
     */
    public static String get(String url, Map<String, Object> headers) {
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            if (headers != null && headers.size() > 0) {
                for (String key : headers.keySet()) {
                    httpGet.setHeader(key, StringUtils.valueOf(headers.get(key)));
                }
            }
            response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            destroy(httpGet, response);
        }
        return null;
    }


    /**json格式的参数数据
     * post请求
     *
     * @param url    请求地址
     * @param params
     * @return
     * @author fengjundan
     * @date 2018/6/2
     */
    public static String post(String url, String params) {
        HttpPost httpPost = new HttpPost(url);
        if (!StringUtils.isNull(params)) {
            StringEntity stringEntity = new StringEntity(params, ContentType.APPLICATION_JSON);
            httpPost.setEntity(stringEntity);
        }
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
            if (response != null && response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");
                return result;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            destroy(httpPost, response);
        }
        return null;
    }

    /**
     * post body请求
     *
     * @param url    请求地址
     * @param params json格式的参数数据
     * @return
     * @author fengjundan
     * @date 2018/6/2
     */
    public static String postBody(String url, String params) {
        HttpPost httpPost = new HttpPost(url);
        if (!StringUtils.isNull(params)) {
            StringEntity stringEntity = new StringEntity(params, ContentType.APPLICATION_JSON);
            httpPost.setEntity(stringEntity);
        }
        CloseableHttpResponse response = null;
        try {
            httpPost.setHeader("Content-Type", "application/json");
            response = httpClient.execute(httpPost);
            if (response != null && response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");
                return result;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            destroy(httpPost, response);
        }
        return null;
    }

    /**
     * post body请求 (带header)
     *
     * @author fengjundan
     * @date 2019/12/30 10:10
     */
    public static String postBody(String url, String params, Map<String, Object> headers) {
        HttpPost httpPost = new HttpPost(url);
        if (!StringUtils.isNull(params)) {
            StringEntity stringEntity = new StringEntity(params, ContentType.APPLICATION_JSON);
            httpPost.setEntity(stringEntity);
        }
        CloseableHttpResponse response = null;
        try {
            if (headers != null && headers.size() > 0) {
                for (String key : headers.keySet()) {
                    httpPost.setHeader(key, StringUtils.valueOf(headers.get(key)));
                }
            }
            httpPost.setHeader("Content-Type", "application/json");
            response = httpClient.execute(httpPost);
            if (response != null && response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");
                return result;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            destroy(httpPost, response);
        }
        return null;
    }

    /**
     * post body请求
     *
     * @param url        请求地址
     * @param jsonObject json参数
     * @return
     * @author fengjundan
     * @date 2018/6/28
     */
    public static String postBody(String url, JSONObject jsonObject) {
        if (jsonObject == null) {
            return null;
        }
        return postBody(url, jsonObject.toJSONString());
    }


    /**
     * post请求
     *
     * @param url 请求地址
     * @return
     * @author fengjundan
     * @date 2018/6/2
     */
    public static String post(String url) {
        return post(url, "");
    }

    /**
     * post请求
     *
     * @param url        请求地址
     * @param jsonObject json格式的参数数据
     * @return
     * @author fengjundan
     * @date 2018/6/2
     */
    public static String post(String url, JSONObject jsonObject) {
        if (jsonObject != null) {
            return post(url, jsonObject.toJSONString());
        } else {
            return post(url, "");
        }
    }

    /**
     * post请求
     *
     * @param url       请求地址
     * @param jsonArray JSONArray格式的参数数据
     * @return
     * @author fengjundan
     * @date 2018/6/2
     */
    public static String post(String url, JSONArray jsonArray) {
        if (jsonArray != null) {
            return post(url, jsonArray.toJSONString());
        } else {
            return post(url, "");
        }
    }

    /**
     * post请求
     * @param url 请求地址
     * @param map map请求参数
     * @author fengjundan
     * @date 2018/6/2
     * @return public static String post(String url, Map<String, Object> map){
    if(map != null){
    String params = JSON.toJSONString(map);
    return post(url, params);
    } else{
    return post(url, "");
    }
    }*/

    /**
     * post请求
     *
     * @param url  请求地址
     * @param list list格式的参数数据
     * @return
     * @author fengjundan
     * @date 2018/6/2
     */
    public static String post(String url, List<Map<String, Object>> list) {
        if (list != null) {
            String params = JSON.toJSONString(list);
            return post(url, params);
        } else {
            return post(url, "");
        }
    }


    /**
     * 释放资源
     *
     * @return
     * @author fengjundan
     * @date 2018/6/2
     */
    private static void destroy(HttpRequestBase httpRequestBase, CloseableHttpResponse response) {
        try {
            if (response != null) {
                response.close();
            }
            if (httpRequestBase != null) {
                httpRequestBase.releaseConnection();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * post请求
     *
     * @param url 请求地址
     * @param map map请求参数
     * @return
     * @author fengjundan
     * @date 2018/6/2
     */
    public static String post(String url, Map<String, Object> map, Map<String, Object> headers) {
        HttpPost httpPost = new HttpPost(url);
        if (map != null && map.size() > 0) {
            List<NameValuePair> postData = new ArrayList<>();
            Set<String> set = map.keySet();
            Iterator<String> iterator = set.iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                String value = StringUtils.valueOf(map.get(key));
                postData.add(new BasicNameValuePair(key, value));
            }
            CloseableHttpResponse response = null;
            try {
                httpPost.setEntity(new UrlEncodedFormEntity(postData, "utf-8"));
                if (headers != null && headers.size() > 0) {
                    for (String key : headers.keySet()) {
                        httpPost.setHeader(key, StringUtils.valueOf(headers.get(key)));
                    }
                }
                response = httpClient.execute(httpPost);
                if (response.getStatusLine().getStatusCode() == 200) {
                    //获取响应实体
                    String result = EntityUtils.toString(response.getEntity(), "utf-8");
                    return result;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                destroy(httpPost, response);
            }
        }
        return null;
    }

    public static String postFormData(String path, HashMap<String, String> Headers, HashMap<String, String> formMap) {
        String result = "";
        HttpURLConnection connection = null;
        String boundary = "--------------------------132183525382215881770481";
        try {
            URL url = new URL(path);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestProperty("Connection", "Keep-Alive");
            // 不使用缓存
            connection.setUseCaches(false);
            if (Headers != null) {
                if (Headers.size() > 0) {
                    for (Map.Entry<String, String> entry : Headers.entrySet()) {
                        connection.setRequestProperty(entry.getKey(), entry.getValue());
                    }
                }
            }
            StringBuffer formSB = new StringBuffer();
            if (formMap != null) {
                if (formMap.size() > 0) {
                    for (Map.Entry<String, String> entry : formMap.entrySet()) {
                        String inputName = entry.getKey();
                        String inputValue = entry.getValue();
                        formSB.append("\r\n").append("--").append(boundary).append("\r\n");
                        formSB.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n");
                        formSB.append(inputValue);
                    }
                    formSB.append("\r\n").append("--").append(boundary).append("--");
                }
            }
            connection.connect();
            //OutputStream out = new DataOutputStream(connection.getOutputStream());
            PrintWriter out = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8));
            out.print(formSB);
            out.flush();
            //获得响应状态
            int resultCode = connection.getResponseCode();
            if (HttpURLConnection.HTTP_OK == resultCode) {
                formSB = new StringBuffer();
                String readLine;
                BufferedReader responseReader = new BufferedReader(new InputStreamReader(connection.getInputStream(),
                        StandardCharsets.UTF_8));
                while ((readLine = responseReader.readLine()) != null) {
                    formSB.append(readLine).append("\n");
                }
                responseReader.close();
                result = formSB.toString();
            } else {
                result = "{\"code\":\"" + resultCode + "\"}";
            }
            out.close();
        } catch (Exception e) {
            logger.error(e.toString());
            return "{\"code\":500,\"result\":\"" + "POST表单请求 " + path + " 时出现异常\"}";
        } finally {
            connection.disconnect();
        }
        return result;
    }


    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url   发送请求的URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream(), StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送GET请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }
}
