package cn.com.taiji.dataService.utils;

import cn.com.digitalhainan.apione.sdk.ApioneSignature;
import cn.com.digitalhainan.apione.sdk.HttpCaller;
import cn.com.digitalhainan.apione.sdk.HttpParameters;
import cn.com.digitalhainan.apione.sdk.HttpReturn;
import cn.com.digitalhainan.apione.utils.LogUtils;
import cn.com.digitalhainan.apione.utils.ObjectUtils;
import okhttp3.*;
import okhttp3.internal.http.HttpMethod;

import java.io.IOException;
import java.util.concurrent.TimeUnit;


import cn.com.digitalhainan.apione.utils.LogUtils;
import cn.com.digitalhainan.apione.utils.ObjectUtils;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.internal.http.HttpMethod;

public class MyHttpCaller {
        private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        public static final String CONNECT_TIMEOUT_KEY = "apione.http.connect.timeout";
        public static final String READ_TIMEOUT_KEY = "apione.http.read.timeout";
        public static final String WRITE_TIMEOUT_KEY = "apione_http.write.timeout";
        private static final String REGION_KEY = "region";
        private static final String REQUEST_ID = "x-request-id";
        private static final String PATH_KEY = "x-http-path";
        private static final String QUERY_KEY = "x-http-query";
        private OkHttpClient client;

        private MyHttpCaller() {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.connectTimeout((long)Integer.parseInt(System.getProperty("apione.http.connect.timeout", "60")), TimeUnit.SECONDS);
            builder.readTimeout((long)Integer.parseInt(System.getProperty("apione.http.read.timeout", "60")), TimeUnit.SECONDS);
            builder.writeTimeout((long)Integer.parseInt(System.getProperty("apione_http.write.timeout", "60")), TimeUnit.SECONDS);
            this.client = builder.build();
        }

        public static cn.com.taiji.dataService.utils.MyHttpCaller getInstance() {
            return cn.com.taiji.dataService.utils.MyHttpCaller.OkHttpHolder.INSTANCE;
        }

        public HttpReturn call(HttpParameters httpParameters) {
            this.assertParams(httpParameters);
            String sign = ApioneSignature.sign(httpParameters.getApi(), httpParameters.getAccessKey(), httpParameters.getDate().getTime(), httpParameters.getSecretKey(), httpParameters.getFormParamsMap(), httpParameters.getVersion());
            RequestBody body = null;
            if (httpParameters.getContentBody() != null) {
                body = RequestBody.create(httpParameters.getMediaType(), httpParameters.getContentBody().getJsonBody());
            } else if (httpParameters.getMediaType().type().toLowerCase().contains("form") && !ObjectUtils.isEmpty(httpParameters.getFormParamsMap())) {
                body = RequestBody.create(httpParameters.getMediaType(), map2Form(httpParameters.getFormParamsMap()));
            }

            if (body == null && HttpMethod.requiresRequestBody(httpParameters.getMethod())) {
                body = RequestBody.create(httpParameters.getMediaType(), "");
            }

            HttpUrl.Builder urlBuilder = HttpUrl.parse(httpParameters.getRequestUrl()).newBuilder();
            Request.Builder builder = (new Request.Builder()).method(httpParameters.getMethod(), body);
            if (!ObjectUtils.isEmpty(httpParameters.getQueryParamsMap())) {
                httpParameters.getQueryParamsMap().forEach(urlBuilder::addQueryParameter);
            }

            TreeMap<String, String> sortedHeaderMap = new TreeMap(this.commonHeader(httpParameters, sign));
            if (httpParameters.getHeaderParamsMap() != null) {
                sortedHeaderMap.putAll(httpParameters.getHeaderParamsMap());
            }

            sortedHeaderMap.forEach(builder::header);
            HttpReturn httpReturn = new HttpReturn();

            try {
                Request request = builder.url(urlBuilder.build()).build();
                Response response = this.client.newCall(request).execute();
                httpReturn.setResponseHttpStatus(response.code()).setResponse(response.body().string());
                response.headers().toMultimap().forEach((key, values) -> {
                    String var10000 = (String)httpReturn.getRespHttpHeaderMap().put(key, values.get(0));
                });
                return httpReturn;
            } catch (IOException var10) {
                LogUtils.error("call url:{} api:{} error:{}", new Object[]{httpParameters.getRequestUrl(), httpParameters.getApi(), var10.getMessage()});
                return httpReturn;
            }
        }

