package tidbxinstance

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

const (
	metricsNamespace = "tidb_management_service"
	metricsSubsystem = "bff_tidbxinstance_api"

	apiListTidbs                   = "list_tidbs"
	apiGetTidb                     = "get_tidb"
	apiGetClusterInventory         = "get_cluster_inventory"
	apiGetProjectMigrationTask     = "get_project_migration_task"
	apiBindTags                    = "bind_tags"
	apiUnbindTags                  = "unbind_tags"
	apiMoveTidb                    = "move_tidb"
	apiBatchMoveTidbs              = "batch_move_tidbs"
	apiApproveProjectMigrationTask = "approve_project_migration_task"

	unknownTenantID = "unknown"
)

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

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

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

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

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

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

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

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

func RegisterMetrics() {
	prometheus.MustRegister(bffWriteRequestTotal)
	prometheus.MustRegister(bffWriteRequestSuccessTotal)
	prometheus.MustRegister(bffWriteRequestFailureTotal)
	prometheus.MustRegister(bffWriteRequestDurationSeconds)
	prometheus.MustRegister(bffQueryRequestTotal)
	prometheus.MustRegister(bffQueryRequestSuccessTotal)
	prometheus.MustRegister(bffQueryRequestFailureTotal)
	prometheus.MustRegister(bffQueryRequestDurationSeconds)
}

func recordWriteAPIMetrics(api, tenantID string, durationSeconds float64, err error) {
	bffWriteRequestTotal.WithLabelValues(api, tenantID).Inc()
	bffWriteRequestDurationSeconds.WithLabelValues(api, tenantID).Observe(durationSeconds)

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

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

func recordQueryAPIMetrics(api string, durationSeconds float64, err error) {
	bffQueryRequestTotal.WithLabelValues(api).Inc()
	bffQueryRequestDurationSeconds.WithLabelValues(api).Observe(durationSeconds)

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

	bffQueryRequestFailureTotal.WithLabelValues(api).Inc()
}
