package webrtc

import (
	"sync"
	"testing"
)

// mockSource implements the minimum Source-like shape needed by the registry.
// The real Source type is defined in Task 5; the registry only needs a
// stable type to store and retrieve.
type mockSource struct {
	id string
}

func (m *mockSource) ID() string { return m.id }

func TestRegistry_RegisterAndLookup(t *testing.T) {
	r := NewRegistry()
	src := &mockSource{id: "streamA"}

	if err := r.Register("streamA", src); err != nil {
		t.Fatalf("Register returned error: %v", err)
	}

	got, ok := r.Lookup("streamA")
	if !ok {
		t.Fatal("Lookup(streamA) returned ok=false, want true")
	}
	if got != src {
		t.Errorf("Lookup returned %v, want %v", got, src)
	}
}

func TestRegistry_LookupMissing(t *testing.T) {
	r := NewRegistry()
	_, ok := r.Lookup("nope")
	if ok {
		t.Error("Lookup on empty registry returned ok=true, want false")
	}
}

func TestRegistry_DuplicateRegister(t *testing.T) {
	r := NewRegistry()
	_ = r.Register("streamA", &mockSource{id: "streamA"})

	if err := r.Register("streamA", &mockSource{id: "streamA"}); err == nil {
		t.Error("duplicate Register should return error, got nil")
	}
}

func TestRegistry_Deregister(t *testing.T) {
	r := NewRegistry()
	_ = r.Register("streamA", &mockSource{id: "streamA"})
	r.Deregister("streamA")

	if _, ok := r.Lookup("streamA"); ok {
		t.Error("after Deregister, Lookup should return ok=false")
	}
}

func TestRegistry_ConcurrentAccess(t *testing.T) {
	r := NewRegistry()
	var wg sync.WaitGroup

	for i := 0; i < 100; i++ {
		wg.Add(3)
		id := string(rune('a' + (i % 26)))
		go func() { defer wg.Done(); _ = r.Register(id, &mockSource{id: id}) }()
		go func() { defer wg.Done(); _, _ = r.Lookup(id) }()
		go func() { defer wg.Done(); r.Deregister(id) }()
	}
	wg.Wait()
	// No assertion — test passes if -race doesn't flag anything.
}
