package metrics

import (
	"github.com/prometheus/client_golang/prometheus"
	"github.com/tidbcloud/dataflow-service/internal/db/entity"
)

const (
	DataflowNamespace = "dataflow"
)

const (
	Unknown  = "unknown"
	DevTier  = "aws-free-tier"
	Dedicate = "dedicate"

	ChangefeedCreateResultFailed = "failed"

	ResultLabel       = "result"
	StatusLabel       = "status"
	TenantLabel       = "tenant"
	TenantNameLabel   = "tenant_name"
	ProjectLabel      = "project"
	ClusterIDLabel    = "cluster_id"
	ClusterNameLabel  = "cluster_name"
	ProviderTypeLabel = "provider_type"
	ChangefeedIDLabel = "changefeed_id"
	MessageLabel      = "message"
	ErrTypeLabel      = "err_type"
	FunctionLabel     = "function"
	HttpMethodLabel   = "http_method"
	CodeLabel         = "code"
)

// CommonLabels define some common labels to help diagnose problems
var (
	CommonLabels   = []string{TenantLabel, TenantNameLabel, ClusterIDLabel, ClusterNameLabel}
	CommonIDLabels = []string{TenantLabel, ClusterIDLabel}
)

type Tenant struct {
	ID   entity.ID
	Name string
}

// metric for backup/restore
var (
	ReplicationCreationDuration = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: DataflowNamespace,
			Subsystem: "replication",
			Name:      "creation_duration_seconds",
			Help:      "create time of create replication",
		}, []string{ProviderTypeLabel},
	)

	ReplicationPlannedDetachDuration = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: DataflowNamespace,
			Subsystem: "replication",
			Name:      "planned_detach_duration_seconds",
			Help:      "planned detach time of create replication",
		}, []string{ProviderTypeLabel},
	)

	ReplicationForceDetachDuration = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: DataflowNamespace,
			Subsystem: "replication",
			Name:      "force_detach_duration_seconds",
			Help:      "force detach time of create replication",
		}, []string{ProviderTypeLabel},
	)
)

// metric for changefeed
var (
	ChangefeedCreateResultCounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: DataflowNamespace,
			Subsystem: "ticdc",
			Name:      "changefeed_create_result",
			Help:      "count of changefeed create result.",
		}, []string{ClusterIDLabel, ClusterNameLabel, ChangefeedIDLabel, ProviderTypeLabel, ResultLabel, MessageLabel, ErrTypeLabel})

	ChangefeedStatusFailedCounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: DataflowNamespace,
			Subsystem: "ticdc",
			Name:      "changefeed_status_failed",
			Help:      "count of changefeed failed status.",
		}, []string{ClusterIDLabel, ClusterNameLabel, ChangefeedIDLabel, ProviderTypeLabel, StatusLabel, MessageLabel})
)

// metric for import
var (
	SyncingImportSinceCreatedSeconds = prometheus.NewDesc(
		prometheus.BuildFQName(DataflowNamespace, "import", "syncing_import_since_created_seconds"),
		"How long has the import been created still syncing",
		[]string{"tenant", ClusterIDLabel, "import_id", ProviderTypeLabel, "status"},
		nil)

	RecentFailImports = prometheus.NewDesc(
		prometheus.BuildFQName(DataflowNamespace, "import", "fail"),
		"Recent failed imports",
		[]string{"tenant", ClusterIDLabel, "import_id", ProviderTypeLabel, "msg", "tenant_plan", "tenant_kind", "project_id", "err_type"},
		nil)

	ImportSlowTask = prometheus.NewDesc(
		prometheus.BuildFQName(DataflowNamespace, "import", "slow_task"),
		"Slow running import tasks",
		[]string{"tenant", ClusterIDLabel, "import_id", ProviderTypeLabel, "slow_type", "tenant_plan", "tenant_kind"},
		nil)

	ImportThroughputBytes = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: DataflowNamespace,
			Subsystem: "import",
			Name:      "throughput_bytes",
			Help:      "Import job throughput in bytes/s",
			Buckets:   prometheus.ExponentialBuckets(1024, 2, 22), // 1KB/s-4GB/s
		}, []string{ProviderTypeLabel})
)

var HttpErrorResultCounter = prometheus.NewCounterVec(
	prometheus.CounterOpts{
		Namespace: DataflowNamespace,
		Subsystem: "http",
		Name:      "request_error",
		Help:      "count of http request error",
	}, []string{FunctionLabel, HttpMethodLabel, CodeLabel})

func RegisterMetrics() {
	prometheus.MustRegister(ReplicationPlannedDetachDuration)
	prometheus.MustRegister(ReplicationForceDetachDuration)
	prometheus.MustRegister(ChangefeedCreateResultCounter)
	prometheus.MustRegister(ChangefeedStatusFailedCounter)

	prometheus.MustRegister(HttpRequestDuration)
	// metrics of dm
	prometheus.MustRegister(DMJobDurationInPhase)
	prometheus.MustRegister(DMCreateStageFailedTotal)
	prometheus.MustRegister(DMModifyFailedTotal)

	prometheus.MustRegister(DownstreamRequestDuration)

	// metrics of statistic
	prometheus.MustRegister(BackupCounter)
	prometheus.MustRegister(RestoreCounter)
	prometheus.MustRegister(ChangefeedCounter)
	prometheus.MustRegister(GoroutineCounter)
}
