package metrics

import (
	"context"
	"net/url"
	"time"

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

var (
	ClientGo = clientGoMetrics{
		TransportCacheEntries: prometheus.NewGauge(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: clientGoSubsystem,
				Name:      "transport_cache_entries",
				Help:      "The number of entries in client-go transport cache.",
			},
		),
		TransportCreateCallsTotal: prometheus.NewCounterVec(
			prometheus.CounterOpts{
				Namespace: namespace,
				Subsystem: clientGoSubsystem,
				Name:      "transport_create_calls_total",
				Help:      "How many times client-go transport create was called.",
			},
			[]string{"result"},
		),
		RequestLatency: prometheus.NewHistogramVec(
			prometheus.HistogramOpts{
				Namespace: namespace,
				Subsystem: clientGoSubsystem,
				Name:      "request_latency_seconds",
				Help:      "The client-go request latency in seconds.",
			},
			[]string{"verb"},
		),
		RateLimiterLatency: prometheus.NewHistogramVec(
			prometheus.HistogramOpts{
				Namespace: namespace,
				Subsystem: clientGoSubsystem,
				Name:      "rate_limiter_latency_seconds",
				Help:      "The client-go rate limiter latency in seconds.",
			},
			[]string{"verb"},
		),
		RequestResultTotal: prometheus.NewCounterVec(
			prometheus.CounterOpts{
				Namespace: namespace,
				Subsystem: clientGoSubsystem,
				Name:      "request_result_total",
				Help:      "How many client-go requests are made by status code and method.",
			},
			[]string{"code", "method"},
		),
	}
)

type clientGoMetrics struct {
	TransportCacheEntries     prometheus.Gauge
	TransportCreateCallsTotal *prometheus.CounterVec
	RequestLatency            *prometheus.HistogramVec
	RateLimiterLatency        *prometheus.HistogramVec
	RequestResultTotal        *prometheus.CounterVec
}

type transportCacheEntriesAdapter struct{}

func (transportCacheEntriesAdapter) Observe(value int) {
	ClientGo.TransportCacheEntries.Set(float64(value))
}

type transportCreateCallsAdapter struct{}

func (transportCreateCallsAdapter) Increment(result string) {
	ClientGo.TransportCreateCallsTotal.WithLabelValues(result).Inc()
}

type latencyAdapter struct {
	metric *prometheus.HistogramVec
}

func (a latencyAdapter) Observe(_ context.Context, verb string, _ url.URL, latency time.Duration) {
	a.metric.WithLabelValues(verb).Observe(latency.Seconds())
}

type requestResultAdapter struct{}

func (requestResultAdapter) Increment(_ context.Context, code string, method string, _ string) {
	ClientGo.RequestResultTotal.WithLabelValues(code, method).Inc()
}
