package com.cirle.scientific.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import lombok.NonNull;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author heihaier@mmears.com
 * Date: 2018/4/19
 * Time: 17:29
 */
public final class OkHttpUtil {

    private OkHttpUtil() {

    }

    private static OkHttpClient client = new OkHttpClient.
            Builder()
            .connectTimeout(15, TimeUnit.SECONDS)
            .readTimeout(15, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true)
            .addNetworkInterceptor(chain -> chain.proceed(chain.request()))
            .build();

    public static OkHttpClient getInstance() {
        return client;
    }

    public static final MediaType TEXT = MediaType.get("application/text; charset=utf-8");

    public static <T> T get(String url, Class<T> clazz) {
        T t = null;

        try {
            Request request = new Request.Builder()
                    .url(url)
                    .build();
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                t = JSON.parseObject(result, clazz);
            }
        } catch (Exception e) {
        }

        return t;
    }

    public static Boolean get(String url, String queryParams) {
        try {
            Request request = new Request.Builder()
                    .url(url + "?" + queryParams)
                    .build();
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return true;
            }
        } catch (Exception e) {
        }

        return false;
    }

    public static Boolean post(String url, Map<String, String> map) {
        MediaType json = MediaType.parse("application/json; charset=utf-8");
        RequestBody body;
        body = RequestBody.create(json, JSON.toJSONString(map));
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return true;
            }
        } catch (IOException e) {
        }
        return false;
    }

    public static String postA(String url, Map<String, String> map) {
        MediaType json = MediaType.parse("application/json; charset=utf-8");
        RequestBody body;
        body = RequestBody.create(json, JSON.toJSONString(map));
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return response.body().string();
            }
        } catch (IOException e) {
        }
        return "";
    }

    public static Boolean post(String url, JSONObject jsonObject) {
        MediaType json = MediaType.parse("application/json; charset=utf-8");
        RequestBody body;
        body = RequestBody.create(json, JSON.toJSONString(jsonObject));
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return true;
            }
        } catch (IOException e) {
        }
        return false;
    }

    public static Boolean postForm(String url, FormBody formBody) {

        if (StringUtils.isBlank(url) || Objects.isNull(formBody)) {
            System.out.println("url: " + url + ", formBody: " + JSON.toJSONString(formBody));
            return false;
        }
        Request request = new Request.Builder()
                .url(url)
                .post(formBody)
                .build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return true;
            }
        } catch (IOException e) {
            System.out.println(e.toString());
        }
        return false;
    }

    public static <T> T postForm(String url, FormBody formBody, Class<T> clazz) {

        if (StringUtils.isBlank(url) || Objects.isNull(formBody)) {
            System.out.println("url: " + url + ", formBody: " + JSON.toJSONString(formBody));
            return null;
        }

        T t = null;
        Request request = new Request.Builder()
                .url(url)
                .post(formBody)
                .build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                t = JSON.parseObject(result, clazz);
            }
        } catch (IOException e) {
            System.out.println(e.toString());
        }
        return t;
    }

    public static <T> T post(String url, JSONObject jsonObject, Class<T> clazz) {
        T t = null;
        MediaType json = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(json, JSON.toJSONString(jsonObject));
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                t = JSON.parseObject(result, clazz);
            }
        } catch (IOException e) {
            System.out.println(e.toString());
        }
        return t;
    }

    public static <T> T post(String url, Map<String, String> map, Class<T> clazz) {
        T t = null;
        MediaType json = MediaType.parse("application/json; charset=utf-8");
        RequestBody body;
        body = RequestBody.create(json, JSON.toJSONString(map));
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                t = JSON.parseObject(result, clazz);
            }
        } catch (IOException e) {
        }
        return t;
    }

    public static <T> T postForHeader(String url, JSONObject jsonObject, Class<T> clazz, String token) {
        T t = null;
        MediaType json = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(json, JSON.toJSONString(jsonObject));

        Request.Builder requestBuild = new Request.Builder()
                .url(url)
                .post(body);


        if(StringUtils.isNotEmpty(token)){
            requestBuild.addHeader("Authorization", token);
        }
        Request request = requestBuild.build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                t = JSON.parseObject(result, clazz);
            }
        } catch (IOException e) {
        }
        return t;
    }

    public static <T> T post(String url, Map<String, String> map, Map<String, String> header, Class<T> clazz) {
        T t = null;
        MediaType json = MediaType.parse("application/json; charset=utf-8");
        RequestBody body;
        body = RequestBody.create(json, JSON.toJSONString(map));

        Request.Builder builder = new Request.Builder();
        builder.url(url).post(body);
        if (Objects.nonNull(header)) {
            header.forEach((k, v) -> {
                builder.addHeader(k, v);
            });
        }
        Request request = builder.build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                t = JSON.parseObject(result, clazz);
            }
        } catch (IOException e) {
        }
        return t;
    }

    /**
     * get
     *
     * @param url     请求的url
     * @param queries 请求的参数，在浏览器？后面的数据，没有可以传null
     * @return
     */
    public static String get(String url, Map<String, String> queries, String userToken, String wxToken) {
        return get(url, queries, userToken, wxToken, StringUtils.EMPTY);
    }

    public static String get(String url, Map<String, String> queries, String userToken, String wxToken, String traceId) {
        StringBuffer sb = getQueryString(url, queries);
        Request.Builder request = new Request.Builder()
                .url(sb.toString());
        if (StringUtils.isNotBlank(userToken)) {
            request.addHeader("X-USER-TOKEN", userToken);
        }
        if (StringUtils.isNotBlank(wxToken)) {
            request.addHeader("X-USER-TOKEN", wxToken);
        }
        if (StringUtils.isNotBlank(traceId)) {
            request.addHeader("X-USER-TOKEN", traceId);
        }
        Request build = request.build();
        try {
            Response response = client.newCall(build).execute();
            if (response.isSuccessful() && response.body() != null) {
                return response.body().string();
            }
        } catch (IOException e) {
        }
        return null;
    }

    /**
     * 根据map获取get请求参数
     *
     * @param queries
     * @return
     */
    public static StringBuffer getQueryString(String url, Map<String, String> queries) {
        StringBuffer sb = new StringBuffer(url);
        if (queries != null && queries.keySet().size() > 0) {
            boolean firstFlag = true;
            Iterator iterator = queries.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry<String, String>) iterator.next();
                if (firstFlag) {
                    sb.append("?" + entry.getKey() + "=" + entry.getValue());
                    firstFlag = false;
                } else {
                    sb.append("&" + entry.getKey() + "=" + entry.getValue());
                }
            }
        }
        return sb;
    }

    public static <T> T post(String url, String requestBody, Class<T> clazz) {
        T t = null;
        MediaType json = MediaType.parse("application/json; charset=utf-8");
        RequestBody body;
        body = RequestBody.create(json, requestBody);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                //log.info("result:{}", result);
                t = JSON.parseObject(result, clazz);
            }
        } catch (IOException e) {
        }
        return t;
    }

    public static <T> T post(String url, String requestBody, Map<String, String> header, Class<T> clazz) {
        T t = null;
        MediaType json = MediaType.parse("application/json; charset=utf-8");
        RequestBody body;
        body = RequestBody.create(json, requestBody);

        Request.Builder builder = new Request.Builder();
        builder.url(url).post(body);
        if (Objects.nonNull(header)) {
            header.forEach((k, v) -> {
                builder.addHeader(k, v);
            });
        }
        Request request = builder.build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                t = JSON.parseObject(result, clazz);
            }
        } catch (IOException e) {
        }
        return t;
    }

    public static <T> T post(String url, String requestBody, TypeReference<T> typeReference) {
        T t = null;
        MediaType json = MediaType.parse("application/json; charset=utf-8");
        RequestBody body;
        body = RequestBody.create(json, requestBody);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                t = JSON.parseObject(result, typeReference);
                new TypeReference<Long>() {
                };
            }
        } catch (IOException e) {
        }
        return t;
    }

    public static String postText(@NonNull String url, String content) {
        RequestBody body = RequestBody.create(TEXT, content);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try (Response response = OkHttpUtil.getInstance().newCall(request).execute()) {
            return response.body().string();
        } catch (IOException e) {
            return null;
        }
    }
}
