package eu.dnetlib.openaire.rest;


import com.google.gson.JsonObject;
import eu.dnetlib.data.claims.entity.Metrics;
import eu.dnetlib.data.claims.handler.MetricsHandler;
import eu.dnetlib.data.claims.sql.SQLStoreException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CrossOrigin;

import javax.ws.rs.CookieParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;


@Component
@CrossOrigin(origins = "*")
@Path("/report")
public class MetricsService {
    private static final Logger logger = LogManager.getLogger(MetricsService.class);

    @Autowired
    public Authorization authorization = null;

    @Autowired
    private MetricsHandler metricsHandler = null;

    public static void main(String[] args) {}


//    @GET
//    @Path("/euprojects")
//    @Produces(MediaType.APPLICATION_JSON)
//    public Response getNumOfEUProjects() {
//        try {
//            int count = metricsHandler.countEUProjects();
//            return Response.status(200).entity(composeDataResponse(count)).build();
//        } catch (SQLStoreException |Exception e) {
//            logger.error("Could not fetch number of EU projects", e);
//            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
//                    compose500Message("Fail to fetch number of EU projects.", e)).
//                    type(MediaType.APPLICATION_JSON).build();
//        }
//    }
//
//
//    @GET
//    @Path("/countries")
//    @Produces(MediaType.APPLICATION_JSON)
//    public Response getNumOfCountriesInClaims() {
//        try {
//            int count = metricsHandler.countCountriesFromClaimedBy();
//            return Response.status(200).entity(composeDataResponse(count)).build();
//        } catch (SQLStoreException |Exception e) {
//            logger.error("Could not fetch number of countries for people who claimed", e);
//            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
//                    compose500Message("Fail to fetch number of countries for people who claimed.", e)).
//                    type(MediaType.APPLICATION_JSON).build();
//        }
//    }
//
//    @GET
//    @Path("/research-results")
//    @Produces(MediaType.APPLICATION_JSON)
//    public Response getNumOfUniqueResearchResults() {
//        try {
//            int count = metricsHandler.countUniqueResearchResults();
//            return Response.status(200).entity(composeDataResponse(count)).build();
//        } catch (SQLStoreException |Exception e) {
//            logger.error("Could not fetch number of unique research results claimed", e);
//            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
//                    compose500Message("Fail to fetch number of unique research results claimed.", e)).
//                    type(MediaType.APPLICATION_JSON).build();
//        }
//    }

    @GET
    @Path("/calc")
    @Produces(MediaType.TEXT_PLAIN)
    public String calculateMetrics(
//            @HeaderParam("X-XSRF-TOKEN") String token,
            @CookieParam("AccessToken") String  cookie
    ) throws SQLStoreException, Exception {
        if(cookie == null || cookie.isEmpty()){
            return "Forbidden: You don't have permission to access. Maybe you are not registered.";
        }

        if(authorization.isPortalAdministrator(cookie)) {
            metricsHandler.calculateMetrics();
            return "metrics calculated!";
        }
        return "Forbidden: You don't have permission to access.";
    }

