package com.fzm.mall.midea.pay.utils;

import com.fzm.mall.midea.pay.model.HttpResponse;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
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.HttpPost;
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.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 网络请求工具
 *
 * @author harvey
 * @date 2020/8/31
 * @email husy7@midea.com
 */
public class HttpClientUtils {

    /**
     * 带文件类型POST请求
     *
     * @param url
     * @param params
     * @param file
     * @return
     */
    public static HttpResponse doPostFile(String url, Map<String, String> params, File file) {
        SSLContext sslcontext = null;
        try {
            sslcontext = SSLContexts.custom()
              .build();
        } catch (KeyManagementException e1) {
            throw new RuntimeException(e1);
        } catch (NoSuchAlgorithmException e1) {
            throw new RuntimeException(e1);
        }
        // Allow TLSv1.2 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
          sslcontext,
          new String[] { "TLSv1.2" },
          null,
          SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        
        HttpResponse resp = new HttpResponse();
        BasicHttpClientConnectionManager connManager;
        connManager = new BasicHttpClientConnectionManager(
                RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
                        .register("https", sslsf)
                        .build(),
                null,
                null,
                null
        );
        
        //构造MultipartEntityBuilder
        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create()
            .setCharset(StandardCharsets.UTF_8).setMode(HttpMultipartMode.BROWSER_COMPATIBLE);

        //设置普通请求参数，如<input type="text" name="name" value="value"/>
        for (Map.Entry<String, String> param : params.entrySet()) {
            if (StringUtils.isNotEmpty(param.getKey(), param.getValue())) {
                multipartEntityBuilder.addTextBody(param.getKey(), param.getValue(), ContentType.create(
                    "text/plain", Consts.UTF_8));
            }
        }

        //设置文件参数
        multipartEntityBuilder.addPart("file", new FileBody(file));

        //创建client和post
        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(15000).setConnectTimeout(3000).build();
        httpPost.setConfig(requestConfig);
        httpPost.setEntity(multipartEntityBuilder.build());
        CloseableHttpClient httpClient = HttpClientBuilder.create()
            .setConnectionManager(connManager)
            .build();

        try {

            //发起请求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);

            if (httpResponse != null) {
                resp.setHttpCode(httpResponse.getStatusLine().getStatusCode());
                resp.setContentType(httpResponse.getHeaders("Content-Type"));
            }
            if(httpResponse.getEntity() != null) {
                resp.setEntity(EntityUtils.toString(httpResponse.getEntity()));
            }
            System.out.println(String.format("http响应结果:code:%s,ContentType:%s,entity%s", 
                resp.getHttpCode(),getContentType(resp.getContentType()),resp.getEntity()));

        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return resp;
    }

    /**
     * 普通POST请求
     *
     * @param url
     * @param params
     * @return
     */
    public static HttpResponse doPost(String url, Map<String, String> params) {
        
        SSLContext sslcontext = null;
        try {
            sslcontext = SSLContexts.custom()
              .build();
        } catch (KeyManagementException e1) {
            throw new RuntimeException(e1);
        } catch (NoSuchAlgorithmException e1) {
            throw new RuntimeException(e1);
        }
        // Allow TLSv1.2 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
          sslcontext,
          new String[] { "TLSv1.2" },
          null,
          SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        
        HttpResponse resp = new HttpResponse();
        BasicHttpClientConnectionManager connManager;
        connManager = new BasicHttpClientConnectionManager(
                RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
                        .register("https", sslsf)
                        .build(),
                null,
                null,
                null
        );
        
//        HttpResponse resp = new HttpResponse();
//        BasicHttpClientConnectionManager connManager;
//        connManager = new BasicHttpClientConnectionManager(
//                RegistryBuilder.<ConnectionSocketFactory>create()
//                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
//                        .register("https", SSLConnectionSocketFactory.getSocketFactory())
//                        .build(),
//                null,
//                null,
//                null
//        );
        
        CloseableHttpClient client = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();
        try {

            //参数转换
            List<NameValuePair> nameValuePairs = new ArrayList<>();
            for (Map.Entry<String, String> param : params.entrySet()) {
                nameValuePairs.add(new BasicNameValuePair(param.getKey(), param.getValue()));
            }

            HttpPost post = new HttpPost(url);
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(15000).setConnectTimeout(3000).build();
            post.setConfig(requestConfig);
            post.setEntity(new UrlEncodedFormEntity(nameValuePairs, StandardCharsets.UTF_8));

            //发起请求
            CloseableHttpResponse httpResponse = client.execute(post);
            if (httpResponse != null) {
                resp.setHttpCode(httpResponse.getStatusLine().getStatusCode());
                resp.setContentType(httpResponse.getHeaders("Content-Type"));
            }
            if(httpResponse.getEntity() != null) {
                resp.setEntity(EntityUtils.toString(httpResponse.getEntity()));
            }
            
            System.out.println(String.format("http响应结果:code:%s,ContentType:%s,entity%s", 
                resp.getHttpCode(),getContentType(resp.getContentType()),resp.getEntity()));

        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (ClientProtocolException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (client != null) {
                try {
                    client.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }

        return resp;
    }

    private static String getContentType(Header[] contentTypes) {
        String contentType = "";
        if(contentTypes != null) {
            for(Header header : contentTypes) {
                contentType = contentType + header.getValue();
            }
        }
        return contentType;
    }
}
