package com.bonait.bnframework.HBL.API;

import com.bonait.bnframework.HBL.Interface.IRunT;
import com.bonait.bnframework.HBL.Logs.MessageLog;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

public class APIHelper {

    private static String key="64059261-1599-472c-b418-3c18b4e3883e";

    /**
     * 获取加密后的签名
     * @param t
     * @return
     */
    public static String GetSign(Object t,String key){
        AtomicReference<String> retstr = new AtomicReference<>("");
        List<Field> fields = Arrays.asList(t.getClass().getFields());
        Collections.sort(fields, Comparator.comparing(Field::getName));
        fields.forEach(item->{
            if( item.getName().toUpperCase()!="sign".toUpperCase()){
                try {
                    if(item.get(t)!=null&&!item.get(t).toString().isEmpty()){
                        Type type = item.getGenericType();
                        String typeName = type.toString();
                        switch(typeName){
                            case "class java.util.Date":
                            case "class java.lang.String":
                            case "byte":
                            case "int":
                            case "float":
                            case "double":
                            case "long":
                            case "short":
                            case "boolean":
                                retstr.set(retstr.get() + item.getName() + "=" + item.get(t) + "&");
                                break;
                            default:
//                             String a= new GsonBuilder().serializeNulls().create().toJson(item.get(t));//保留为空的属性
                                String a= new Gson().toJson(item.get(t));
                                retstr.set(retstr.get() + item.getName() + "=" + a + "&");
                                break;
                        }
                    }
                } catch (Exception e) {
                }
            }
        });
        String tempSign="&key="+key;
        if(retstr.get().length()>0){
            tempSign=retstr.get().substring(0, retstr.get().length()-1)+"&key="+key;
        }
//        String tempSign=retstr.get().substring(0, retstr.get().length()-1)+"&key="+key;
        StringBuilder sb = new StringBuilder();
        try{
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(tempSign.toUpperCase().getBytes());
            for (byte b : digest) {
                sb.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1,3));
            }
        }catch (Exception e){

        }
        return sb.toString().toUpperCase();
    }

    public static String Post(String url, Map<String, String> parameters, Map<String, String> headers) throws IOException {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        BufferedReader reader = null;
        StringBuffer buffer = new StringBuffer();
        try {
            URL requestUrl = new URL(url);
            connection = (HttpURLConnection) requestUrl.openConnection();
            connection.setRequestMethod("POST");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            // 设置header
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    connection.setRequestProperty(entry.getKey(), entry.getValue());
                }
            }
            // 设置参数
            if (parameters != null) {
                StringBuilder stringBuilder = new StringBuilder();
                for (Map.Entry<String, String> entry : parameters.entrySet()) {
                    stringBuilder.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&");
                }
                String params = stringBuilder.toString();
                byte[] postData = params.getBytes("UTF-8");
                connection.setRequestProperty("Content-Length", Integer.toString(postData.length));
                try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
                    outputStream.write(postData);
                }
            }
            // 获取响应结果
            int statusCode = connection.getResponseCode();
            if (statusCode == HttpURLConnection.HTTP_OK) {
                inputStream = connection.getInputStream();
                reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                String line;
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                }
            } else {
                throw new IOException("服务器返回错误，状态码：" + statusCode);
            }
        }catch (Exception e){
            MessageLog.ShowError("POST 请求异常:"+e.toString());
        }finally {
            // 关闭连接和流
            if (reader != null) {
                reader.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return buffer.toString();
    }
    public static String Post(String url, String body, Map<String, String> headers) throws IOException {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        BufferedReader reader = null;
        StringBuffer buffer = new StringBuffer();
        try {
            URL requestUrl = new URL(url);
            connection = (HttpURLConnection) requestUrl.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");// "Fiddler"
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Charset", "UTF-8");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            // 设置header
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    connection.setRequestProperty(entry.getKey(), entry.getValue());
                }
            }
            // 设置参数
            if (!body .isEmpty()) {
                connection.setRequestProperty("Content-Length", Integer.toString(body.getBytes().length));
                try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
                    outputStream.write(body.getBytes());
                }
            }
            // 获取响应结果
            int statusCode = connection.getResponseCode();
            if (statusCode == HttpURLConnection.HTTP_OK) {
                inputStream = connection.getInputStream();
                reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                String line;
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                }
            } else {
                throw new IOException("服务器返回错误，状态码：" + statusCode);
            }
        }catch (Exception e){
            MessageLog.ShowError("POST 请求异常:"+e.toString());
        }finally {
            // 关闭连接和流
            if (reader != null) {
                reader.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return buffer.toString();
    }
    public static String Post(String url, Object body, Map<String, String> headers) throws IOException {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        BufferedReader reader = null;
        StringBuffer buffer = new StringBuffer();
        try {
            URL requestUrl = new URL(url);
            connection = (HttpURLConnection) requestUrl.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");// "Fiddler"
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Charset", "UTF-8");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            // 设置header
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    connection.setRequestProperty(entry.getKey(), entry.getValue());
                }
            }
            // 设置参数
            if (body !=null) {
                byte[] bytes = new Gson().toJson(body).getBytes();
                connection.setRequestProperty("Content-Length", Integer.toString(bytes.length));
                try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
                    outputStream.write(bytes);
                }
            }
            // 获取响应结果
            int statusCode = connection.getResponseCode();
            if (statusCode == HttpURLConnection.HTTP_OK) {
                inputStream = connection.getInputStream();
                reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                String line;
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                }
            } else {
                throw new IOException("服务器返回错误，状态码：" + statusCode);
            }
        }catch (Exception e){
            MessageLog.ShowError("POST 请求异常:"+e.toString());
        }finally {
            // 关闭连接和流
            if (reader != null) {
                reader.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return buffer.toString();
    }
    public static void Post(String url, Object body, IRunT<APIResult> callback) {
        new Thread(()->{
            HttpURLConnection connection = null;
            InputStream inputStream = null;
            BufferedReader reader = null;
            StringBuffer buffer = new StringBuffer();
            try {
                URL requestUrl = new URL(url);
                connection = (HttpURLConnection) requestUrl.openConnection();
                connection.setRequestMethod("POST");
                connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");// "Fiddler"
                connection.setRequestProperty("Content-Type", "application/json");
                connection.setRequestProperty("Charset", "UTF-8");
                connection.setConnectTimeout(5000);
                connection.setReadTimeout(5000);
                connection.setDoOutput(true);
                connection.setDoInput(true);

                if(body!=null){
                    //获取签名信息
                    String sign = GetSign(body,key);

                    //设置请求头
                    connection.setRequestProperty("key", key);
                    connection.setRequestProperty("sign", sign);


                    //设置请求 body
                    byte[] bytes = new Gson().toJson(body).getBytes();
                    connection.setRequestProperty("Content-Length", Integer.toString(bytes.length));
                    try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
                        outputStream.write(bytes);
                    }
                }

                // 获取响应结果
                int statusCode = connection.getResponseCode();
                if (statusCode == HttpURLConnection.HTTP_OK) {
                    inputStream = connection.getInputStream();
                    reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                    String line;
                    while ((line = reader.readLine()) != null) {
                        buffer.append(line);
                    }
                } else {
                    throw new IOException("服务器返回错误，状态码：" + statusCode);
                }
            }catch (Exception e){
                MessageLog.ShowError("POST 请求异常:"+e.toString());
                return;
            }finally {
                try{
                    // 关闭连接和流
                    if (reader != null)  reader.close();

                    if (inputStream != null)  inputStream.close();

                    if (connection != null)  connection.disconnect();

                }catch(Exception e){
                    MessageLog.ShowError("POST 请求异常:"+e.toString());
                    return;
                }
            }

            try{
                APIResult res =  new GsonBuilder().serializeNulls().create().fromJson(buffer.toString(), APIResult.class);
                if(res!=null)if(callback!=null) callback.Run(res);
            }catch(Exception e){

            }
        }).start();

    }
    public static void Post(String url, Object body,String signkey, IRunT<APIResult> callback) {
        new Thread(()->{
            HttpURLConnection connection = null;
            InputStream inputStream = null;
            BufferedReader reader = null;
            StringBuffer buffer = new StringBuffer();
            try {
                URL requestUrl = new URL(url);
                connection = (HttpURLConnection) requestUrl.openConnection();
                connection.setRequestMethod("POST");
                connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");// "Fiddler"
                connection.setRequestProperty("Content-Type", "application/json");
                connection.setRequestProperty("Charset", "UTF-8");
                connection.setConnectTimeout(5000);
                connection.setReadTimeout(5000);
                connection.setDoOutput(true);
                connection.setDoInput(true);

                if(body!=null){
                    //获取签名信息
                    String sign = GetSign(body,signkey);

                    MessageLog.ShowInfo("签名信息："+sign);

                    //设置请求头
                    connection.setRequestProperty("key", signkey);
//                    connection.setRequestProperty("sign", sign);


                    //设置请求 body
                    byte[] bytes = new Gson().toJson(body).getBytes();
                    connection.setRequestProperty("Content-Length", Integer.toString(bytes.length));
                    try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
                        outputStream.write(bytes);
                    }
                }

                // 获取响应结果
                int statusCode = connection.getResponseCode();
                if (statusCode == HttpURLConnection.HTTP_OK) {
                    inputStream = connection.getInputStream();
                    reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                    String line;
                    while ((line = reader.readLine()) != null) {
                        buffer.append(line);
                    }
                } else {
                    throw new IOException("服务器返回错误，状态码：" + statusCode);
                }
            }catch (Exception e){
                MessageLog.ShowError("POST 请求异常:"+e.toString());
                return;
            }finally {
                try{
                    // 关闭连接和流
                    if (reader != null)  reader.close();

                    if (inputStream != null)  inputStream.close();

                    if (connection != null)  connection.disconnect();

                }catch(Exception e){
                    MessageLog.ShowError("POST 请求异常:"+e.toString());
                    return;
                }
            }

            try{
                APIResult res =  new GsonBuilder().serializeNulls().create().fromJson(buffer.toString(), APIResult.class);
                if(res!=null)if(callback!=null) callback.Run(res);
            }catch(Exception e){
                MessageLog.ShowError("POST 请求异常:"+e.toString());
            }
        }).start();

    }

    public static <T> void PostT(String url, Object body,String signkey ,IRunT<APIResultT<T>> callback) {
        new Thread(()->{
            HttpURLConnection connection = null;
            InputStream inputStream = null;
            BufferedReader reader = null;
            StringBuffer buffer = new StringBuffer();
            try {
                URL requestUrl = new URL(url);
                connection = (HttpURLConnection) requestUrl.openConnection();
                connection.setRequestMethod("POST");
                connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");// "Fiddler"
                connection.setRequestProperty("Content-Type", "application/json");
                connection.setRequestProperty("Charset", "UTF-8");
                connection.setConnectTimeout(5000);
                connection.setReadTimeout(5000);
                connection.setDoOutput(true);
                connection.setDoInput(true);

                if(body!=null){
                    //获取签名信息
                    String sign = GetSign(body,signkey);

                    //设置请求头
                    connection.setRequestProperty("key", signkey);
                    connection.setRequestProperty("sign", sign);


                    //设置请求 body
                    byte[] bytes = new Gson().toJson(body).getBytes();
                    connection.setRequestProperty("Content-Length", Integer.toString(bytes.length));
                    try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
                        outputStream.write(bytes);
                    }
                }

                // 获取响应结果
                int statusCode = connection.getResponseCode();
                if (statusCode == HttpURLConnection.HTTP_OK) {
                    inputStream = connection.getInputStream();
                    reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                    String line;
                    while ((line = reader.readLine()) != null) {
                        buffer.append(line);
                    }
                } else {
                    throw new IOException("服务器返回错误，状态码：" + statusCode);
                }
            }catch (Exception e){
                MessageLog.ShowError("POST 请求异常:"+e.toString());
                return;
            }finally {
                try{
                    // 关闭连接和流
                    if (reader != null)  reader.close();
                    if (inputStream != null)  inputStream.close();
                    if (connection != null)  connection.disconnect();
                }catch(Exception e){
                    MessageLog.ShowError("POST 请求异常:"+e.toString());
                    return;
                }
            }
            try{

                APIResultT<T> res =  new GsonBuilder().serializeNulls().create().fromJson(buffer.toString(), APIResultT.class);
                if(res!=null)if(callback!=null) callback.Run(res);
            }catch(Exception e){
                MessageLog.ShowError("POST请求返回值解析异常，"+e.toString());
            }
        }).start();

    }
    public static void get(String urlAdd,Map<String,String> params,IRunT<String> callback) {
        new Thread(()->{
            try {
                String ResponseAdd = BuildUrlWithParams(urlAdd,params);//请求地址和参数
                URL url = new URL(ResponseAdd);
                HttpURLConnection Connection = (HttpURLConnection) url.openConnection();
                Connection.setRequestMethod("GET");
                Connection.setConnectTimeout(3000);
                Connection.setReadTimeout(3000);
                int responseCode = Connection.getResponseCode();
                if (responseCode == Connection.HTTP_OK) {
                    InputStream inputStream = Connection.getInputStream();
                    ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
                    byte[] bytes = new byte[1024];
                    int length = 0;
                    while ((length = inputStream.read(bytes)) != -1) {
                        arrayOutputStream.write(bytes, 0, length);
                        arrayOutputStream.flush();//强制释放缓冲区
                    }
                    String s = arrayOutputStream.toString();
                    if(callback!=null)callback.Run(s);
                } else {
                    MessageLog.ShowError("get 请求失败");
                }
            } catch (Exception e) {
                MessageLog.ShowError(e);
            }
        }).start();
    }

    /**
     * 请求参数拼接
     * @param Url 请求地址
     * @param params 请求参数
     * @return
     */
    public static String BuildUrlWithParams(String Url,Map<String,String> params){
        StringBuilder sb = new StringBuilder(Url);
        if(params!=null&&!params.isEmpty()){
            sb.append("?");

            params.forEach((key,value)->{
                sb.append(key).append("=").append(value).append("&");
            });

            sb.deleteCharAt(sb.length()-1);
        }
        return sb.toString();
    }

}
