package com.seeyon.apps.esign.utils;

import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * @ClassName: HttpClient
 * @Description: HTTP请求工具类
 * @Author: GiikJc
 * @Date: 2022/7/12 15:03
 */

/**
 * 发送Get请求：HttpResponse httpGet(String url,Map<String,String> headers,String encode)
 *发送Post请求，同表单Post提交：HttpResponse httpPostForm(String url,Map<String,String> params, Map<String,String> headers,String encode)
 *发送Post Raw请求：HttpResponse httpPostRaw(String url,String stringJson,Map<String,String> headers, String encode)
 *发送Put Raw请求：HttpResponse httpPutRaw(String url,String stringJson,Map<String,String> headers, String encode)
 *发送Delete请求：HttpResponse httpDelete(String url,Map<String,String> headers,String encode)
 */
public class HttpClient {

    /**
     * 发送 HTTP GET 请求下载文件
     * @param url 下载文件的 URL
     * @param headers 请求头
     * @param savePath 文件保存的路径
     * @param encode 文件内容的编码
     * @return 下载成功返回 true，失败返回 false
     */
    public static boolean httpDownloadFile(String url, Map<String, String> headers, String savePath, String encode) {
        if (encode == null) {
            encode = "utf-8";  // 默认字符编码
        }

        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            // 创建 HttpClient 实例
            httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(url);

            // 设置请求头
            if (headers != null && headers.size() > 0) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpGet.setHeader(entry.getKey(), entry.getValue());
                }
            }

            // 执行请求
            httpResponse = httpClient.execute(httpGet);
            HttpEntity entity = httpResponse.getEntity();

            // 检查响应状态码
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                inputStream = entity.getContent();

                // 创建输出流，将文件保存到本地
                outputStream = new FileOutputStream(savePath);

                // 设置缓冲区
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }

                // 文件下载成功
                return true;
            } else {
                System.out.println("Download failed, HTTP error code: " + httpResponse.getStatusLine().getStatusCode());
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
                if (httpResponse != null) {
                    httpResponse.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 对queryString参数按key进行字典序升序排序
     * @param queryString 原始参数字符串，如"b=2&a=1&c=3"
     * @return 排序后的字符串，如"a=1&b=2&c=3"
     */
    public static String sortQueryString(String queryString) {
        if (queryString == null || queryString.isEmpty()) {
            return queryString;
        }

        String[] pairs = queryString.split("&");
        Map<String, String> params = new TreeMap<>();

        for (String pair : pairs) {
            String[] kv = pair.split("=");
            if (kv.length == 2) {
                params.put(kv[0], kv[1]);
            } else if (kv.length == 1) {
                params.put(kv[0], "");
            }
        }

        return params.entrySet().stream()
                .map(entry -> entry.getKey() + "=" + entry.getValue())
                .collect(Collectors.joining("&"));
    }
    /**
     * 发送http get请求
     */
    public static String httpGet(String url,Map<String,String> headers,String encode){

        if(encode == null){
            encode = "utf-8";
        }
        CloseableHttpResponse httpResponse = null;
        CloseableHttpClient closeableHttpClient = null;
        String content = null;
        //since 4.3 不再使用 DefaultHttpClient
        try {
            closeableHttpClient = HttpClientBuilder.create().build();
            HttpGet httpGet = new HttpGet(url);
            //设置header
            if (headers != null && headers.size() > 0) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpGet.setHeader(entry.getKey(),entry.getValue());
                }
            }

            httpResponse = closeableHttpClient.execute(httpGet);
            HttpEntity entity = httpResponse.getEntity();
            content = EntityUtils.toString(entity, encode);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                httpResponse.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {  //关闭连接、释放资源
            closeableHttpClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }
    /**
     * 发送 http post 请求，参数以form表单键值对的形式提交。
     */
    public static String httpPostForm(String url,Map<String,String> params, Map<String,String> headers,String encode){

        if(encode == null){
            encode = "utf-8";
        }

        String content = null;
        CloseableHttpResponse  httpResponse = null;
        CloseableHttpClient closeableHttpClient = null;
        try {

            closeableHttpClient = HttpClients.createDefault();
            HttpPost httpost = new HttpPost(url);

            //设置header
            if (headers != null && headers.size() > 0) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpost.setHeader(entry.getKey(),entry.getValue());
                }
            }
            //组织请求参数
            List<NameValuePair> paramList = new ArrayList <NameValuePair>();
            if(params != null && params.size() > 0){
                Set<String> keySet = params.keySet();
                for(String key : keySet) {
                    paramList.add(new BasicNameValuePair(key, params.get(key)));
                }
            }
            httpost.setEntity(new UrlEncodedFormEntity(paramList, encode));


            httpResponse = closeableHttpClient.execute(httpost);
            HttpEntity entity = httpResponse.getEntity();
            content = EntityUtils.toString(entity, encode);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                httpResponse.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {  //关闭连接、释放资源
            closeableHttpClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }

    /**
     * 发送 http post 请求，参数以原生字符串进行提交
     * @param url
     * @param encode
     * @return
     */
    public static String httpPostRaw(String url,String stringJson,Map<String,String> headers, String encode){
        if(encode == null){
            encode = "utf-8";
        }
        String content = null;
        CloseableHttpResponse  httpResponse = null;
        CloseableHttpClient closeableHttpClient = null;
        try {

            //HttpClients.createDefault()等价于 HttpClientBuilder.create().build();
            closeableHttpClient = HttpClients.createDefault();
            HttpPost httpost = new HttpPost(url);

            //设置header
            httpost.setHeader("Content-type", "application/json");
            if (headers != null && headers.size() > 0) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpost.setHeader(entry.getKey(),entry.getValue());
                }
            }
            //组织请求参数
            StringEntity stringEntity = new StringEntity(stringJson, encode);
            httpost.setEntity(stringEntity);


            //响应信息
            httpResponse = closeableHttpClient.execute(httpost);
            HttpEntity entity = httpResponse.getEntity();
            content = EntityUtils.toString(entity, encode);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                httpResponse.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {  //关闭连接、释放资源
            closeableHttpClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }

    /**
     * 发送 http put 请求，参数以原生字符串进行提交
     * @param url
     * @param encode
     * @return
     */
    public static String httpPutRaw(String url,String stringJson,Map<String,String> headers, String encode){
        if(encode == null){
            encode = "utf-8";
        }
        CloseableHttpResponse httpResponse = null;
        CloseableHttpClient closeableHttpClient = null;
        String content = null;
        //since 4.3 不再使用 DefaultHttpClient
        try {

            //HttpClients.createDefault()等价于 HttpClientBuilder.create().build();
            closeableHttpClient = HttpClients.createDefault();
            HttpPut httpput = new HttpPut(url);

            //设置header
            httpput.setHeader("Content-type", "application/json");
            if (headers != null && headers.size() > 0) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpput.setHeader(entry.getKey(),entry.getValue());
                }
            }
            //组织请求参数
            StringEntity stringEntity = new StringEntity(stringJson, encode);
            httpput.setEntity(stringEntity);
            //响应信息
            httpResponse = closeableHttpClient.execute(httpput);
            HttpEntity entity = httpResponse.getEntity();
            content = EntityUtils.toString(entity, encode);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                httpResponse.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            closeableHttpClient.close();  //关闭连接、释放资源
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }
    /**
     * 发送http delete请求
     */
    public static String httpDelete(String url,Map<String,String> headers,String encode){
        if(encode == null){
            encode = "utf-8";
        }
        String content = null;
        CloseableHttpResponse  httpResponse = null;
        CloseableHttpClient closeableHttpClient = null;
        try {
            //since 4.3 不再使用 DefaultHttpClient
            closeableHttpClient = HttpClientBuilder.create().build();
            HttpDelete httpdelete = new HttpDelete(url);
            //设置header
            if (headers != null && headers.size() > 0) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpdelete.setHeader(entry.getKey(),entry.getValue());
                }
            }

            httpResponse = closeableHttpClient.execute(httpdelete);
            HttpEntity entity = httpResponse.getEntity();
            content = EntityUtils.toString(entity, encode);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                httpResponse.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {   //关闭连接、释放资源
            closeableHttpClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }

    /**
     * 发送 http post 请求，支持文件上传
     */
    public static String httpPostFormMultipart(String url,Map<String,String> params, List<File> files,Map<String,String> headers,String encode){
        if(encode == null){
            encode = "utf-8";
        }
        CloseableHttpResponse httpResponse = null;
        CloseableHttpClient closeableHttpClient = null;
        String content = null;
        //since 4.3 不再使用 DefaultHttpClient
        try {

            closeableHttpClient = HttpClients.createDefault();
            HttpPost httpost = new HttpPost(url);

            //设置header
            if (headers != null && headers.size() > 0) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpost.setHeader(entry.getKey(),entry.getValue());
                }
            }
            MultipartEntityBuilder mEntityBuilder = MultipartEntityBuilder.create();
            mEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            mEntityBuilder.setCharset(Charset.forName(encode));

            // 普通参数
            ContentType contentType = ContentType.create("text/plain",Charset.forName(encode));//解决中文乱码
            if (params != null && params.size() > 0) {
                Set<String> keySet = params.keySet();
                for (String key : keySet) {
                    mEntityBuilder.addTextBody(key, params.get(key),contentType);
                }
            }
            //二进制参数
            if (files != null && files.size() > 0) {
                for (File file : files) {
                    mEntityBuilder.addBinaryBody("file", file);
                }
            }
            httpost.setEntity(mEntityBuilder.build());
            httpResponse = closeableHttpClient.execute(httpost);
            HttpEntity entity = httpResponse.getEntity();
            content = EntityUtils.toString(entity, encode);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                httpResponse.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {  //关闭连接、释放资源
            closeableHttpClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }


    public static String uploadBinaryFile(String url, Map<String,String> headers,
                                          InputStream io, String fileName) throws IOException {

        CloseableHttpClient client = HttpClients.createDefault();
        HttpPut put = new HttpPut(url);
        String responseBody = null;

        try {
            // 设置请求头
            for (String key : headers.keySet()) {
                put.addHeader(key, headers.get(key));
            }

            // 构建多部分实体
            MultipartEntityBuilder builder = MultipartEntityBuilder.create()
                    .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
                    .setCharset(Charset.forName("UTF-8"));
            builder.addBinaryBody("file", io, ContentType.MULTIPART_FORM_DATA, fileName);

            put.setEntity(builder.build());

            // 执行请求
            CloseableHttpResponse response = null;
            try {
                response = client.execute(put);
                HttpEntity resEntity = response.getEntity();
                responseBody = EntityUtils.toString(resEntity, "UTF-8");

                // 无论状态码如何，都返回响应体
                return responseBody;

            } finally {
                if(response != null) {
                    response.close();
                }
            }
        } finally {
            client.close();
            io.close();
        }
    }

}