package fees

import (
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	feesv1 "github.com/tech/sendico/pkg/proto/billing/fees/v1"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

var (
	metricsOnce sync.Once

	quoteRequestsTotal *prometheus.CounterVec
	quoteLatency       *prometheus.HistogramVec
)

func initMetrics() {
	metricsOnce.Do(func() {
		quoteRequestsTotal = promauto.NewCounterVec(
			prometheus.CounterOpts{
				Namespace: "billing",
				Subsystem: "fees",
				Name:      "requests_total",
				Help:      "Total number of fee service requests processed.",
			},
			[]string{"call", "trigger", "status", "fx_used"},
		)

		quoteLatency = promauto.NewHistogramVec(
			prometheus.HistogramOpts{
				Namespace: "billing",
				Subsystem: "fees",
				Name:      "request_latency_seconds",
				Help:      "Latency of fee service requests.",
				Buckets:   prometheus.DefBuckets,
			},
			[]string{"call", "trigger", "status", "fx_used"},
		)
	})
}

func observeMetrics(call string, trigger feesv1.Trigger, statusLabel string, fxUsed bool, took time.Duration) {
	triggerLabel := trigger.String()
	if trigger == feesv1.Trigger_TRIGGER_UNSPECIFIED {
		triggerLabel = "TRIGGER_UNSPECIFIED"
	}

	fxLabel := strconv.FormatBool(fxUsed)
	quoteRequestsTotal.WithLabelValues(call, triggerLabel, statusLabel, fxLabel).Inc()
	quoteLatency.WithLabelValues(call, triggerLabel, statusLabel, fxLabel).Observe(took.Seconds())
}

func statusFromError(err error) string {
	if err == nil {
		return "success"
	}

	st, ok := status.FromError(err)
	if !ok {
		return "error"
	}

	code := st.Code()
	if code == codes.OK {
		return "success"
	}

	return strings.ToLower(code.String())
}
