package ops

import (
	"strconv"
	"sync"
	"time"

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

var (
	metricsOnce     sync.Once
	ingestTotal     *prometheus.CounterVec
	ingestLatency   *prometheus.HistogramVec
	deliveryTotal   *prometheus.CounterVec
	deliveryLatency *prometheus.HistogramVec
)

type observer struct{}

func newObserver() Observer {
	initMetrics()
	return observer{}
}

func initMetrics() {
	metricsOnce.Do(func() {
		ingestTotal = promauto.NewCounterVec(prometheus.CounterOpts{
			Namespace: "sendico",
			Subsystem: "callbacks",
			Name:      "ingest_total",
			Help:      "Total ingest attempts by result",
		}, []string{"result"})

		ingestLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{
			Namespace: "sendico",
			Subsystem: "callbacks",
			Name:      "ingest_duration_seconds",
			Help:      "Ingest latency in seconds",
			Buckets:   prometheus.DefBuckets,
		}, []string{"result"})

		deliveryTotal = promauto.NewCounterVec(prometheus.CounterOpts{
			Namespace: "sendico",
			Subsystem: "callbacks",
			Name:      "delivery_total",
			Help:      "Total delivery attempts by result and status code",
		}, []string{"result", "status_code"})

		deliveryLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{
			Namespace: "sendico",
			Subsystem: "callbacks",
			Name:      "delivery_duration_seconds",
			Help:      "Delivery latency in seconds",
			Buckets:   prometheus.DefBuckets,
		}, []string{"result"})
	})
}

func (observer) ObserveIngest(result string, duration time.Duration) {
	if result == "" {
		result = "unknown"
	}
	ingestTotal.WithLabelValues(result).Inc()
	ingestLatency.WithLabelValues(result).Observe(duration.Seconds())
}

func (observer) ObserveDelivery(result string, statusCode int, duration time.Duration) {
	if result == "" {
		result = "unknown"
	}
	deliveryTotal.WithLabelValues(result, strconv.Itoa(statusCode)).Inc()
	deliveryLatency.WithLabelValues(result).Observe(duration.Seconds())
}
