package metrics

import (
	"github.com/prometheus/client_golang/prometheus"
)

const gatewayComponent = "gateway"

// Gateway metrics.
var (
	ConnectionCounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Subsystem: gatewayComponent,
			Name:      "connection_total",
			Help:      "Counter of connection",
		},
		[]string{"cluster_id", "stage"},
	)

	ConnectionGauge = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Subsystem: gatewayComponent,
			Name:      "connection_gauge",
			Help:      "Gauge of connection",
		},
		[]string{"cluster_id", "keyspace_token"},
	)

	ConnectionHistogram = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Subsystem: gatewayComponent,
			Name:      "connection_seconds",
			Help:      "Histogram of connection",
		},
		[]string{"cluster_id", "stage"},
	)

	SessionHistogram = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Subsystem: gatewayComponent,
			Name:      "session_seconds",
			Help:      "Histogram of session durations",
			Buckets:   prometheus.ExponentialBucketsRange(30, 3600*24, 10), // 30s to 1d
		},
		[]string{"cluster_id"},
	)

	ConnectionFlow = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Subsystem: gatewayComponent,
			Name:      "connection_flow_bytes_total",
			Help:      "Counter of connection flow bytes",
		},
		[]string{"cluster_id", "keyspace_id", "direction"},
	)

	ClientsDriverCounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Subsystem: gatewayComponent,
			Name:      "clients_driver_total",
			Help:      "Counter of clients' driver",
		},
		[]string{"client_name", "client_version", "program_name"},
	)

	ConnectionSLACounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Subsystem: gatewayComponent,
			Name:      "connection_sla_total",
			Help:      "Counter of connection status for sla",
		},
		[]string{"cluster_id", "token", "tidb_pool", "ru_mode", "error_source", "stage", "status", "service_plan"},
	)

	ConnectionErrorTypeCounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Subsystem: gatewayComponent,
			Name:      "connection_error_type_total",
			Help:      "Counter of connection error_type",
		},
		[]string{"tidb_pool", "ru_mode", "error_source", "error_type"},
	)

	ProbeTiDBHistogram = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Subsystem: gatewayComponent,
			Name:      "probe_tidb_seconds",
			Help:      "Histogram of probe tidb durations",
		},
		[]string{"cluster_id", "token", "tidb_pool", "ru_mode", "status"},
	)

	ProbeLatencyHistogram = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Subsystem: gatewayComponent,
			Name:      "probe_latency_v1_seconds",
			Help:      "Histogram of probe latency duration",
			Buckets:   []float64{0.005, 0.02, 0.06, 0.2, 0.5, 1, 5, 10},
		},
		[]string{"user", "stmt", "status"},
	)

	BackendRecvCounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Subsystem: gatewayComponent,
			Name:      "backend_recv_total",
			Help:      "Counter of backend recv",
		},
		[]string{"cluster_id", "token"},
	)

	GetBackendListCounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Subsystem: gatewayComponent,
			Name:      "get_backendlist_total",
			Help:      "Counter of GetBackendList",
		},
		[]string{"cluster_id", "token", "stage"},
	)

	TiDBReplicasGauge = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Subsystem: gatewayComponent,
			Name:      "tidb_replicas",
			Help:      "Gauge of tidb replicas",
		},
		[]string{"cluster_id", "token"},
	)

	BackendPodsGauge = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Subsystem: gatewayComponent,
			Name:      "backend_pods",
			Help:      "Gauge of backend pods",
		},
		[]string{"cluster_id", "token", "tidb_pool", "pod_name"},
	)
)

func init() {
	prometheus.MustRegister(ConnectionCounter)
	prometheus.MustRegister(ConnectionGauge)
	prometheus.MustRegister(ConnectionHistogram)
	prometheus.MustRegister(SessionHistogram)
	prometheus.MustRegister(ConnectionFlow)
	prometheus.MustRegister(ClientsDriverCounter)
	prometheus.MustRegister(ConnectionSLACounter)
	prometheus.MustRegister(ConnectionErrorTypeCounter)
	prometheus.MustRegister(ProbeTiDBHistogram)
	prometheus.MustRegister(BackendRecvCounter)
	prometheus.MustRegister(GetBackendListCounter)
	prometheus.MustRegister(ProbeLatencyHistogram)
	prometheus.MustRegister(TiDBReplicasGauge)
	prometheus.MustRegister(BackendPodsGauge)
}

func ClearMetrics(clusterID string) {
	ConnectionCounter.DeletePartialMatch(prometheus.Labels{"cluster_id": clusterID})
	ConnectionGauge.DeletePartialMatch(prometheus.Labels{"cluster_id": clusterID})
	ConnectionHistogram.DeletePartialMatch(prometheus.Labels{"cluster_id": clusterID})
	ConnectionFlow.DeletePartialMatch(prometheus.Labels{"cluster_id": clusterID})
	ConnectionSLACounter.DeletePartialMatch(prometheus.Labels{"cluster_id": clusterID})
	ProbeTiDBHistogram.DeletePartialMatch(prometheus.Labels{"cluster_id": clusterID})
	GetBackendListCounter.DeletePartialMatch(prometheus.Labels{"cluster_id": clusterID})
	TiDBReplicasGauge.DeletePartialMatch(prometheus.Labels{"cluster_id": clusterID})
	SessionHistogram.DeletePartialMatch(prometheus.Labels{"cluster_id": clusterID})
	BackendRecvCounter.DeletePartialMatch(prometheus.Labels{"cluster_id": clusterID})
	BackendPodsGauge.DeletePartialMatch(prometheus.Labels{"cluster_id": clusterID})
}
