package skabandclient

import (
	"testing"
)

// TestValidateSessionID_Roundtrip tests that all session IDs generated by NewSessionID
// pass validation by ValidateSessionID
func TestValidateSessionID_Roundtrip(t *testing.T) {
	// Test multiple generated session IDs to ensure consistent behavior
	for i := range 1000 {
		sessionID := NewSessionID()
		if !ValidateSessionID(sessionID) {
			t.Errorf("Generated session ID %q failed validation (iteration %d)", sessionID, i)
		}
	}
}

// TestValidateSessionID_ValidCases tests various valid session ID formats
func TestValidateSessionID_ValidCases(t *testing.T) {
	tests := []struct {
		name      string
		sessionID string
		want      bool
	}{
		{"uppercase letters", "ABCD-EFGH-JKMN-PQRS", true},
		{"lowercase letters", "abcd-efgh-jkmn-pqrs", true},
		{"mixed case", "AbCd-EfGh-JkMn-PqRs", true},
		{"with numbers", "123A-5678-9BCD-EF0H", true},
		{"all numbers", "1234-5678-9012-3456", true},
		{"boundary chars lower", "0000-0000-0000-0000", true},
		{"boundary chars upper A-H", "ABCD-EFGH-ABCD-EFGH", true},
		{"boundary chars J-N", "JKMN-JKMN-JKMN-JKMN", true},
		{"boundary chars P-Z", "PQRS-TUVW-XYZ0-1234", true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := ValidateSessionID(tt.sessionID)
			if got != tt.want {
				t.Errorf("ValidateSessionID(%q) = %v, want %v", tt.sessionID, got, tt.want)
			}
		})
	}
}

// TestValidateSessionID_InvalidCases tests various invalid session ID formats
func TestValidateSessionID_InvalidCases(t *testing.T) {
	tests := []struct {
		name      string
		sessionID string
		want      bool
	}{
		{"empty string", "", false},
		{"too short", "ABC-DEF-GHI-JKL", false},
		{"too long", "ABCDE-EFGH-JKMN-PQRS", false},
		{"missing dashes", "ABCDEFGHJKMNPQRS", false},
		{"wrong dash positions", "AB-CD-EFGH-JKMNPQRS", false},
		{"invalid chars I", "ABCI-EFGH-JKMN-PQRS", false},
		{"invalid chars O", "ABCO-EFGH-JKMN-PQRS", false},
		{"invalid chars lowercase i", "ABCi-EFGH-JKMN-PQRS", false},
		{"invalid chars lowercase o", "ABCo-EFGH-JKMN-PQRS", false},
		{"special characters", "ABC!-EFGH-JKMN-PQRS", false},
		{"spaces", "ABC -EFGH-JKMN-PQRS", false},
		{"extra dashes", "ABCD--EFGH-JKMN-PQRS", false},
		{"underscore instead of dash", "ABCD_EFGH_JKMN_PQRS", false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := ValidateSessionID(tt.sessionID)
			if got != tt.want {
				t.Errorf("ValidateSessionID(%q) = %v, want %v", tt.sessionID, got, tt.want)
			}
		})
	}
}

// TestNewSessionID_Format tests that NewSessionID generates properly formatted IDs
func TestNewSessionID_Format(t *testing.T) {
	// Generate multiple session IDs and verify they all have the correct format
	for range 100 {
		sessionID := NewSessionID()

		// Check length
		if len(sessionID) != 19 { // xxxx-xxxx-xxxx-xxxx = 19 characters
			t.Errorf("Generated session ID %q has wrong length %d, expected 19", sessionID, len(sessionID))
		}

		// Check dash positions
		if sessionID[4] != '-' || sessionID[9] != '-' || sessionID[14] != '-' {
			t.Errorf("Generated session ID %q has wrong dash positions", sessionID)
		}

		// Should pass validation
		if !ValidateSessionID(sessionID) {
			t.Errorf("Generated session ID %q failed validation", sessionID)
		}
	}
}

// TestNewSessionID_Uniqueness tests that NewSessionID generates unique IDs
func TestNewSessionID_Uniqueness(t *testing.T) {
	seen := make(map[string]bool)
	count := 10000

	for range count {
		sessionID := NewSessionID()
		if seen[sessionID] {
			t.Errorf("Duplicate session ID generated: %q", sessionID)
		}
		seen[sessionID] = true
	}

	if len(seen) != count {
		t.Errorf("Expected %d unique session IDs, got %d", count, len(seen))
	}
}
