package cluster

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

const (
	metricsNamespace = "tidb_management_service"
	metricsSubsystem = "serverless_cluster_api"

	apiCreateCluster           = "create_cluster"
	apiDeleteCluster           = "delete_cluster"
	apiUpdateCluster           = "update_cluster"
	apiBindTags                = "bind_tags"
	apiUnbindTags              = "unbind_tags"
	apiBatchCreateClusters     = "batch_create_clusters"
	apiBatchDeleteClusters     = "batch_delete_clusters"
	apiClaimClusterFromZero    = "claim_cluster_from_zero"
	apiTakeoverClusterFromPool = "takeover_cluster_from_pool"
	apiListClusters            = "list_clusters"
	apiGetCluster              = "get_cluster"
	apiBatchGetClusters        = "batch_get_clusters"
	unknownTenantID            = "unknown"
)

var (
	clusterWriteRequestTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricsNamespace,
			Subsystem: metricsSubsystem,
			Name:      "write_request_total",
			Help:      "Total number of write requests for serverless cluster APIs",
		},
		[]string{"api", "tenant_id"},
	)

	clusterWriteRequestSuccessTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricsNamespace,
			Subsystem: metricsSubsystem,
			Name:      "write_request_success_total",
			Help:      "Total number of successful write requests for serverless cluster APIs",
		},
		[]string{"api", "tenant_id"},
	)

	clusterWriteRequestFailureTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricsNamespace,
			Subsystem: metricsSubsystem,
			Name:      "write_request_failure_total",
			Help:      "Total number of failed write requests for serverless cluster APIs",
		},
		[]string{"api", "tenant_id"},
	)

	clusterWriteRequestDurationSeconds = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: metricsNamespace,
			Subsystem: metricsSubsystem,
			Name:      "write_request_duration_seconds",
			Help:      "Duration of write requests for serverless cluster APIs",
			Buckets:   prometheus.DefBuckets,
		},
		[]string{"api", "tenant_id"},
	)

	clusterQueryRequestTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricsNamespace,
			Subsystem: metricsSubsystem,
			Name:      "query_request_total",
			Help:      "Total number of query requests for serverless cluster APIs",
		},
		[]string{"api"},
	)

	clusterQueryRequestSuccessTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricsNamespace,
			Subsystem: metricsSubsystem,
			Name:      "query_request_success_total",
			Help:      "Total number of successful query requests for serverless cluster APIs",
		},
		[]string{"api"},
	)

	clusterQueryRequestFailureTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: metricsNamespace,
			Subsystem: metricsSubsystem,
			Name:      "query_request_failure_total",
			Help:      "Total number of failed query requests for serverless cluster APIs",
		},
		[]string{"api"},
	)

	clusterQueryRequestDurationSeconds = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: metricsNamespace,
			Subsystem: metricsSubsystem,
			Name:      "query_request_duration_seconds",
			Help:      "Duration of query requests for serverless cluster APIs",
			Buckets:   prometheus.DefBuckets,
		},
		[]string{"api"},
	)
)

func RegisterMetrics() {
	prometheus.MustRegister(clusterWriteRequestTotal)
	prometheus.MustRegister(clusterWriteRequestSuccessTotal)
	prometheus.MustRegister(clusterWriteRequestFailureTotal)
	prometheus.MustRegister(clusterWriteRequestDurationSeconds)
	prometheus.MustRegister(clusterQueryRequestTotal)
	prometheus.MustRegister(clusterQueryRequestSuccessTotal)
	prometheus.MustRegister(clusterQueryRequestFailureTotal)
	prometheus.MustRegister(clusterQueryRequestDurationSeconds)
}

func recordWriteClusterAPIMetrics(api, tenantID string, durationSeconds float64, err error) {
	clusterWriteRequestTotal.WithLabelValues(api, tenantID).Inc()
	clusterWriteRequestDurationSeconds.WithLabelValues(api, tenantID).Observe(durationSeconds)

	if err == nil {
		clusterWriteRequestSuccessTotal.WithLabelValues(api, tenantID).Inc()
		return
	}

	clusterWriteRequestFailureTotal.WithLabelValues(api, tenantID).Inc()
}

func recordQueryClusterAPIMetrics(api string, durationSeconds float64, err error) {
	clusterQueryRequestTotal.WithLabelValues(api).Inc()
	clusterQueryRequestDurationSeconds.WithLabelValues(api).Observe(durationSeconds)

	if err == nil {
		clusterQueryRequestSuccessTotal.WithLabelValues(api).Inc()
		return
	}

	clusterQueryRequestFailureTotal.WithLabelValues(api).Inc()
}
