package asinfo

import (
	"testing"
)

func TestGet(t *testing.T) {
	tests := []struct {
		name     string
		asn      int
		wantOK   bool
		wantDesc string
	}{
		{
			name:     "AS1 Level 3",
			asn:      1,
			wantOK:   true,
			wantDesc: "Level 3 Parent, LLC",
		},
		{
			name:     "AS15169 Google",
			asn:      15169,
			wantOK:   true,
			wantDesc: "Google LLC",
		},
		{
			name:   "Non-existent AS",
			asn:    999999999,
			wantOK: false,
		},
		{
			name:     "AS0 IANA Reserved",
			asn:      0,
			wantOK:   true,
			wantDesc: "Internet Assigned Numbers Authority",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			info, ok := Get(tt.asn)
			if ok != tt.wantOK {
				t.Errorf("Get(%d) ok = %v, want %v", tt.asn, ok, tt.wantOK)
				return
			}

			if ok && info.Description != tt.wantDesc {
				t.Errorf("Get(%d) description = %q, want %q", tt.asn, info.Description, tt.wantDesc)
			}
		})
	}
}

func TestGetDescription(t *testing.T) {
	tests := []struct {
		asn  int
		want string
	}{
		{1, "Level 3 Parent, LLC"},
		{999999999, ""},
	}

	for _, tt := range tests {
		t.Run("", func(t *testing.T) {
			if got := GetDescription(tt.asn); got != tt.want {
				t.Errorf("GetDescription(%d) = %q, want %q", tt.asn, got, tt.want)
			}
		})
	}
}

func TestGetHandle(t *testing.T) {
	tests := []struct {
		asn  int
		want string
	}{
		{1, "LVLT"},
		{0, "IANA-RSVD"},
		{999999999, ""},
	}

	for _, tt := range tests {
		t.Run("", func(t *testing.T) {
			if got := GetHandle(tt.asn); got != tt.want {
				t.Errorf("GetHandle(%d) = %q, want %q", tt.asn, got, tt.want)
			}
		})
	}
}

func TestTotal(t *testing.T) {
	total := Total()
	if total < 100000 {
		t.Errorf("Total() = %d, expected > 100000", total)
	}

	// Verify it's consistent
	if total2 := Total(); total2 != total {
		t.Errorf("Total() returned different values: %d vs %d", total, total2)
	}
}

func TestSearch(t *testing.T) {
	tests := []struct {
		name    string
		query   string
		wantMin int
	}{
		{
			name:    "Search for Google",
			query:   "Google",
			wantMin: 1,
		},
		{
			name:    "Search for University",
			query:   "University",
			wantMin: 10,
		},
		{
			name:    "Empty search",
			query:   "",
			wantMin: 0,
		},
		{
			name:    "Non-existent org",
			query:   "XYZABC123456",
			wantMin: 0,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			results := Search(tt.query)
			if len(results) < tt.wantMin {
				t.Errorf("Search(%q) returned %d results, want at least %d", tt.query, len(results), tt.wantMin)
			}

			// Verify all results contain the query
			if tt.query != "" {
				for _, r := range results {
					if !contains(r.Handle, tt.query) && !contains(r.Description, tt.query) {
						t.Errorf("Search result ASN %d doesn't contain query %q", r.ASN, tt.query)
					}
				}
			}
		})
	}
}

func TestDataIntegrity(t *testing.T) {
	// Verify no duplicate ASNs
	all := All()
	seen := make(map[int]bool)
	for _, info := range all {
		if seen[info.ASN] {
			t.Errorf("Duplicate ASN found: %d", info.ASN)
		}
		seen[info.ASN] = true
	}

	// Verify all entries have required fields
	for _, info := range all {
		if info.Handle == "" && info.ASN != 0 {
			t.Errorf("ASN %d has empty handle", info.ASN)
		}
		if info.Description == "" {
			t.Errorf("ASN %d has empty description", info.ASN)
		}
	}
}

func BenchmarkGet(b *testing.B) {
	// Common ASNs to lookup
	asns := []int{1, 15169, 13335, 32934, 8075, 16509}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		Get(asns[i%len(asns)])
	}
}

func BenchmarkSearch(b *testing.B) {
	queries := []string{"Google", "Amazon", "Microsoft", "University"}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		Search(queries[i%len(queries)])
	}
}
