package mru

import (
	"testing"
)

func TestDefaultScopeObjects(t *testing.T) {
	defaults := DefaultScopeObjects()
	if len(defaults) == 0 {
		t.Error("DefaultScopeObjects should return non-empty list")
	}

	// ARCHITECTURE: Only core system objects in fallback defaults
	// CRM objects are loaded dynamically from metadata
	// User is the only guaranteed object in the fallback list
	foundUser := false
	for _, d := range defaults {
		if d == "User" {
			foundUser = true
			break
		}
	}
	if !foundUser {
		t.Error("Expected User in default scope objects (core system object)")
	}
}

func TestGetKeyPrefix(t *testing.T) {
	// ARCHITECTURE: Core Salesforce standard objects can be preloaded as fallbacks
	// so describe/search resources have stable keyPrefix values before metadata warmup.
	tests := []struct {
		input    string
		expected string
	}{
		{"User", "005"},         // Core system object - always present
		{"Organization", "00D"}, // Core system object
		{"Account", "001"},      // Standard object fallback
		{"Contact", "003"},      // Standard object fallback
		{"UnknownObject", ""},   // Unregistered object returns empty
		{"AB", ""},              // Unregistered object returns empty
	}

	for _, tt := range tests {
		t.Run(tt.input, func(t *testing.T) {
			result := GetKeyPrefix(tt.input)
			if result != tt.expected {
				t.Errorf("GetKeyPrefix(%q) = %q; want %q", tt.input, result, tt.expected)
			}
		})
	}
}

func TestResolveTypeFromID(t *testing.T) {
	// ARCHITECTURE: Common standard Salesforce objects are preloaded in the fallback map.
	tests := []struct {
		name        string
		input       string
		wantType    string
		wantSuccess bool
	}{
		{"User ID", "0055000001ABC12", "User", true},                 // Core system object
		{"Organization ID", "00D5000001ABC12", "Organization", true}, // Core system object
		{"Account ID", "0015000001ABC12", "Account", true},           // Standard object fallback
		{"Unknown prefix", "XYZ5000001ABC12", "", false},
		{"Empty string", "", "", false},
		{"Too short", "00", "", false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			gotType, gotSuccess := ResolveTypeFromID(tt.input)
			if gotType != tt.wantType {
				t.Errorf("ResolveTypeFromID(%q) type = %q; want %q", tt.input, gotType, tt.wantType)
			}
			if gotSuccess != tt.wantSuccess {
				t.Errorf("ResolveTypeFromID(%q) success = %v; want %v", tt.input, gotSuccess, tt.wantSuccess)
			}
		})
	}
}

func TestRegisterKeyPrefix(t *testing.T) {
	// Register a custom prefix
	RegisterKeyPrefix("a0B", "CustomWidget__c")

	// Test that it can be resolved
	gotType, gotSuccess := ResolveTypeFromID("a0B5000001ABC12")
	if !gotSuccess {
		t.Error("Expected ResolveTypeFromID to succeed for registered prefix")
	}
	if gotType != "CustomWidget__c" {
		t.Errorf("ResolveTypeFromID for registered prefix = %q; want CustomWidget__c", gotType)
	}

	// Test that GetKeyPrefix returns it correctly
	gotPrefix := GetKeyPrefix("CustomWidget__c")
	if gotPrefix != "a0B" {
		t.Errorf("GetKeyPrefix for registered object = %q; want a0B", gotPrefix)
	}
}

func TestObjectAPINameRegex(t *testing.T) {
	validNames := []string{
		"Account",
		"Contact",
		"Custom_Object__c",
		"_InternalObject",
		"Account123",
	}

	invalidNames := []string{
		"Account.Name",
		"Object Name",
		"123Account",
		"Account-Name",
		"",
	}

	for _, name := range validNames {
		if !objectAPINameRegex.MatchString(name) {
			t.Errorf("Expected %q to be valid API name", name)
		}
	}

	for _, name := range invalidNames {
		if objectAPINameRegex.MatchString(name) {
			t.Errorf("Expected %q to be invalid API name", name)
		}
	}
}

func TestConstants(t *testing.T) {
	if MaxRecentItemsPerObject <= 0 {
		t.Error("MaxRecentItemsPerObject should be positive")
	}
	if MaxScopeOrderResults <= 0 {
		t.Error("MaxScopeOrderResults should be positive")
	}
	if MaxRelevantItemsTotal <= 0 {
		t.Error("MaxRelevantItemsTotal should be positive")
	}
}
