package streaming

import (
	"testing"
	"time"
)

func TestSessionManager_CreateSession(t *testing.T) {
	sm := NewSessionManager(5 * time.Minute)
	defer sm.Stop()

	clientID := sm.CreateSession()
	if clientID == "" {
		t.Error("Expected non-empty client ID")
	}

	if sm.SessionCount() != 1 {
		t.Errorf("Expected 1 session, got %d", sm.SessionCount())
	}
}

func TestSessionManager_ValidateSession(t *testing.T) {
	sm := NewSessionManager(5 * time.Minute)
	defer sm.Stop()

	clientID := sm.CreateSession()

	if !sm.ValidateSession(clientID) {
		t.Error("Expected session to be valid")
	}

	if sm.ValidateSession("invalid-id") {
		t.Error("Expected invalid session to fail validation")
	}
}

func TestSessionManager_Subscribe(t *testing.T) {
	sm := NewSessionManager(5 * time.Minute)
	defer sm.Stop()

	clientID := sm.CreateSession()

	if !sm.Subscribe(clientID, "/topic/test") {
		t.Error("Expected subscribe to succeed")
	}

	channels := sm.GetSubscribedChannels(clientID)
	if len(channels) != 1 || channels[0] != "/topic/test" {
		t.Errorf("Expected [/topic/test], got %v", channels)
	}
}

func TestSessionManager_Unsubscribe(t *testing.T) {
	sm := NewSessionManager(5 * time.Minute)
	defer sm.Stop()

	clientID := sm.CreateSession()
	sm.Subscribe(clientID, "/topic/test")
	sm.Unsubscribe(clientID, "/topic/test")

	channels := sm.GetSubscribedChannels(clientID)
	if len(channels) != 0 {
		t.Errorf("Expected empty channels, got %v", channels)
	}
}

func TestSessionManager_DestroySession(t *testing.T) {
	sm := NewSessionManager(5 * time.Minute)
	defer sm.Stop()

	clientID := sm.CreateSession()
	sm.DestroySession(clientID)

	if sm.ValidateSession(clientID) {
		t.Error("Expected session to be destroyed")
	}

	if sm.SessionCount() != 0 {
		t.Errorf("Expected 0 sessions, got %d", sm.SessionCount())
	}
}

func TestSessionManager_Stop(t *testing.T) {
	sm := NewSessionManager(5 * time.Minute)
	sm.CreateSession()

	// Should not panic
	sm.Stop()
}

func TestSessionManager_InvalidClientID(t *testing.T) {
	sm := NewSessionManager(5 * time.Minute)
	defer sm.Stop()

	if sm.Subscribe("invalid", "/topic/test") {
		t.Error("Expected subscribe with invalid client to fail")
	}

	if sm.Unsubscribe("invalid", "/topic/test") {
		t.Error("Expected unsubscribe with invalid client to fail")
	}

	channels := sm.GetSubscribedChannels("invalid")
	if channels != nil {
		t.Errorf("Expected nil channels for invalid client, got %v", channels)
	}
}

func TestSessionManager_MultipleSubscriptions(t *testing.T) {
	sm := NewSessionManager(5 * time.Minute)
	defer sm.Stop()

	clientID := sm.CreateSession()

	// Subscribe to multiple channels
	sm.Subscribe(clientID, "/topic/a")
	sm.Subscribe(clientID, "/topic/b")
	sm.Subscribe(clientID, "/topic/c")

	channels := sm.GetSubscribedChannels(clientID)
	if len(channels) != 3 {
		t.Errorf("Expected 3 subscriptions, got %d", len(channels))
	}
}

func TestSessionManager_MultipleSessions(t *testing.T) {
	sm := NewSessionManager(5 * time.Minute)
	defer sm.Stop()

	// Create multiple sessions
	id1 := sm.CreateSession()
	id2 := sm.CreateSession()
	id3 := sm.CreateSession()

	if sm.SessionCount() != 3 {
		t.Errorf("Expected 3 sessions, got %d", sm.SessionCount())
	}

	// Ensure unique IDs
	if id1 == id2 || id2 == id3 || id1 == id3 {
		t.Error("Expected unique session IDs")
	}

	// Destroy one session
	sm.DestroySession(id2)
	if sm.SessionCount() != 2 {
		t.Errorf("Expected 2 sessions after destroy, got %d", sm.SessionCount())
	}
}

func TestSessionManager_ResubscribeAfterDestroy(t *testing.T) {
	sm := NewSessionManager(5 * time.Minute)
	defer sm.Stop()

	clientID := sm.CreateSession()
	sm.Subscribe(clientID, "/topic/test")
	sm.DestroySession(clientID)

	// Try to subscribe after destroy - should fail
	if sm.Subscribe(clientID, "/topic/new") {
		t.Error("Expected subscribe after destroy to fail")
	}
}
