package com.yingxin.prms.service.asyncTask;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import com.yingxin.prms.domain.Server_Host_Info;
import com.yingxin.prms.dto.SingleHostStatus;
import org.kairosdb.client.HttpClient;
import org.kairosdb.client.builder.*;
import org.kairosdb.client.response.QueryResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.Callable;

public class QueryHostStatusTask implements Callable<SingleHostStatus> {

    private static Logger logger = LoggerFactory.getLogger(QueryHostStatusTask.class);

    private Server_Host_Info hostInfo;
    private HttpClient httpClient;

    public QueryHostStatusTask(Server_Host_Info hostInfo, HttpClient httpClient) {
        this.hostInfo = hostInfo;
        this.httpClient = httpClient;
    }

    @Override
    public SingleHostStatus call() {
        Map<String, Object> hostStatusMap = new HashMap<>();
        hostStatusMap.put("inMonitoring", true);
        hostStatusMap.put("avgResp", 0);
        hostStatusMap.put("f60s", 0);
        hostStatusMap.put("value", "ok");
        hostStatusMap.put("faultCount", 0);
        hostStatusMap.put("stamp", System.currentTimeMillis());
        String tag = hostInfo.getService_path();
        SingleHostStatus singleHostStatus = new SingleHostStatus(hostInfo.getCluster_name(), tag, hostStatusMap);
        Aggregator aggregatorDay = AggregatorFactory.createSumAggregator(1, TimeUnit.DAYS).withStartTimeAlignment(0);
        Aggregator aggregator5Min = AggregatorFactory.createSumAggregator(5, TimeUnit.MINUTES);
        Aggregator aggregator1Min = AggregatorFactory.createSumAggregator(1, TimeUnit.MINUTES);
        Aggregator aggregatorDur = AggregatorFactory.createAverageAggregator(5, TimeUnit.MINUTES);
        QueryBuilder queryDay = createQuery(1, TimeUnit.DAYS, "heartbeat", tag, aggregatorDay);
        QueryBuilder query5Min = createQuery(5, TimeUnit.MINUTES, "heartbeat", tag, aggregator5Min);
        QueryBuilder query1Min = createQuery(1, TimeUnit.MINUTES, "heartbeat", tag, aggregator1Min);
        QueryBuilder queryDur = createQuery(5, TimeUnit.MINUTES, "respdur", tag, aggregatorDur);
        try {
            QueryResponse heartbeatDay = httpClient.query(queryDay);
            QueryResponse heartbeat5Min = httpClient.query(query5Min);
            QueryResponse heartbeat1Min = httpClient.query(query1Min);
            QueryResponse dur = httpClient.query(queryDur);
            List<DataPoint> dataPointsDay = heartbeatDay.getQueries().get(0).getResults().get(0).getDataPoints();

            List<DataPoint> dataPoints5Min = heartbeat5Min.getQueries().get(0).getResults().get(0).getDataPoints();
            List<DataPoint> dataPoints1Min = heartbeat1Min.getQueries().get(0).getResults().get(0).getDataPoints();
            List<DataPoint> dataPointsDur = dur.getQueries().get(0).getResults().get(0).getDataPoints();
            long faultCountDay = dataPointsDay.size() == 0 ? 0 : dataPointsDay.get(dataPointsDay.size() - 1).longValue();

            if (dataPointsDay.size() == 0 || dataPoints5Min.size() == 0 || dataPointsDur.size() == 0) {
                hostStatusMap.put("inMonitoring", false);
                hostStatusMap.put("value", "down");
                hostStatusMap.put("faultCount", faultCountDay);
                logger.error("tag：{}的查询数据为空，inMonitoring返回false。dataPointsDay={}，dataPoints5Min={}，dataPoints1Min={}，dataPointsDur={}", tag, dataPointsDay.size(), dataPoints5Min.size(), dataPoints1Min.size(), dataPointsDur.size());
                return singleHostStatus;
            }

            long faultCount5Min = dataPoints5Min.get(0).longValue();
            long faultCount1Min = 0;
            if (dataPoints1Min.size() != 0) {
                faultCount1Min = dataPoints1Min.get(0).longValue();
            }
            long avgResp = dataPointsDur.get(0).longValue();
            if (dataPoints5Min.size() > 1) {
                faultCount5Min = dataPoints5Min.get(dataPoints5Min.size() - 1).longValue();
            }
            if (dataPoints1Min.size() > 1) {
                faultCount1Min = dataPoints1Min.get(dataPoints1Min.size() - 1).longValue() + dataPoints1Min.get(dataPoints1Min.size() - 2).longValue();
            }
            int correctCount1Min = 60 / 10 - 1;
            String value = "ok";
            if (faultCount5Min != 0) value = "unstable";
//            if (faultCount1Min != 0 && faultCount1Min >= correctCount1Min) value = "down";
            if (faultCount1Min >= correctCount1Min) value = "down";
            if (!value.equals("ok")) logger.error("返回状态为：{}，5分钟内失败数：{}，1分钟内失败数：{}，标准值：{}", value, faultCount5Min, faultCount1Min, correctCount1Min);
            hostStatusMap.put("faultCount", faultCountDay);
            hostStatusMap.put("f60s", faultCount1Min);
            hostStatusMap.put("value", value);
            hostStatusMap.put("avgResp", avgResp);
        } catch (IOException | DataFormatException e) {
            logger.error("查询状态记录失败。inMonitoring返回false");
            logger.error(e.getMessage());
            hostStatusMap.put("inMonitoring", false);
            hostStatusMap.put("value", "down");
        }
        return singleHostStatus;
    }

    private QueryBuilder createQuery(int start, TimeUnit timeUnit, String metric, String tag, Aggregator aggregator) {
        QueryBuilder queryBuilder = QueryBuilder.getInstance();
        queryBuilder.setStart(start, timeUnit).setTimeZone(TimeZone.getDefault())
                .addMetric(metric)
                .addTag("host", tag)
                .addAggregator(aggregator);
        return queryBuilder;
    }
}
