package com.iqser.red.service.peristence.v1.server.utils;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.databind.JsonNode;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

@Service
public class MetricsPrinterService {

    @Value("${server.port}")
    private int serverPort;

    @Value("${management.endpoint.metrics.enabled}")
    private boolean metricsEnabled;


    @SneakyThrows
    public void printMetrics() {

        if (!metricsEnabled) {
            return;
        }

        RestTemplate rt = new RestTemplate();

        var url = "http://127.0.0.1:" + serverPort + "/actuator/metrics";

        var ent = rt.getForEntity(url, JsonNode.class);
        List<String> metrics = new ArrayList<>();
        ent.getBody().get("names").forEach(name -> {
            if (name.asText().startsWith("Timer") || name.asText().startsWith("QueryCounter")) {
                metrics.add(name.asText());
            }
        });

        double count = 0;
        double total = 0;
        var counterResults = new ArrayList<Result>();

        var timerResults = new ArrayList<Result>();
        for (var metric : metrics) {
            if (!metric.contains("com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.")) {
                continue;
            }

            if (metric.startsWith("Timer")) {
                var m = rt.getForEntity(url + "/" + metric, JsonNode.class);
                var baseUnit = m.getBody().get("baseUnit").asText();
                // System.out.println(om.writeValueAsString(m.getBody()));
                for (var mes : m.getBody().get("measurements")) {
                    if (mes.get("statistic").asText().equals("COUNT")) {
                        count = mes.get("value").asDouble();
                    }

                    if (mes.get("statistic").asText().equals("TOTAL_TIME")) {
                        total = mes.get("value").asDouble() * 1000; // in ms
                    }

                }
                var result = new Result(metric, count, total);
                timerResults.add(result);
            }
            if (metric.startsWith("Query")) {
                var m = rt.getForEntity(url + "/" + metric, JsonNode.class);
                for (var mes : m.getBody().get("measurements")) {
                    if (mes.get("statistic").asText().equals("COUNT")) {
                        count = mes.get("value").asDouble();
                    }

                    if (mes.get("statistic").asText().equals("TOTAL")) {
                        total = mes.get("value").asDouble(); // in ms
                    }

                }
                var result = new Result(metric, count, total);
                counterResults.add(result);
            }
        }

        timerResults.sort((a, b) -> Double.compare(b.total, a.total));
        timerResults.forEach(System.out::println);

        counterResults.sort((a, b) -> Double.compare(b.average, a.average));
        counterResults.forEach(System.out::println);

    }


    @Slf4j
    public static class Result {

        String metric;
        double count;
        double total;
        double average;
        String totalStr;
        String averageStr;


        public Result(String metric, double count, double total) {

            this.metric = metric.replace("com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.", "");
            this.count = count;
            this.total = total;
            this.average = total / count;

            DecimalFormat df = new DecimalFormat("#.##");
            this.totalStr = df.format(this.total);
            this.averageStr = df.format(this.average);
        }


        @Override
        public String toString() {

            return padRight(metric + ": ") + " | " + padLeft(count + "") + " |  " + padLeft(totalStr + "") + " | " + padLeft(averageStr + "");
        }


        private String padRight(String str) {

            while (str.length() < 100) {
                str += " ";
            }
            return str;
        }


        private String padLeft(String str) {

            while (str.length() < 12) {
                str = " " + str;
            }
            return str;
        }

    }

}
