package helper

import (
	"strings"
	"testing"
)

func TestUUIDGenerator(t *testing.T) {
	uuid := UUIDGenerator()

	// Check length
	if len(uuid) != IDLength {
		t.Errorf("Expected UUID length %d, got %d", IDLength, len(uuid))
	}

	// Check that it only contains valid characters
	for _, char := range uuid {
		if !strings.ContainsRune(IDCharset, char) {
			t.Errorf("Invalid character %c in UUID", char)
		}
	}
}

func TestUUIDGeneratorUniqueness(t *testing.T) {
	iterations := 1000
	uuids := make(map[string]bool)

	for i := 0; i < iterations; i++ {
		uuid := UUIDGenerator()

		if uuids[uuid] {
			t.Errorf("Duplicate UUID generated: %s", uuid)
		}

		uuids[uuid] = true
	}

	if len(uuids) != iterations {
		t.Errorf("Expected %d unique UUIDs, got %d", iterations, len(uuids))
	}
}

func TestUUIDGeneratorCharset(t *testing.T) {
	// Generate many UUIDs and verify all characters in charset are used
	iterations := 10000
	charCount := make(map[rune]int)

	for i := 0; i < iterations; i++ {
		uuid := UUIDGenerator()
		for _, char := range uuid {
			charCount[char]++
		}
	}

	// Verify we have a good distribution (not comprehensive but basic check)
	if len(charCount) < len(IDCharset)/2 {
		t.Errorf("Expected more character variety. Only %d out of %d characters used", len(charCount), len(IDCharset))
	}
}

func TestUUIDGeneratorNotEmpty(t *testing.T) {
	for i := 0; i < 100; i++ {
		uuid := UUIDGenerator()
		if uuid == "" {
			t.Error("Generated UUID should not be empty")
		}
	}
}

func TestUUIDGeneratorLength(t *testing.T) {
	// Verify length constant
	if IDLength != 11 {
		t.Errorf("Expected IDLength to be 11, got %d", IDLength)
	}

	// Generate multiple and check they all have correct length
	for i := 0; i < 100; i++ {
		uuid := UUIDGenerator()
		if len(uuid) != 11 {
			t.Errorf("Expected UUID length 11, got %d for UUID: %s", len(uuid), uuid)
		}
	}
}

func TestUUIDGeneratorCharsetContents(t *testing.T) {
	expected := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	if IDCharset != expected {
		t.Errorf("IDCharset changed. Expected: %s, Got: %s", expected, IDCharset)
	}

	if len(IDCharset) != 62 {
		t.Errorf("Expected IDCharset length 62, got %d", len(IDCharset))
	}
}

func TestUUIDGeneratorConcurrency(t *testing.T) {
	// Test concurrent UUID generation
	count := 1000
	uuids := make(chan string, count)

	// Generate UUIDs concurrently
	for i := 0; i < count; i++ {
		go func() {
			uuids <- UUIDGenerator()
		}()
	}

	// Collect results
	results := make(map[string]bool)
	for i := 0; i < count; i++ {
		uuid := <-uuids
		if results[uuid] {
			t.Errorf("Duplicate UUID in concurrent generation: %s", uuid)
		}
		results[uuid] = true
	}

	if len(results) != count {
		t.Errorf("Expected %d unique UUIDs, got %d", count, len(results))
	}
}

func TestUUIDGeneratorNoSpecialCharacters(t *testing.T) {
	for i := 0; i < 100; i++ {
		uuid := UUIDGenerator()

		// Check for common special characters that shouldn't be there
		specialChars := []string{"-", "_", ".", " ", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "+", "="}
		for _, special := range specialChars {
			if strings.Contains(uuid, special) {
				t.Errorf("UUID contains special character %s: %s", special, uuid)
			}
		}
	}
}

func TestUUIDGeneratorDistribution(t *testing.T) {
	// Generate many UUIDs and check character distribution is reasonable
	iterations := 10000
	positionCounts := make([]map[rune]int, IDLength)
	for i := range positionCounts {
		positionCounts[i] = make(map[rune]int)
	}

	for i := 0; i < iterations; i++ {
		uuid := UUIDGenerator()
		for pos, char := range uuid {
			positionCounts[pos][char]++
		}
	}

	// Each position should have multiple different characters
	for pos, counts := range positionCounts {
		if len(counts) < 10 {
			t.Errorf("Position %d has poor character variety: only %d different characters", pos, len(counts))
		}
	}
}

func BenchmarkUUIDGenerator(b *testing.B) {
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		UUIDGenerator()
	}
}

func BenchmarkUUIDGeneratorParallel(b *testing.B) {
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			UUIDGenerator()
		}
	})
}

func TestUUIDGeneratorFormat(t *testing.T) {
	uuid := UUIDGenerator()

	// Should not start or end with special characters
	firstChar := uuid[0]
	lastChar := uuid[len(uuid)-1]

	if !strings.ContainsRune(IDCharset, rune(firstChar)) {
		t.Errorf("First character %c not in charset", firstChar)
	}

	if !strings.ContainsRune(IDCharset, rune(lastChar)) {
		t.Errorf("Last character %c not in charset", lastChar)
	}
}
