package net.northking.cctp.device.util.prometheus;

import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import net.northking.cctp.common.exception.PlatformRuntimeException;
import net.northking.cctp.device.constants.DeviceError;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.net.URLEncoder;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class PrometheusClient {

    private static final Gson gson = new Gson();

    private static final CloseableHttpClient httpClient;

    static {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setDefaultSocketConfig(SocketConfig.custom()
                .setSoReuseAddress(true)
                .setTcpNoDelay(true)
                .build());
        connectionManager.setDefaultMaxPerRoute(200);
        RequestConfig.Builder requestConfig = RequestConfig.custom()
                .setSocketTimeout(3 * 1000)
                .setConnectTimeout(3 * 1000)
                .setConnectionRequestTimeout(5 * 1000);
        httpClient = HttpClientBuilder.create()
                .setConnectionTimeToLive(1, TimeUnit.MINUTES)
                .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(requestConfig.build())
                .build();
    }

    public static PrometheusTargets queryTargets(String ipPort) {
        String url = PromQlConfig.getTargetsUrl(ipPort);
        PrometheusQuery result = get(url);
        if ("error".equals(result.getStatus())) {
            throw new PlatformRuntimeException(DeviceError.PROMETHEUS_RESULT_ERROR,result.getMessage());
        }
        return gson.fromJson(result.getDataJson(), PrometheusTargets.class);
    }

    public static PrometheusQuery get(String url) {
        return get(url, null);
    }

    public static PrometheusQuery get(String url, PrometheusRequest request) {
        if (request != null) {
            url = buildUrl(url, request.toMap());
        }
        log.info("发送请求->{}", url);
        HttpRequestBase httpRequest = new HttpGet(url);
        CloseableHttpResponse response = null;
        long start = System.currentTimeMillis();
        try {
            response = httpClient.execute(httpRequest);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 400) {
                PrometheusQuery data = new PrometheusQuery();
                data.setStatus("error");
                data.setMessage("参数错误");
                return data;
            } else if (statusCode == 422) {
                PrometheusQuery data = new PrometheusQuery();
                data.setStatus("error");
                data.setMessage("表达式错误");
                return data;
            }

            HttpEntity responseEntity = response.getEntity();
            String json = EntityUtils.toString(responseEntity);
            return parsingResponse(json);
        } catch (Exception e) {
            throw new RuntimeException("请求异常", e);
        } finally {
            long end = System.currentTimeMillis();
            long n = end - start;
            if (n > 1000) {
                log.warn("请求耗时：{}ms", n);
            }
            if (response != null) {
                try {
                    response.close();
                } catch (Exception e) {
                }
            }
        }
    }

    private static PrometheusQuery parsingResponse(String response) {
        PrometheusQuery data;
        try {
            data = gson.fromJson(response, PrometheusQuery.class);
            data.setData(data.getData());
        } catch (Exception e) {
            data = new PrometheusQuery();
            log.info("响应数据解析失败");
        }
        data.setDataJson(response);
        return data;
    }

    private static String buildUrl(String url, Map<String, Object> queryParam) {
        StringBuffer sb = new StringBuffer(url).append("?");
        queryParam.forEach((k, v) -> {
            sb.append(k).append("=").append(URLEncoder.encode(v.toString())).append("&");
        });
        return StringUtils.removeEnd(sb.toString(), "&");
    }
}