    @GET
    @Path("/metrics")
    @Produces(MediaType.TEXT_PLAIN)
    public String getMetrics() throws SQLStoreException, SQLException {
        Metrics metrics = metricsHandler.getMetrics();

        String response = "";

        if(metrics != null) {
//            response += "# TYPE claims gauge\n";
//            response += "claims " + metrics.getTotal_claims() + "\n";
//
//            response += "# TYPE claims_users gauge\n";
//            response += "claims_users " + metrics.getTotal_users() + "\n";
//
//            response += "# TYPE claims_projects gauge\n";
//            response += "claims_projects " + metrics.getProjects() + "\n";
//
//            response += "# TYPE claims_eu_projects gauge\n";
//            response += "claims_eu_projects " + metrics.getEu_projects() + "\n";
//
//            response += "# TYPE claims_countries gauge\n";
//            response += "claims_countries " + metrics.getCountries() + "\n";
//
//            response += "# TYPE claims_unique_research_results gauge\n";
//            response += "claims_unique_research_results " + metrics.getResearch_results() + "\n";

            Map<String, Integer> worksPerDashboard = new HashMap<>();
            // 1st approach
//            response += "# TYPE orcid_works gauge\n";

            response += "# TYPE claims_recorded gauge\n";
            for(JsonObject dashboardMetrics : metrics.getMetrics_per_dashboard()) {
                if(dashboardMetrics.get("claims") != null) {
                    response += "claims_recorded{environment=" + dashboardMetrics.get("environment") + " portal=" + dashboardMetrics.get("dashboard") + "}" + " " + dashboardMetrics.get("claims") + "\n";
                }
            }

            response += "# TYPE claims_users gauge\n";
            for(JsonObject dashboardMetrics : metrics.getMetrics_per_dashboard()) {
                if(dashboardMetrics.get("users") != null) {
                    response += "claims_users{environment=" + dashboardMetrics.get("environment") + " portal=" + dashboardMetrics.get("dashboard") + "}" + " " + dashboardMetrics.get("users") + "\n";
                }
            }

            response += "# TYPE claims_projects gauge\n";
            for(JsonObject dashboardMetrics : metrics.getMetrics_per_dashboard()) {
                if(dashboardMetrics.get("projects") != null) {
                    response += "claims_projects{environment=" + dashboardMetrics.get("environment") + " portal=" + dashboardMetrics.get("dashboard") + "}" + " " + dashboardMetrics.get("projects") + "\n";
                }
            }

            response += "# TYPE claims_eu_projects gauge\n";
            for(JsonObject dashboardMetrics : metrics.getMetrics_per_dashboard()) {
                if(dashboardMetrics.get("eu_projects") != null) {
                    response += "claims_eu_projects{environment=" + dashboardMetrics.get("environment") + " portal=" + dashboardMetrics.get("dashboard") + "}" + " " + dashboardMetrics.get("eu_projects") + "\n";
                }
            }

            response += "# TYPE claims_countries gauge\n";
            for(JsonObject dashboardMetrics : metrics.getMetrics_per_dashboard()) {
                if(dashboardMetrics.get("countries") != null) {
                    response += "claims_countries{environment=" + dashboardMetrics.get("environment") + " portal=" + dashboardMetrics.get("dashboard") + "}" + " " + dashboardMetrics.get("countries") + "\n";
                }
            }

            response += "# TYPE claims_unique_research_results gauge\n";
            for(JsonObject dashboardMetrics : metrics.getMetrics_per_dashboard()) {
//            for(Object dashboardMetricsObj : (List) metrics.getMetrics_per_dashboard()) {
//                Map<String, Object> dashboardMetrics = (HashMap<String, Object>) dashboardMetricsObj;
                if(dashboardMetrics.get("research_results") != null) {
                    response += "claims_unique_research_results{environment=" + dashboardMetrics.get("environment") + " portal=" + dashboardMetrics.get("dashboard") + "}" + " " + dashboardMetrics.get("research_results") + "\n";
                }
            }

            if(metrics.getDate() != null) {
                response += "claims_last_metrics_updater_run_timestamp_seconds " + (metrics.getDate().getTime() / 1000) + "\n";
            }
        }
        return response;
    }

    private String composeResults(int total, String label) {
        return "\""+label+"\": \""+total+"\"";
    }

    private String composeTotalResults(int total) {
        return "\"total\": \""+total+"\"";
    }

    private String composeDataResponse(int count) {
        return " { \"status\" : \"success\", \"code\": \"200\",  "+composeTotalResults(count) + " }";
    }

//    private String composeDataResponse(Metrics metrics) {
//        return " { \"status\" : \"success\", \"code\": \"200\",  "
//                +composeResults(metrics.getCountries(), "countries")
//                +composeResults(metrics.getEu_projects(), "eu_projects")
//                +composeResults(metrics.getResearch_results(), "research_results")+ " }";
//    }

    private String compose500Message(String message, Throwable throwable) {
        return  "{ \"status\" : \"fail\", \"code\" : \"500\", \"message\" : \"  " + message + "\", " +
                "\"description\" : \""+  throwable.getMessage() +"\" }";
    }


}
