package metrics

import (
	"net/http"

	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	dto "github.com/prometheus/client_model/go"
)

const namespace = "frostfs_s3_gw"

type StatisticScraper interface {
	Statistic() pool.Statistic
}

type GateMetrics struct {
	registry   prometheus.Registerer
	State      *StateMetrics
	Pool       *poolMetricsCollector
	Billing    *billingMetrics
	Stats      *APIStatMetrics
	HTTPServer *httpServerMetrics
}

func NewGateMetrics(scraper StatisticScraper) *GateMetrics {
	registry := prometheus.DefaultRegisterer

	stateMetric := newStateMetrics()
	registry.MustRegister(stateMetric)

	poolMetric := newPoolMetricsCollector(scraper)
	registry.MustRegister(poolMetric)

	billingMetric := newBillingMetrics()
	billingMetric.Register()

	statsMetric := newAPIStatMetrics()
	registry.MustRegister(statsMetric)

	serverMetric := newHTTPServerMetrics()
	registry.MustRegister(serverMetric)

	return &GateMetrics{
		registry:   registry,
		State:      stateMetric,
		Pool:       poolMetric,
		Billing:    billingMetric,
		Stats:      statsMetric,
		HTTPServer: serverMetric,
	}
}

func (g *GateMetrics) Unregister() {
	g.registry.Unregister(g.State)
	g.registry.Unregister(g.Pool)
	g.Billing.Unregister()
	g.registry.Unregister(g.Stats)
	g.registry.Unregister(g.HTTPServer)
}

func (g *GateMetrics) Handler() http.Handler {
	handler := http.NewServeMux()
	handler.Handle("/", promhttp.Handler())
	handler.Handle("/metrics/billing", promhttp.HandlerFor(g.Billing.Gatherer(), promhttp.HandlerOpts{}))
	return handler
}

func (g *GateMetrics) Gather() ([]*dto.MetricFamily, error) {
	return prometheus.Gatherers([]prometheus.Gatherer{g.Billing.Gatherer()}).Gather()
}