package metrics

import (
	"testing"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	dto "github.com/prometheus/client_model/go"
)

func TestRegisterAndObserveReconcile(t *testing.T) {
	reg := prometheus.NewRegistry()
	collectors, err := Register(reg)
	if err != nil {
		t.Fatalf("Register: %v", err)
	}

	collectors.ObserveReconcile(ReconcileResultSuccess, 150*time.Millisecond)

	families, err := reg.Gather()
	if err != nil {
		t.Fatalf("Gather: %v", err)
	}
	byName := metricFamiliesByName(families)
	for _, name := range []string{
		"capacity_planner_reconciler_runs_total",
		"capacity_planner_reconciler_duration_seconds",
	} {
		if byName[name] == nil {
			t.Fatalf("missing metric family %q", name)
		}
	}
}

func TestRegisterRejectsNil(t *testing.T) {
	if _, err := Register(nil); err == nil {
		t.Fatal("nil registerer must fail")
	}
	var collectors *Collectors
	if err := collectors.Register(prometheus.NewRegistry()); err == nil {
		t.Fatal("nil collectors must fail")
	}
}

func TestObserveReconcileHandlesEmptyResult(t *testing.T) {
	reg := prometheus.NewRegistry()
	collectors, err := Register(reg)
	if err != nil {
		t.Fatalf("Register: %v", err)
	}

	collectors.ObserveReconcile("", time.Millisecond)

	families, err := reg.Gather()
	if err != nil {
		t.Fatalf("Gather: %v", err)
	}
	runs := metricFamiliesByName(families)["capacity_planner_reconciler_runs_total"]
	if runs == nil || len(runs.Metric) != 1 {
		t.Fatalf("runs metric = %+v, want one sample", runs)
	}
	if got := runs.Metric[0].Label[0].GetValue(); got != ReconcileResultUnknown {
		t.Fatalf("result label = %q, want %q", got, ReconcileResultUnknown)
	}
}

func metricFamiliesByName(families []*dto.MetricFamily) map[string]*dto.MetricFamily {
	out := make(map[string]*dto.MetricFamily, len(families))
	for _, family := range families {
		out[family.GetName()] = family
	}
	return out
}
