package push_test

import (
	"testing"
	"time"

	"galaxy/gateway/internal/push"
	"galaxy/gateway/internal/telemetry"
	"galaxy/gateway/internal/testutil"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestHubObserverClassifiesClosureReasons(t *testing.T) {
	t.Parallel()

	logger, _ := testutil.NewObservedLogger(t)
	telemetryRuntime := testutil.NewTelemetryRuntime(t, logger)
	hub := push.NewHubWithObserver(1, telemetry.NewPushObserver(telemetryRuntime))

	overflow, err := hub.Register(push.StreamBinding{
		UserID:          "user-123",
		DeviceSessionID: "device-session-overflow",
	})
	require.NoError(t, err)
	revoked, err := hub.Register(push.StreamBinding{
		UserID:          "user-123",
		DeviceSessionID: "device-session-revoked",
	})
	require.NoError(t, err)
	shutdown, err := hub.Register(push.StreamBinding{
		UserID:          "user-123",
		DeviceSessionID: "device-session-shutdown",
	})
	require.NoError(t, err)

	hub.Publish(push.Event{
		UserID:          "user-123",
		DeviceSessionID: "device-session-overflow",
		EventType:       "fleet.updated",
		EventID:         "event-1",
		PayloadBytes:    []byte("payload-1"),
	})
	hub.Publish(push.Event{
		UserID:          "user-123",
		DeviceSessionID: "device-session-overflow",
		EventType:       "fleet.updated",
		EventID:         "event-2",
		PayloadBytes:    []byte("payload-2"),
	})
	hub.RevokeDeviceSession("device-session-revoked")
	hub.Shutdown()

	select {
	case <-overflow.Done():
	case <-time.After(time.Second):
		require.FailNow(t, "overflow subscription did not close")
	}
	select {
	case <-revoked.Done():
	case <-time.After(time.Second):
		require.FailNow(t, "revoked subscription did not close")
	}
	select {
	case <-shutdown.Done():
	case <-time.After(time.Second):
		require.FailNow(t, "shutdown subscription did not close")
	}

	metricsText := testutil.ScrapeMetrics(t, telemetryRuntime.Handler())
	assert.Contains(t, metricsText, `gateway_push_stream_closures_total`)
	assert.Contains(t, metricsText, `reason="overflow"`)
	assert.Contains(t, metricsText, `reason="revoked"`)
	assert.Contains(t, metricsText, `reason="shutdown"`)
	assert.Contains(t, metricsText, `gateway_push_active_streams`)
}
