package middleware

import (
	"testing"
)

func TestNormalizeEndpoint(t *testing.T) {
	testCases := []struct {
		name     string
		input    string
		expected string
	}{
		{
			name:     "Simple path",
			input:    "/api/users",
			expected: "/api/users",
		},
		{
			name:     "Path with UUID",
			input:    "/api/users/abcdef12345",
			expected: "/api/users/{id}",
		},
		{
			name:     "Path with UUID and trailing slash",
			input:    "/api/users/abcdef12345/",
			expected: "/api/users/{id}/",
		},
		{
			name:     "Path with UUID in middle",
			input:    "/api/users/abcdef12345/profile",
			expected: "/api/users/{id}/profile",
		},
		{
			name:     "Path with query params",
			input:    "/api/users?page=1&limit=10",
			expected: "/api/users",
		},
		{
			name:     "Path with UUID and query params",
			input:    "/api/users/abcdef12345?detail=full",
			expected: "/api/users/abcdef12345", // Query params removed first, then UUID not matched
		},
		{
			name:     "Multiple UUIDs",
			input:    "/api/users/abc12345678/posts/def87654321",
			expected: "/api/users/{id}/posts/{id}",
		},
		{
			name:     "Root path",
			input:    "/",
			expected: "/",
		},
		{
			name:     "Empty path",
			input:    "",
			expected: "",
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			result := normalizeEndpoint(tc.input)
			if result != tc.expected {
				t.Errorf("Expected '%s', got '%s'", tc.expected, result)
			}
		})
	}
}

func TestNormalizeEndpointUUIDFormats(t *testing.T) {
	uuidFormats := []string{
		"abcdef12345",
		"ABCDEF12345",
		"abc_def1234",
		"abc-def1234",
		"mixedCase12",
	}

	for _, uuid := range uuidFormats {
		t.Run(uuid, func(t *testing.T) {
			input := "/api/users/" + uuid
			result := normalizeEndpoint(input)
			expected := "/api/users/{id}"

			if result != expected {
				t.Errorf("Expected '%s', got '%s' for UUID format '%s'", expected, result, uuid)
			}
		})
	}
}

func TestNormalizeEndpointComplexQueryStrings(t *testing.T) {
	testCases := []struct {
		input    string
		expected string
	}{
		{"/api/users?a=1&b=2&c=3", "/api/users"},
		{"/api/users?filter=active&sort=name&order=asc", "/api/users"},
		{"/api/users?search=john+doe", "/api/users"},
		{"/api/users?tags[]=tag1&tags[]=tag2", "/api/users"},
	}

	for _, tc := range testCases {
		result := normalizeEndpoint(tc.input)
		if result != tc.expected {
			t.Errorf("Input '%s': expected '%s', got '%s'", tc.input, tc.expected, result)
		}
	}
}

func TestNormalizeEndpointEdgeCases(t *testing.T) {
	testCases := []struct {
		name     string
		input    string
		expected string
	}{
		{
			name:     "Just query string",
			input:    "?param=value",
			expected: "",
		},
		{
			name:     "Double slashes",
			input:    "/api//users",
			expected: "/api//users",
		},
		{
			name:     "Trailing query without params",
			input:    "/api/users?",
			expected: "/api/users",
		},
		{
			name:     "UUID at end without slash",
			input:    "/users/abc12345678",
			expected: "/users/{id}",
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			result := normalizeEndpoint(tc.input)
			if result != tc.expected {
				t.Errorf("Expected '%s', got '%s'", tc.expected, result)
			}
		})
	}
}

func TestNormalizeEndpointPreservesNonUUID(t *testing.T) {
	testCases := []string{
		"/api/users/all",
		"/api/users/active",
		"/api/sessions/current",
		"/health",
		"/metrics",
	}

	for _, input := range testCases {
		t.Run(input, func(t *testing.T) {
			result := normalizeEndpoint(input)
			if result != input {
				t.Errorf("Non-UUID path should be preserved. Input: '%s', got '%s'", input, result)
			}
		})
	}
}

func TestNormalizeEndpointUUIDLength(t *testing.T) {
	// UUIDs must be exactly 11 characters
	testCases := []struct {
		name            string
		uuid            string
		shouldNormalize bool
	}{
		{"10 chars", "abcdefghij", false},
		{"11 chars", "abcdefghijk", true},
		{"12 chars", "abcdefghijkl", false},
		{"5 chars", "abcde", false},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			input := "/api/users/" + tc.uuid
			result := normalizeEndpoint(input)

			if tc.shouldNormalize {
				expected := "/api/users/{id}"
				if result != expected {
					t.Errorf("Expected '%s', got '%s'", expected, result)
				}
			} else {
				if result != input {
					t.Errorf("Should not normalize, expected '%s', got '%s'", input, result)
				}
			}
		})
	}
}

func BenchmarkNormalizeEndpoint(b *testing.B) {
	testPaths := []string{
		"/api/users",
		"/api/users/abc12345678",
		"/api/users/abc12345678/profile",
		"/api/users?page=1&limit=10",
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, path := range testPaths {
			normalizeEndpoint(path)
		}
	}
}