    public HttpByteReturn callByte(HttpParameters httpParameters) {
        this.assertParams(httpParameters);
        String sign = ApioneSignature.sign(httpParameters.getApi(), httpParameters.getAccessKey(), httpParameters.getDate().getTime(), httpParameters.getSecretKey(), httpParameters.getFormParamsMap(), httpParameters.getVersion());
        RequestBody body = null;
        if (httpParameters.getContentBody() != null) {
            body = RequestBody.create(httpParameters.getMediaType(), httpParameters.getContentBody().getJsonBody());
        } else if (httpParameters.getMediaType().type().toLowerCase().contains("form") && !ObjectUtils.isEmpty(httpParameters.getFormParamsMap())) {
            body = RequestBody.create(httpParameters.getMediaType(), map2Form(httpParameters.getFormParamsMap()));
        }

        if (body == null && HttpMethod.requiresRequestBody(httpParameters.getMethod())) {
            body = RequestBody.create(httpParameters.getMediaType(), "");
        }

        HttpUrl.Builder urlBuilder = HttpUrl.parse(httpParameters.getRequestUrl()).newBuilder();
        Request.Builder builder = (new Request.Builder()).method(httpParameters.getMethod(), body);
        if (!ObjectUtils.isEmpty(httpParameters.getQueryParamsMap())) {
            httpParameters.getQueryParamsMap().forEach(urlBuilder::addQueryParameter);
        }

        TreeMap<String, String> sortedHeaderMap = new TreeMap(this.commonHeader(httpParameters, sign));
        if (httpParameters.getHeaderParamsMap() != null) {
            sortedHeaderMap.putAll(httpParameters.getHeaderParamsMap());
        }

        sortedHeaderMap.forEach(builder::header);
        HttpByteReturn httpReturn = new HttpByteReturn();

        try {
            Request request = builder.url(urlBuilder.build()).build();
            Response response = this.client.newCall(request).execute();
            httpReturn.setResponseHttpStatus(response.code()).setResponse(response.body().byteStream());
            response.headers().toMultimap().forEach((key, values) -> {
                String var10000 = (String)httpReturn.getRespHttpHeaderMap().put(key, values.get(0));
            });
            return httpReturn;
        } catch (IOException var10) {
            LogUtils.error("call url:{} api:{} error:{}", new Object[]{httpParameters.getRequestUrl(), httpParameters.getApi(), var10.getMessage()});
            return httpReturn;
        }
    }

        public static String map2Form(Map<String, String> map) {
            StringBuilder stringBuilder = new StringBuilder();
            if (map == null) {
                return stringBuilder.toString();
            } else {
                Iterator var2 = map.entrySet().iterator();

                while(var2.hasNext()) {
                    Map.Entry<String, String> entry = (Map.Entry)var2.next();
                    stringBuilder.append((String)entry.getKey()).append("=").append((String)entry.getValue()).append("&");
                }

                return stringBuilder.substring(0, stringBuilder.length() - 1);
            }
        }

        private void assertParams(HttpParameters httpParameters) {
            if (httpParameters.getMethod() == null) {
                httpParameters.setMethod("POST");
            }

            if (httpParameters.getMediaType() == null) {
                httpParameters.setMediaType(JSON);
            }

            if (httpParameters.getDate() == null) {
                httpParameters.setDate(new Date());
            }

            if (ObjectUtils.isEmpty(httpParameters.getVersion())) {
                httpParameters.setVersion("1.0");
            }

            if (ObjectUtils.isEmpty(httpParameters.getAccessKey())) {
                throw new RuntimeException("Miss ak");
            } else if (ObjectUtils.isEmpty(httpParameters.getSecretKey())) {
                throw new RuntimeException("Miss sk");
            } else if (ObjectUtils.isEmpty(httpParameters.getApi())) {
                throw new RuntimeException("Miss api name");
            } else if (ObjectUtils.isEmpty(httpParameters.getRequestUrl())) {
                throw new RuntimeException("Miss request url");
            }
        }

        private Map<String, String> commonHeader(HttpParameters httpParameters, String sign) {
            Map<String, String> headerMap = new HashMap();
            headerMap.put("_api_name", httpParameters.getApi());
            headerMap.put("_api_access_key", httpParameters.getAccessKey());
            headerMap.put("_api_signature", sign);
            headerMap.put("_api_version", httpParameters.getVersion());
            headerMap.put("_api_timestamp", httpParameters.getDate().getTime() + "");
            String requestId = UUID.randomUUID().toString().replaceAll("-", "");
            headerMap.put("x-request-id", requestId);
            LogUtils.info("apione trace api = {} ,requestId = {}", new Object[]{httpParameters.getApi(), requestId});
            if (!ObjectUtils.isEmpty(httpParameters.getRegion())) {
                headerMap.put("region", httpParameters.getRegion());
            }

            if (!ObjectUtils.isEmpty(httpParameters.getPath())) {
                if (!httpParameters.getPath().startsWith("/")) {
                    httpParameters.setPath("/" + httpParameters.getPath());
                }

                headerMap.put("x-http-path", httpParameters.getPath());
            }

            return headerMap;
        }

        private String getUrlParamsByMap(Map<String, String> map) {
            if (map == null) {
                return "";
            } else {
                StringBuffer sb = new StringBuffer();
                Iterator var3 = map.entrySet().iterator();

                while(var3.hasNext()) {
                    Map.Entry<String, String> entry = (Map.Entry)var3.next();
                    sb.append((String)entry.getKey() + "=" + (String)entry.getValue());
                    sb.append("&");
                }

                String s = sb.toString();
                if (s.endsWith("&")) {
                    s = ObjectUtils.substringBeforeLast(s, "&");
                }

                return s;
            }
        }

        private static class OkHttpHolder {
            private static final MyHttpCaller INSTANCE = new MyHttpCaller();

            private OkHttpHolder() {
            }
        }



}
