package metrics_test

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/uopi/uopi/internal/metrics"
)

func TestCounters(t *testing.T) {
	// Counters are package-level atomics; exercise each Inc function.
	metrics.IncWsConns()
	metrics.IncWsConns()
	metrics.DecWsConns()
	metrics.IncMsgIn()
	metrics.IncMsgOut()
	metrics.IncWrites()
	metrics.IncHistoryReqs()
	// No panic = pass; values are additive across tests but that's fine.
}

func TestHandlerFormat(t *testing.T) {
	handler := metrics.Handler(func() int { return 42 })

	req := httptest.NewRequest(http.MethodGet, "/metrics", nil)
	rec := httptest.NewRecorder()
	handler(rec, req)

	body := rec.Body.String()

	// Must contain all metric names.
	required := []string{
		"uopi_uptime_seconds",
		"uopi_ws_connections",
		"uopi_signal_subscriptions",
		"uopi_ws_messages_in_total",
		"uopi_ws_messages_out_total",
		"uopi_write_ops_total",
		"uopi_history_requests_total",
	}
	for _, name := range required {
		if !strings.Contains(body, name) {
			t.Errorf("metric %q not found in response body", name)
		}
	}

	// Content-Type must be set for Prometheus scrapers.
	ct := rec.Header().Get("Content-Type")
	if !strings.Contains(ct, "text/plain") {
		t.Errorf("Content-Type = %q, want text/plain", ct)
	}

	// activeSubs value 42 must appear.
	if !strings.Contains(body, "42") {
		t.Error("activeSubs value 42 not found in body")
	}
}

func TestHandlerNilActiveSubs(t *testing.T) {
	handler := metrics.Handler(nil)
	req := httptest.NewRequest(http.MethodGet, "/metrics", nil)
	rec := httptest.NewRecorder()
	handler(rec, req) // must not panic
	if rec.Code != http.StatusOK {
		t.Errorf("status = %d, want 200", rec.Code)
	}
}
