package app

import (
	"fmt"
	"net/http"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/rs/cors"
)

var (
	namespace = "collage"

	counter = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: namespace,
		Name:      "endpoint_request_count",
		Help:      "collage request count.",
	}, []string{"app", "name", "method", "state"})

	histogram = prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Namespace: namespace,
		Name:      "endpoint_duration_seconds",
		Help:      "Time taken to execute endpoint.",
	}, []string{"app", "name", "method", "status"})
)

type metricResponseWriter struct {
	http.ResponseWriter
	statusCode int
}

func newMetricResponseWriter(w http.ResponseWriter) *metricResponseWriter {
	return &metricResponseWriter{w, http.StatusOK}
}

func (lrw *metricResponseWriter) WriteHeader(code int) {
	lrw.statusCode = code
	lrw.ResponseWriter.WriteHeader(code)
}

// SetupPrometheusHandler enable CORS, handler metrics
func SetupPrometheusHandler(handler http.Handler, app string) http.Handler {
	sugar.Debug("app.SetupPrometheusHandler: 📥")
	handleCORS := cors.AllowAll().Handler
	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		lrw := newMetricResponseWriter(w)
		handler.ServeHTTP(lrw, r)
		statusCode := lrw.statusCode
		duration := time.Since(start)
		histogram.WithLabelValues(app, r.URL.String(), r.Method, fmt.Sprintf("%d", statusCode)).Observe(duration.Seconds())
		counter.WithLabelValues(app, r.URL.String(), r.Method, fmt.Sprintf("%d", statusCode)).Inc()
	})
	err := prometheus.Register(histogram)
	if err != nil {
		sugar.Errorf("app.SetupPrometheusHandler: 💣 ⛔ %s", err.Error())
		return nil
	}
	err = prometheus.Register(counter)
	if err != nil {
		sugar.Errorf("app.SetupPrometheusHandler: 💣 ⛔ %s", err.Error())
		return nil
	}
	sugar.Info("app.SetupPrometheusHandler: 👍 📤")
	return handleCORS(h)
}
