package metrics_test

import (
	"net/http"
	"net/http/httptest"
	"regexp"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/onsi/gomega"
	"github.com/prometheus/client_golang/prometheus/promhttp"

	"github.com/pingcap-inc/clinic/pkg/middlewares/metrics"
)

func TestMetricsMiddleware_GinMiddleware(t *testing.T) {
	g := gomega.NewWithT(t)
	gin.SetMode(gin.TestMode)
	_, engine := gin.CreateTestContext(httptest.NewRecorder())
	engine.Use(metrics.NewAPIMetricsGinMiddleware("test-api"))
	engine.GET("/ping", func(ctx *gin.Context) {
		ctx.String(http.StatusOK, "OK")
	})
	engine.GET("/metrics", gin.WrapH(promhttp.Handler()))
	{
		req, err := http.NewRequest(http.MethodGet, "/ping", nil)
		g.Expect(err).To(gomega.Succeed())
		w := httptest.NewRecorder()
		engine.ServeHTTP(w, req)
		g.Expect(w.Code).To(gomega.Equal(http.StatusOK))
	}
	{
		req, err := http.NewRequest(http.MethodGet, "/metrics", nil)
		g.Expect(err).To(gomega.Succeed())
		w := httptest.NewRecorder()
		engine.ServeHTTP(w, req)
		// check if the response body has our metrics data
		t.Log(w.Body.String())
		namespace, subsystem := "rest", "server"
		reReqTotal := regexp.MustCompile(namespace + `_` + subsystem + `_` + `requests_total` + `{method="GET",service="test-api",uri="\/ping"} ([0-9\.]+)`)
		reReqInFlight := regexp.MustCompile(namespace + `_` + subsystem + `_` + `requests_in_flight` + `{method="GET",service="test-api",uri="\/metrics"} ([0-9\.]+)`)
		reReqDurationBucket := regexp.MustCompile(namespace + `_` + subsystem + `_` + `request_duration_seconds_bucket` + `{code="200",method="GET",service="test-api",uri="\/ping",le="0.005"} ([0-9\.]+)`)
		reReqDurationCount := regexp.MustCompile(namespace + `_` + subsystem + `_` + `request_duration_seconds_count` + `{code="200",method="GET",service="test-api",uri="\/ping"} ([0-9\.]+)`)
		matchReqTotal := reReqTotal.FindStringSubmatch(w.Body.String())
		matchReqInFlight := reReqInFlight.FindStringSubmatch(w.Body.String())
		matchReqDurationBucket := reReqDurationBucket.FindStringSubmatch(w.Body.String())
		matchReqDurationCount := reReqDurationCount.FindStringSubmatch(w.Body.String())
		g.Expect(matchReqTotal).To(gomega.HaveLen(2))
		g.Expect(matchReqTotal[1]).To(gomega.Equal("1"))

		g.Expect(matchReqInFlight).To(gomega.HaveLen(2))
		g.Expect(matchReqInFlight[1]).To(gomega.Equal("1"))

		g.Expect(matchReqDurationBucket).To(gomega.HaveLen(2))
		g.Expect(matchReqDurationBucket[1]).To(gomega.Equal("1"))

		g.Expect(matchReqDurationCount).To(gomega.HaveLen(2))
		g.Expect(matchReqDurationCount[1]).To(gomega.Equal("1"))
	}
}
