package pgsql

import (
	"testing"
)

func TestGetPostgresKeywords(t *testing.T) {
	keywords := GetPostgresKeywords()

	// Test that keywords are returned
	if len(keywords) == 0 {
		t.Fatal("Expected non-empty list of keywords")
	}

	// Test that we get all keywords from the map
	expectedCount := len(postgresKeywords)
	if len(keywords) != expectedCount {
		t.Errorf("Expected %d keywords, got %d", expectedCount, len(keywords))
	}

	// Test that all returned keywords exist in the map
	for _, keyword := range keywords {
		if !postgresKeywords[keyword] {
			t.Errorf("Keyword %q not found in postgresKeywords map", keyword)
		}
	}

	// Test that no duplicate keywords are returned
	seen := make(map[string]bool)
	for _, keyword := range keywords {
		if seen[keyword] {
			t.Errorf("Duplicate keyword found: %q", keyword)
		}
		seen[keyword] = true
	}
}

func TestPostgresKeywordsMap(t *testing.T) {
	tests := []struct {
		name    string
		keyword string
		want    bool
	}{
		{"SELECT keyword", "select", true},
		{"FROM keyword", "from", true},
		{"WHERE keyword", "where", true},
		{"TABLE keyword", "table", true},
		{"PRIMARY keyword", "primary", true},
		{"FOREIGN keyword", "foreign", true},
		{"CREATE keyword", "create", true},
		{"DROP keyword", "drop", true},
		{"ALTER keyword", "alter", true},
		{"INDEX keyword", "index", true},
		{"NOT keyword", "not", true},
		{"NULL keyword", "null", true},
		{"TRUE keyword", "true", true},
		{"FALSE keyword", "false", true},
		{"Non-keyword lowercase", "notakeyword", false},
		{"Non-keyword uppercase", "NOTAKEYWORD", false},
		{"Empty string", "", false},
	}

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

func TestPostgresKeywordsMapContent(t *testing.T) {
	// Test that the map contains expected common keywords
	commonKeywords := []string{
		"select", "insert", "update", "delete", "create", "drop", "alter",
		"table", "index", "view", "schema", "function", "procedure",
		"primary", "foreign", "key", "constraint", "unique", "check",
		"null", "not", "and", "or", "like", "in", "between",
		"join", "inner", "left", "right", "cross", "full", "outer",
		"where", "having", "group", "order", "limit", "offset",
		"union", "intersect", "except",
		"begin", "commit", "rollback", "transaction",
	}

	for _, keyword := range commonKeywords {
		if !postgresKeywords[keyword] {
			t.Errorf("Expected common keyword %q to be in postgresKeywords map", keyword)
		}
	}
}

func TestPostgresKeywordsMapSize(t *testing.T) {
	// PostgreSQL has a substantial list of reserved keywords
	// This test ensures the map has a reasonable number of entries
	minExpectedKeywords := 200 // PostgreSQL 13+ has 400+ reserved words

	if len(postgresKeywords) < minExpectedKeywords {
		t.Errorf("Expected at least %d keywords, got %d. The map may be incomplete.",
			minExpectedKeywords, len(postgresKeywords))
	}
}

func TestGetPostgresKeywordsConsistency(t *testing.T) {
	// Test that calling GetPostgresKeywords multiple times returns consistent results
	keywords1 := GetPostgresKeywords()
	keywords2 := GetPostgresKeywords()

	if len(keywords1) != len(keywords2) {
		t.Errorf("Inconsistent results: first call returned %d keywords, second call returned %d",
			len(keywords1), len(keywords2))
	}

	// Create a map from both results to compare
	map1 := make(map[string]bool)
	map2 := make(map[string]bool)

	for _, k := range keywords1 {
		map1[k] = true
	}
	for _, k := range keywords2 {
		map2[k] = true
	}

	// Check that both contain the same keywords
	for k := range map1 {
		if !map2[k] {
			t.Errorf("Keyword %q present in first call but not in second", k)
		}
	}
	for k := range map2 {
		if !map1[k] {
			t.Errorf("Keyword %q present in second call but not in first", k)
		}
	}
}
