package cn.com.qmth.examcloud.tool.utils;

import cn.com.qmth.examcloud.tool.config.Constants;
import okhttp3.*;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpHelper {

    private static final Logger log = LoggerFactory.getLogger(HttpHelper.class);

    public static String get(String url, Map<String, String> headers, Map<String, String> params) {
        String urlParams = toUrlParams(params);
        log.debug("[GET] {}, headers: {}, params: {}", url, headers, urlParams);

        String and = url.indexOf("?") < 1 ? "?" : "&";
        Request.Builder builder = new Request.Builder().get().url(url + and + urlParams);
        return call(url, headers, builder);
    }

    public static String post(String url, Map<String, String> headers, Map<String, Object> params) {
        String jsonParams = "{}";
        if (MapUtils.isNotEmpty(params)) {
            jsonParams = new JsonMapper().toJson(params);
        }
        log.debug("[POST] {}, headers: {}, params: {}", url, headers, jsonParams);

        RequestBody requestBody = FormBody.create(jsonParams, MediaType.parse(Constants.CONTENT_TYPE_JSON));
        Request.Builder builder = new Request.Builder().post(requestBody).url(url);
        return call(url, headers, builder);
    }

    public static String put(String url, Map<String, String> headers, Map<String, Object> params) {
        String jsonParams = "{}";
        if (MapUtils.isNotEmpty(params)) {
            jsonParams = new JsonMapper().toJson(params);
        }
        log.debug("[PUT] {}, headers: {}, params: {}", url, headers, jsonParams);

        RequestBody requestBody = FormBody.create(jsonParams, MediaType.parse(Constants.CONTENT_TYPE_JSON));
        Request.Builder builder = new Request.Builder().put(requestBody).url(url);
        return call(url, headers, builder);
    }

    private static String call(String url, Map<String, String> headers, Request.Builder builder) {
        if (MapUtils.isNotEmpty(headers)) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }

        Request request = builder.build();
        try (Response response = HttpClientBuilder.getClient().newCall(request).execute();
                ResponseBody body = response.body();) {
            String bodyStr = body.string();
            if (response.isSuccessful()) {
                return bodyStr;
            }

            log.error("{}, response code: {}, body: {}", url, response.code(), bodyStr);
            if (response.code() == 403) {
                throw new StatusException("禁止访问，请检查认证信息是否错误或已过期！");
            }

            throw new StatusException(bodyStr);
        } catch (IOException e) {
            log.error("{}, error: {}", url, e.getMessage());
            throw new StatusException("接口调用失败！");
        }
    }

    public static String toUrlParams(Map<String, String> params) {
        if (MapUtils.isEmpty(params)) {
            return "";
        }

        List<String> pair = new ArrayList<>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            pair.add(entry.getKey() + "=" + urlEncode(entry.getValue()));
        }

        return StringUtils.join(pair, "&");
    }

    public static String urlEncode(String value) {
        if (StringUtils.isEmpty(value)) {
            return "";
        }
        try {
            return URLEncoder.encode(value, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

}
