package metrics

import (
	"strconv"
	"time"

	"git.frostfs.info/TrueCloudLab/frostfs-observability/metrics"
	"github.com/prometheus/client_golang/prometheus"
)

type morphClientMetrics struct {
	switchCount       prometheus.Counter
	lastBlock         prometheus.Gauge
	notificationCount *prometheus.CounterVec
	invokeDuration    *prometheus.HistogramVec
}

func newMorphClientMetrics() *morphClientMetrics {
	return &morphClientMetrics{
		switchCount: metrics.NewCounter(prometheus.CounterOpts{
			Namespace: namespace,
			Subsystem: morphSubsystem,
			Name:      "switches_total",
			Help:      "Number of endpoint switches",
		}),
		lastBlock: metrics.NewGauge(prometheus.GaugeOpts{
			Namespace: namespace,
			Subsystem: morphSubsystem,
			Name:      "last_block",
			Help:      "Index of the last received block",
		}),
		notificationCount: metrics.NewCounterVec(prometheus.CounterOpts{
			Namespace: namespace,
			Subsystem: morphSubsystem,
			Name:      "notifications_total",
			Help:      "Number of notifications received by notification type",
		}, []string{notificationTypeLabel}),
		invokeDuration: metrics.NewHistogramVec(prometheus.HistogramOpts{
			Namespace: namespace,
			Subsystem: morphSubsystem,
			Name:      "invoke_duration_seconds",
			Help:      "Cummulative duration of contract invocations",
		}, []string{invokeTypeLabel, contractLabel, methodLabel, successLabel}),
	}
}

func (m *morphClientMetrics) IncSwitchCount() {
	m.switchCount.Inc()
}

func (m *morphClientMetrics) SetLastBlock(index uint32) {
	m.lastBlock.Set(float64(index))
}

func (m *morphClientMetrics) IncNotificationCount(typ string) {
	m.notificationCount.With(
		prometheus.Labels{
			notificationTypeLabel: typ,
		},
	).Inc()
}

func (m *morphClientMetrics) ObserveInvoke(typ string, contract string, method string, success bool, d time.Duration) {
	m.invokeDuration.With(
		prometheus.Labels{
			invokeTypeLabel: typ,
			contractLabel:   contract,
			methodLabel:     method,
			successLabel:    strconv.FormatBool(success),
		},
	).Observe(d.Seconds())
}