package mymetric

import (
	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"log"
	"net/http"
	"time"
)

type (
	HistogramVec struct {
		*prometheus.HistogramVec
		Labels []string
	}
	CounterVec struct {
		*prometheus.CounterVec
		Labels []string
	}
)

func NewQPSHistogram(name string, labels ...string) *HistogramVec {
	name = HistogramKey(name)
	v := prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Name:    name,
		Buckets: []float64{5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 95, 100, 200, 300, 500, 600, 700, 800, 900, 1000, 1500, 2000, 5000}, // 统计区间 单位毫秒

	}, labels)

	wrapMetric := &HistogramVec{
		HistogramVec: v,
		Labels:       labels,
	}

	RegisterPrometheus(wrapMetric)

	return wrapMetric
}

func NewHistogram(name string, buckets []float64, labels ...string) *HistogramVec {
	name = HistogramKey(name)
	v := prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Name:    name,
		Buckets: buckets,
	}, labels)

	wrapMetric := &HistogramVec{
		HistogramVec: v,
		Labels:       labels,
	}

	RegisterPrometheus(wrapMetric)
	return wrapMetric
}

func NewCounter(name string, labels ...string) *CounterVec {
	name = CounterKey(name)
	v := prometheus.NewCounterVec(prometheus.CounterOpts{
		Name: name,
	}, labels)

	wrapMetric := &CounterVec{
		CounterVec: v,
		Labels:     labels,
	}

	RegisterPrometheus(wrapMetric)
	return wrapMetric
}

const (
	MetricsRoute = "/metrics"
)

// 监控指标路由
func GinExport(authKey string) gin.HandlerFunc {
	pm := promhttp.HandlerFor(
		prometheus.DefaultGatherer,
		promhttp.HandlerOpts{Timeout: time.Second * 3},
	)

	return func(ctx *gin.Context) {
		if authKey != "" {
			value := ctx.Query("key")
			if authKey != value {
				ctx.String(http.StatusForbidden, "metric auth key is empty")
				return
			}
		}

		pm.ServeHTTP(ctx.Writer, ctx.Request)
	}

}

func HistogramKey(name string) string {
	return name + "_h"
}

func CounterKey(name string) string {
	return name + "_c"
}

func RegisterPrometheus(c prometheus.Collector) {
	err := prometheus.Register(c)
	if err != nil {
		log.Printf("register err: %s", err)
	}

}
