package discovery

import (
	"errors"
	"sync"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"github.com/tech/sendico/pkg/merrors"
)

var (
	metricsOnce sync.Once

	eventLatency *prometheus.HistogramVec
	eventStatus  *prometheus.CounterVec
)

func initMetrics() {
	metricsOnce.Do(func() {
		eventLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{
			Namespace: "sendico",
			Subsystem: "discovery",
			Name:      "event_latency_seconds",
			Help:      "Latency distribution for discovery event handling.",
			Buckets:   prometheus.DefBuckets,
		}, []string{"event"})

		eventStatus = promauto.NewCounterVec(prometheus.CounterOpts{
			Namespace: "sendico",
			Subsystem: "discovery",
			Name:      "event_requests_total",
			Help:      "Total number of discovery events handled, grouped by event and status.",
		}, []string{"event", "status"})
	})
}

func observeEvent(event string, err error, duration time.Duration) {
	if eventLatency != nil {
		eventLatency.WithLabelValues(event).Observe(duration.Seconds())
	}
	if eventStatus != nil {
		eventStatus.WithLabelValues(event, statusLabel(err)).Inc()
	}
}

func statusLabel(err error) string {
	switch {
	case err == nil:
		return "ok"
	case errors.Is(err, merrors.ErrInvalidArg):
		return "invalid_argument"
	case errors.Is(err, merrors.ErrNoData):
		return "not_found"
	case errors.Is(err, merrors.ErrDataConflict):
		return "conflict"
	case errors.Is(err, merrors.ErrAccessDenied):
		return "denied"
	case errors.Is(err, merrors.ErrInternal):
		return "internal"
	default:
		return "error"
	}
}
