package push_test

import (
	"testing"

	"scrabble/gateway/internal/push"
)

func TestHubRoutesByUser(t *testing.T) {
	h := push.NewHub(4)
	chA, cancelA := h.Subscribe("user-a")
	defer cancelA()
	chB, cancelB := h.Subscribe("user-b")
	defer cancelB()

	h.Publish(push.Event{UserID: "user-a", Kind: "your_turn"})

	select {
	case e := <-chA:
		if e.Kind != "your_turn" {
			t.Fatalf("user-a received %q", e.Kind)
		}
	default:
		t.Fatal("user-a should have received the event")
	}
	select {
	case <-chB:
		t.Fatal("user-b must not receive user-a's event")
	default:
	}
}

func TestHubDropsOnOverflow(t *testing.T) {
	h := push.NewHub(1)
	ch, cancel := h.Subscribe("u")
	defer cancel()
	for i := 0; i < 5; i++ {
		h.Publish(push.Event{UserID: "u", Kind: "chat_message"})
	}
	if got := len(ch); got != 1 {
		t.Fatalf("buffered %d events, want 1 (overflow dropped)", got)
	}
}

func TestHubUnsubscribeClosesChannel(t *testing.T) {
	h := push.NewHub(2)
	ch, cancel := h.Subscribe("u")
	cancel()
	if _, ok := <-ch; ok {
		t.Fatal("channel should be closed after unsubscribe")
	}
	if h.SubscriberCount() != 0 {
		t.Fatalf("subscriber count = %d, want 0", h.SubscriberCount())
	}
	h.Publish(push.Event{UserID: "u"}) // must not panic
}

func TestHubHasSubscribers(t *testing.T) {
	h := push.NewHub(2)
	if h.HasSubscribers("u") {
		t.Fatal("no subscribers yet")
	}
	_, cancel := h.Subscribe("u")
	if !h.HasSubscribers("u") {
		t.Error("u should be reported online after Subscribe")
	}
	if h.HasSubscribers("other") {
		t.Error("other has no subscription")
	}
	cancel()
	if h.HasSubscribers("u") {
		t.Error("u should be offline after unsubscribe")
	}
}
