package metrics

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

const (
	monitorNamespace = "acs"
)

var DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 15, 30}

var (
	buildInfo = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: monitorNamespace,
			Name:      "build_info",
			Help:      "Build information",
		},
		[]string{"build_time", "git_hash", "git_branch"},
	)

	controllerReconciledTotal = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: monitorNamespace,
			Name:      "controller_reconciled_total",
			Help:      "Total number of controller reconciles",
		},
		[]string{"agent", "namespace", "name", "status"},
	)

	controllerReconciledDuration = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: monitorNamespace,
			Name:      "controller_reconciled_duration_seconds",
			Help:      "Histogram of controller reconciles durations",
			Buckets:   DefBuckets,
		},
		[]string{"agent", "namespace", "name"},
	)

	controllerHandledTaskTotal = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: monitorNamespace,
			Name:      "controller_handled_task_total",
			Help:      "Total number of controller handle tasks",
		},
		[]string{"agent", "task", "k8s_cluster_name", "tenant_id", "application_id", "step", "status"},
	)

	controllerHandledTaskDuration = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: monitorNamespace,
			Name:      "controller_handled_task_duration_seconds",
			Help:      "Histogram of controller handles task durations",
			Buckets:   DefBuckets,
		},
		[]string{"agent", "task", "k8s_cluster_name", "tenant_id", "application_id", "step"},
	)

	agentStatus = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: monitorNamespace,
			Name:      "agent_status",
			Help:      "Status of agents",
		},
		[]string{"agent", "k8s_cluster_name", "tenant_id", "application_id", "status"},
	)

	vpcEndpointStatus = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: monitorNamespace,
			Name:      "vpc_endpoint_status",
			Help:      "Status of VPC endpoints",
		},
		[]string{"resource", "namespace", "name", "service_name", "vpc_id", "vpc_endpoint_type", "reason", "status"},
	)

	o11yApiRequestsTotal = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: monitorNamespace,
			Name:      "o11y_api_requests_total",
			Help:      "Total number of O11y API requests",
		},
		[]string{"tenant_id", "o11y_cluster_id", "method", "status"},
	)

	o11yApiRequestsDuration = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: monitorNamespace,
			Name:      "o11y_api_requests_duration_seconds",
			Help:      "Histogram of O11y API request durations",
			Buckets:   DefBuckets,
		},
		[]string{"tenant_id", "o11y_cluster_id", "method", "status"},
	)

	scaledResourceTotal = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: monitorNamespace,
			Name:      "scaled_resource_total",
			Help:      "Total number of scaled resources",
		},
		[]string{"agent", "k8s_cluster_name", "action"},
	)

	nodegroupDesiredNodeCount = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: monitorNamespace,
			Name:      "nodegroup_desired_node_count",
			Help:      "Desired node count of nodegroup/nodepool resources per cloud provider and CRD type",
		},
		[]string{"provider", "cluster_name", "nodegroup_name", "crd_type"},
	)

	agentAnnotations = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: monitorNamespace,
			Name:      "agent_annotations",
			Help:      "Annotations of agents",
		},
		[]string{"agent", "k8s_cluster_name", "tenant_id", "application_id", "pause_reconciliation", "vmagent_config_template", "vector_config_template"},
	)

	agentCreated = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: monitorNamespace,
			Name:      "agent_created",
			Help:      "Creation timestamp (Unix epoch) of agent CRs",
		},
		[]string{"agent", "k8s_cluster_name", "tenant_id", "application_id"},
	)
)

func SetBuildInfo(buildTime, gitHash, gitBranch string) {
	buildInfo.WithLabelValues(buildTime, gitHash, gitBranch).Set(1)
}

func IncControllerHandledTaskCounter(lbs []string) {
	controllerHandledTaskTotal.WithLabelValues(lbs...).Inc()
}

func ObserveControllerHandledTaskDuration(lbs []string, duration float64) {
	controllerHandledTaskDuration.WithLabelValues(lbs...).Observe(duration)
}

func IncO11yApiRequestsCounter(lbs []string) {
	o11yApiRequestsTotal.WithLabelValues(lbs...).Inc()
}

func ObserveO11yApiRequestsDuration(lbs []string, duration float64) {
	o11yApiRequestsDuration.WithLabelValues(lbs...).Observe(duration)
}

func IncScaledResourceCounter(lbs []string) {
	scaledResourceTotal.WithLabelValues(lbs...).Inc()
}
