// Package config provides configuration management for AutoSSO.
// This file contains tests for configuration validation functionality.
package config

import (
	"errors"
	"strings"
	"testing"
	"time"
)

// TestValidate_EmptyConfig tests validation of an empty configuration.
// Validates: Requirements 2.9, 9.3, 9.8
func TestValidate_EmptyConfig(t *testing.T) {
	cfg := &Config{}

	err := cfg.Validate()
	if err == nil {
		t.Fatal("expected validation error for empty config, got nil")
	}

	// Should have errors for required fields
	errs := GetValidationErrors(err)
	if len(errs) == 0 {
		t.Fatal("expected validation errors, got none")
	}

	// Check that required Feishu fields are reported
	hasFeishuAppID := false
	hasFeishuAppSecret := false
	hasDatabaseUser := false
	hasDatabasePassword := false

	for _, e := range errs {
		switch e.Field {
		case "feishu.app_id":
			hasFeishuAppID = true
		case "feishu.app_secret":
			hasFeishuAppSecret = true
		case "database.user":
			hasDatabaseUser = true
		case "database.password":
			hasDatabasePassword = true
		}
	}

	if !hasFeishuAppID {
		t.Error("expected error for missing feishu.app_id")
	}
	if !hasFeishuAppSecret {
		t.Error("expected error for missing feishu.app_secret")
	}
	if !hasDatabaseUser {
		t.Error("expected error for missing database.user")
	}
	if !hasDatabasePassword {
		t.Error("expected error for missing database.password")
	}
}

// TestValidate_ValidMinimalConfig tests validation of a minimal valid configuration.
// Validates: Requirements 2.9, 9.3
func TestValidate_ValidMinimalConfig(t *testing.T) {
	cfg := &Config{
		Feishu: FeishuConfig{
			AppID:     "test-app-id",
			AppSecret: "test-app-secret",
			BaseURL:   "https://open.feishu.cn",
		},
		Database: DatabaseConfig{
			Host:         "127.0.0.1",
			Port:         3306,
			User:         "testuser",
			Password:     "testpass",
			Database:     "testdb",
			MaxOpenConns: 10,
			MaxIdleConns: 5,
			MaxLifetime:  time.Hour,
		},
		Runtime: RuntimeConfig{
			PollInterval:        5 * time.Second,
			ExpireCheckInterval: time.Hour,
			GracePeriodDays:     3,
			HTTPTimeout:         10 * time.Second,
			MaxRetries:          3,
			LogLevel:            "info",
		},
	}

	err := cfg.Validate()
	if err != nil {
		t.Fatalf("expected no validation error for valid config, got: %v", err)
	}
}

// TestValidate_FeishuConfig tests Feishu configuration validation.
func TestValidate_FeishuConfig(t *testing.T) {
	tests := []struct {
		name        string
		feishu      FeishuConfig
		expectError bool
		errorField  string
	}{
		{
			name: "valid config",
			feishu: FeishuConfig{
				AppID:     "test-app-id",
				AppSecret: "test-app-secret",
				BaseURL:   "https://open.feishu.cn",
			},
			expectError: false,
		},
		{
			name: "missing app_id",
			feishu: FeishuConfig{
				AppSecret: "test-app-secret",
			},
			expectError: true,
			errorField:  "feishu.app_id",
		},
		// The following test case for AlibabaConfig is syntactically incorrect
		// within TestValidate_FeishuConfig because the 'tests' slice expects
		// a 'feishu FeishuConfig' field, not an 'alibaba AlibabaConfig' field.
		// To maintain syntactic correctness as per instructions, this block
		// cannot be directly inserted here.
		// If this test case was intended for a different function (e.g., TestValidate_AlibabaConfig),
		// it should be placed there.
		// For now, it is commented out to prevent compilation errors.
		/*
			{
				name: "invalid endpoint format",
				alibaba: AlibabaConfig{
					Endpoint:    "invalid-url",
					DirectoryID: "d-test",
					Accounts: []CloudAccount{
						{ID: "1234567890123456", Name: "test-account"},
					},
				},
				expectError: true,
				errorField:  "providers.alibaba.endpoint",
			},
		*/
		{
			name: "missing app_secret",
			feishu: FeishuConfig{
				AppID: "test-app-id",
			},
			expectError: true,
			errorField:  "feishu.app_secret",
		},
		{
			name: "invalid base_url",
			feishu: FeishuConfig{
				AppID:     "test-app-id",
				AppSecret: "test-app-secret",
				BaseURL:   "not-a-valid-url",
			},
			expectError: true,
			errorField:  "feishu.base_url",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cfg := createValidConfig()
			cfg.Feishu = tt.feishu

			err := cfg.Validate()
			if tt.expectError {
				if err == nil {
					t.Fatal("expected validation error, got nil")
				}
				if tt.errorField != "" && !containsFieldError(err, tt.errorField) {
					t.Errorf("expected error for field %s, got: %v", tt.errorField, err)
				}
			} else {
				if err != nil {
					t.Fatalf("expected no error, got: %v", err)
				}
			}
		})
	}
}

// TestValidate_DatabaseConfig tests Database configuration validation.
func TestValidate_DatabaseConfig(t *testing.T) {
	tests := []struct {
		name        string
		database    DatabaseConfig
		expectError bool
		errorField  string
	}{
		{
			name: "valid config",
			database: DatabaseConfig{
				Host:         "127.0.0.1",
				Port:         3306,
				User:         "testuser",
				Password:     "testpass",
				Database:     "testdb",
				MaxOpenConns: 10,
				MaxIdleConns: 5,
			},
			expectError: false,
		},
		{
			name: "missing user",
			database: DatabaseConfig{
				Host:         "127.0.0.1",
				Port:         3306,
				Password:     "testpass",
				MaxOpenConns: 10,
				MaxIdleConns: 5,
			},
			expectError: true,
			errorField:  "database.user",
		},
		{
			name: "missing password",
			database: DatabaseConfig{
				Host:         "127.0.0.1",
				Port:         3306,
				User:         "testuser",
				MaxOpenConns: 10,
				MaxIdleConns: 5,
			},
			expectError: true,
			errorField:  "database.password",
		},
		{
			name: "invalid port - too low",
			database: DatabaseConfig{
				Host:         "127.0.0.1",
				Port:         0,
				User:         "testuser",
				Password:     "testpass",
				MaxOpenConns: 10,
				MaxIdleConns: 5,
			},
			expectError: true,
			errorField:  "database.port",
		},
		{
			name: "invalid port - too high",
			database: DatabaseConfig{
				Host:         "127.0.0.1",
				Port:         70000,
				User:         "testuser",
				Password:     "testpass",
				MaxOpenConns: 10,
				MaxIdleConns: 5,
			},
			expectError: true,
			errorField:  "database.port",
		},
		{
			name: "invalid max_open_conns",
			database: DatabaseConfig{
				Host:         "127.0.0.1",
				Port:         3306,
				User:         "testuser",
				Password:     "testpass",
				MaxOpenConns: 0,
				MaxIdleConns: 5,
			},
			expectError: true,
			errorField:  "database.max_open_conns",
		},
		{
			name: "max_idle_conns exceeds max_open_conns",
			database: DatabaseConfig{
				Host:         "127.0.0.1",
				Port:         3306,
				User:         "testuser",
				Password:     "testpass",
				MaxOpenConns: 5,
				MaxIdleConns: 10,
			},
			expectError: true,
			errorField:  "database.max_idle_conns",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cfg := createValidConfig()
			cfg.Database = tt.database

			err := cfg.Validate()
			if tt.expectError {
				if err == nil {
					t.Fatal("expected validation error, got nil")
				}
				if tt.errorField != "" && !containsFieldError(err, tt.errorField) {
					t.Errorf("expected error for field %s, got: %v", tt.errorField, err)
				}
			} else {
				if err != nil {
					t.Fatalf("expected no error, got: %v", err)
				}
			}
		})
	}
}

// TestValidate_AWSConfig tests AWS provider configuration validation.
func TestValidate_AWSConfig(t *testing.T) {
	tests := []struct {
		name        string
		aws         AWSConfig
		expectError bool
		errorField  string
	}{
		{
			name:        "empty config - no accounts",
			aws:         AWSConfig{},
			expectError: false,
		},
		{
			name: "valid config with accounts",
			aws: AWSConfig{
				IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
				IdentityStoreID:   "d-95670a3c83",
				Region:            "ap-northeast-1",
				Accounts: []CloudAccount{
					{ID: "123456789012", Name: "test-account", Type: "prod"},
				},
			},
			expectError: false,
		},
		{
			name: "missing identity_center_arn with accounts",
			aws: AWSConfig{
				IdentityStoreID: "d-95670a3c83",
				Accounts: []CloudAccount{
					{ID: "123456789012", Name: "test-account"},
				},
			},
			expectError: true,
			errorField:  "providers.aws.identity_center_arn",
		},
		{
			name: "invalid identity_center_arn format",
			aws: AWSConfig{
				IdentityCenterARN: "invalid-arn",
				IdentityStoreID:   "d-95670a3c83",
				Accounts: []CloudAccount{
					{ID: "123456789012", Name: "test-account"},
				},
			},
			expectError: true,
			errorField:  "providers.aws.identity_center_arn",
		},
		{
			name: "missing identity_store_id with accounts",
			aws: AWSConfig{
				IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
				Accounts: []CloudAccount{
					{ID: "123456789012", Name: "test-account"},
				},
			},
			expectError: true,
			errorField:  "providers.aws.identity_store_id",
		},
		{
			name: "account missing ID",
			aws: AWSConfig{
				IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
				IdentityStoreID:   "d-95670a3c83",
				Accounts: []CloudAccount{
					{Name: "test-account"},
				},
			},
			expectError: true,
			errorField:  "providers.aws.accounts[0].id",
		},
		{
			name: "account missing name",
			aws: AWSConfig{
				IdentityCenterARN: "arn:aws:sso:::instance/ssoins-7758e707bb6ea352",
				IdentityStoreID:   "d-95670a3c83",
				Accounts: []CloudAccount{
					{ID: "123456789012"},
				},
			},
			expectError: true,
			errorField:  "providers.aws.accounts[0].name",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cfg := createValidConfig()
			cfg.Providers.AWS = tt.aws

			err := cfg.Validate()
			if tt.expectError {
				if err == nil {
					t.Fatal("expected validation error, got nil")
				}
				if tt.errorField != "" && !containsFieldError(err, tt.errorField) {
					t.Errorf("expected error for field %s, got: %v", tt.errorField, err)
				}
			} else {
				if err != nil {
					t.Fatalf("expected no error, got: %v", err)
				}
			}
		})
	}
}

// TestValidate_AzureConfig tests Azure provider configuration validation.
func TestValidate_AzureConfig(t *testing.T) {
	tests := []struct {
		name        string
		azure       AzureConfig
		expectError bool
		errorField  string
	}{
		{
			name:        "empty config - no subscriptions",
			azure:       AzureConfig{},
			expectError: false,
		},
		{
			name: "valid config with subscriptions",
			azure: AzureConfig{
				TenantID:     "ad881159-0593-4502-96e4-e2698b790a3d",
				ClientID:     "12345678-1234-1234-1234-123456789012",
				ClientSecret: "test-secret",
				Subscriptions: []CloudAccount{
					{ID: "ad881159-0593-4502-96e4-e2698b790a3d", Name: "test-sub"},
				},
			},
			expectError: false,
		},
		{
			name: "missing tenant_id with subscriptions",
			azure: AzureConfig{
				ClientID:     "12345678-1234-1234-1234-123456789012",
				ClientSecret: "test-secret",
				Subscriptions: []CloudAccount{
					{ID: "ad881159-0593-4502-96e4-e2698b790a3d", Name: "test-sub"},
				},
			},
			expectError: true,
			errorField:  "providers.azure.tenant_id",
		},
		{
			name: "invalid tenant_id format",
			azure: AzureConfig{
				TenantID:     "invalid-uuid",
				ClientID:     "12345678-1234-1234-1234-123456789012",
				ClientSecret: "test-secret",
				Subscriptions: []CloudAccount{
					{ID: "ad881159-0593-4502-96e4-e2698b790a3d", Name: "test-sub"},
				},
			},
			expectError: true,
			errorField:  "providers.azure.tenant_id",
		},
		{
			name: "missing client_id with subscriptions",
			azure: AzureConfig{
				TenantID:     "ad881159-0593-4502-96e4-e2698b790a3d",
				ClientSecret: "test-secret",
				Subscriptions: []CloudAccount{
					{ID: "ad881159-0593-4502-96e4-e2698b790a3d", Name: "test-sub"},
				},
			},
			expectError: true,
			errorField:  "providers.azure.client_id",
		},
		{
			name: "missing client_secret with subscriptions",
			azure: AzureConfig{
				TenantID: "ad881159-0593-4502-96e4-e2698b790a3d",
				ClientID: "12345678-1234-1234-1234-123456789012",
				Subscriptions: []CloudAccount{
					{ID: "ad881159-0593-4502-96e4-e2698b790a3d", Name: "test-sub"},
				},
			},
			expectError: true,
			errorField:  "providers.azure.client_secret",
		},
		{
			name: "subscription with invalid UUID",
			azure: AzureConfig{
				TenantID:     "ad881159-0593-4502-96e4-e2698b790a3d",
				ClientID:     "12345678-1234-1234-1234-123456789012",
				ClientSecret: "test-secret",
				Subscriptions: []CloudAccount{
					{ID: "invalid-uuid", Name: "test-sub"},
				},
			},
			expectError: true,
			errorField:  "providers.azure.subscriptions[0].id",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cfg := createValidConfig()
			cfg.Providers.Azure = tt.azure

			err := cfg.Validate()
			if tt.expectError {
				if err == nil {
					t.Fatal("expected validation error, got nil")
				}
				if tt.errorField != "" && !containsFieldError(err, tt.errorField) {
					t.Errorf("expected error for field %s, got: %v", tt.errorField, err)
				}
			} else {
				if err != nil {
					t.Fatalf("expected no error, got: %v", err)
				}
			}
		})
	}
}

// TestValidate_GCPConfig tests GCP provider configuration validation.
func TestValidate_GCPConfig(t *testing.T) {
	tests := []struct {
		name        string
		gcp         GCPConfig
		expectError bool
		errorField  string
	}{
		{
			name:        "empty config - no projects",
			gcp:         GCPConfig{},
			expectError: false,
		},
		{
			name: "valid config with projects",
			gcp: GCPConfig{
				CredentialsFile: "/path/to/credentials.json",
				Projects: []CloudAccount{
					{ID: "my-project", Name: "My Project"},
				},
			},
			expectError: false,
		},
		{
			name: "missing credentials_file with projects",
			gcp: GCPConfig{
				Projects: []CloudAccount{
					{ID: "my-project", Name: "My Project"},
				},
			},
			expectError: true,
			errorField:  "providers.gcp.credentials_file",
		},
		{
			name: "project missing ID",
			gcp: GCPConfig{
				CredentialsFile: "/path/to/credentials.json",
				Projects: []CloudAccount{
					{Name: "My Project"},
				},
			},
			expectError: true,
			errorField:  "providers.gcp.projects[0].id",
		},
		{
			name: "project missing name",
			gcp: GCPConfig{
				CredentialsFile: "/path/to/credentials.json",
				Projects: []CloudAccount{
					{ID: "my-project"},
				},
			},
			expectError: true,
			errorField:  "providers.gcp.projects[0].name",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cfg := createValidConfig()
			cfg.Providers.GCP = tt.gcp

			err := cfg.Validate()
			if tt.expectError {
				if err == nil {
					t.Fatal("expected validation error, got nil")
				}
				if tt.errorField != "" && !containsFieldError(err, tt.errorField) {
					t.Errorf("expected error for field %s, got: %v", tt.errorField, err)
				}
			} else {
				if err != nil {
					t.Fatalf("expected no error, got: %v", err)
				}
			}
		})
	}
}

// TestValidate_AlibabaConfig tests Alibaba Cloud provider configuration validation.
func TestValidate_AlibabaConfig(t *testing.T) {
	tests := []struct {
		name        string
		alibaba     AlibabaConfig
		expectError bool
		errorField  string
	}{
		{
			name:        "empty config - no accounts",
			alibaba:     AlibabaConfig{},
			expectError: false,
		},
		{
			name: "valid config with accounts",
			alibaba: AlibabaConfig{
				DirectoryID:     "d-00ts1z0rjv32",
				Endpoint:        "cloudsso.cn-shanghai.aliyuncs.com",
				Accounts: []CloudAccount{
					{ID: "5480039859161595", Name: "test-account"},
				},
			},
			expectError: false,
		},

		{
			name: "missing directory_id with accounts",
			alibaba: AlibabaConfig{
				Accounts: []CloudAccount{
					{ID: "5480039859161595", Name: "test-account"},
				},
			},
			expectError: true,
			errorField:  "providers.alibaba.directory_id",
		},
		{
			name: "invalid endpoint format",
			alibaba: AlibabaConfig{
				DirectoryID:     "d-00ts1z0rjv32",
				Endpoint:        "invalid endpoint with spaces",
				Accounts: []CloudAccount{
					{ID: "5480039859161595", Name: "test-account"},
				},
			},
			expectError: true,
			errorField:  "providers.alibaba.endpoint",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cfg := createValidConfig()
			cfg.Providers.Alibaba = tt.alibaba

			err := cfg.Validate()
			if tt.expectError {
				if err == nil {
					t.Fatal("expected validation error, got nil")
				}
				if tt.errorField != "" && !containsFieldError(err, tt.errorField) {
					t.Errorf("expected error for field %s, got: %v", tt.errorField, err)
				}
			} else {
				if err != nil {
					t.Fatalf("expected no error, got: %v", err)
				}
			}
		})
	}
}

// TestValidate_RuntimeConfig tests Runtime configuration validation.
func TestValidate_RuntimeConfig(t *testing.T) {
	tests := []struct {
		name        string
		runtime     RuntimeConfig
		expectError bool
		errorField  string
	}{
		{
			name: "valid config",
			runtime: RuntimeConfig{
				PollInterval:        5 * time.Second,
				ExpireCheckInterval: time.Hour,
				GracePeriodDays:     3,
				HTTPTimeout:         10 * time.Second,
				MaxRetries:          3,
				LogLevel:            "info",
			},
			expectError: false,
		},
		{
			name: "valid log levels",
			runtime: RuntimeConfig{
				PollInterval:        5 * time.Second,
				ExpireCheckInterval: time.Hour,
				GracePeriodDays:     3,
				HTTPTimeout:         10 * time.Second,
				MaxRetries:          3,
				LogLevel:            "debug",
			},
			expectError: false,
		},
		{
			name: "invalid log level",
			runtime: RuntimeConfig{
				PollInterval:        5 * time.Second,
				ExpireCheckInterval: time.Hour,
				GracePeriodDays:     3,
				HTTPTimeout:         10 * time.Second,
				MaxRetries:          3,
				LogLevel:            "invalid",
			},
			expectError: true,
			errorField:  "runtime.log_level",
		},
		{
			name: "negative poll_interval",
			runtime: RuntimeConfig{
				PollInterval:        -1 * time.Second,
				ExpireCheckInterval: time.Hour,
				GracePeriodDays:     3,
				HTTPTimeout:         10 * time.Second,
				MaxRetries:          3,
				LogLevel:            "info",
			},
			expectError: true,
			errorField:  "runtime.poll_interval",
		},
		{
			name: "negative grace_period_days",
			runtime: RuntimeConfig{
				PollInterval:        5 * time.Second,
				ExpireCheckInterval: time.Hour,
				GracePeriodDays:     -1,
				HTTPTimeout:         10 * time.Second,
				MaxRetries:          3,
				LogLevel:            "info",
			},
			expectError: true,
			errorField:  "runtime.grace_period_days",
		},
		{
			name: "negative max_retries",
			runtime: RuntimeConfig{
				PollInterval:        5 * time.Second,
				ExpireCheckInterval: time.Hour,
				GracePeriodDays:     3,
				HTTPTimeout:         10 * time.Second,
				MaxRetries:          -1,
				LogLevel:            "info",
			},
			expectError: true,
			errorField:  "runtime.max_retries",
		},
		{
			name: "valid whitelist emails",
			runtime: RuntimeConfig{
				PollInterval:        5 * time.Second,
				ExpireCheckInterval: time.Hour,
				GracePeriodDays:     3,
				HTTPTimeout:         10 * time.Second,
				MaxRetries:          3,
				LogLevel:            "info",
				WhitelistEmails:     []string{"user@example.com", "admin@company.org"},
			},
			expectError: false,
		},
		{
			name: "invalid whitelist email",
			runtime: RuntimeConfig{
				PollInterval:        5 * time.Second,
				ExpireCheckInterval: time.Hour,
				GracePeriodDays:     3,
				HTTPTimeout:         10 * time.Second,
				MaxRetries:          3,
				LogLevel:            "info",
				WhitelistEmails:     []string{"invalid-email"},
			},
			expectError: true,
			errorField:  "runtime.whitelist_emails[0]",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cfg := createValidConfig()
			cfg.Runtime = tt.runtime

			err := cfg.Validate()
			if tt.expectError {
				if err == nil {
					t.Fatal("expected validation error, got nil")
				}
				if tt.errorField != "" && !containsFieldError(err, tt.errorField) {
					t.Errorf("expected error for field %s, got: %v", tt.errorField, err)
				}
			} else {
				if err != nil {
					t.Fatalf("expected no error, got: %v", err)
				}
			}
		})
	}
}

// TestValidationError_Error tests the ValidationError.Error() method.
func TestValidationError_Error(t *testing.T) {
	err := &ValidationError{
		Field:   "feishu.app_id",
		Message: "required field is missing",
	}

	expected := "config validation error: feishu.app_id: required field is missing"
	if err.Error() != expected {
		t.Errorf("expected %q, got %q", expected, err.Error())
	}
}

// TestValidationErrors_Error tests the ValidationErrors.Error() method.
func TestValidationErrors_Error(t *testing.T) {
	tests := []struct {
		name     string
		errs     ValidationErrors
		contains []string
	}{
		{
			name:     "empty errors",
			errs:     ValidationErrors{},
			contains: []string{"no validation errors"},
		},
		{
			name: "single error",
			errs: ValidationErrors{
				{Field: "feishu.app_id", Message: "required field is missing"},
			},
			contains: []string{"feishu.app_id", "required field is missing"},
		},
		{
			name: "multiple errors",
			errs: ValidationErrors{
				{Field: "feishu.app_id", Message: "required field is missing"},
				{Field: "database.user", Message: "required field is missing"},
			},
			contains: []string{"2 errors", "feishu.app_id", "database.user"},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			errStr := tt.errs.Error()
			for _, substr := range tt.contains {
				if !strings.Contains(errStr, substr) {
					t.Errorf("expected error string to contain %q, got: %s", substr, errStr)
				}
			}
		})
	}
}

// TestIsValidationError tests the IsValidationError helper function.
func TestIsValidationError(t *testing.T) {
	tests := []struct {
		name     string
		err      error
		expected bool
	}{
		{
			name:     "nil error",
			err:      nil,
			expected: false,
		},
		{
			name:     "ValidationError",
			err:      &ValidationError{Field: "test", Message: "test"},
			expected: true,
		},
		{
			name: "ValidationErrors",
			err: ValidationErrors{
				{Field: "test", Message: "test"},
			},
			expected: true,
		},
		{
			name:     "other error",
			err:      errors.New("some other error"),
			expected: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := IsValidationError(tt.err)
			if result != tt.expected {
				t.Errorf("expected %v, got %v", tt.expected, result)
			}
		})
	}
}

// TestGetValidationErrors tests the GetValidationErrors helper function.
func TestGetValidationErrors(t *testing.T) {
	tests := []struct {
		name          string
		err           error
		expectedCount int
	}{
		{
			name:          "nil error",
			err:           nil,
			expectedCount: 0,
		},
		{
			name:          "ValidationError",
			err:           &ValidationError{Field: "test", Message: "test"},
			expectedCount: 1,
		},
		{
			name: "ValidationErrors with 2 errors",
			err: ValidationErrors{
				{Field: "test1", Message: "test1"},
				{Field: "test2", Message: "test2"},
			},
			expectedCount: 2,
		},
		{
			name:          "other error",
			err:           errors.New("some other error"),
			expectedCount: 0,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := GetValidationErrors(tt.err)
			if len(result) != tt.expectedCount {
				t.Errorf("expected %d errors, got %d", tt.expectedCount, len(result))
			}
		})
	}
}

// TestValidateURL tests the validateURL helper function.
func TestValidateURL(t *testing.T) {
	tests := []struct {
		name        string
		url         string
		expectError bool
	}{
		{"valid https url", "https://example.com", false},
		{"valid http url", "http://example.com", false},
		{"valid url with path", "https://example.com/api/v1", false},
		{"missing scheme", "example.com", true},
		{"missing host", "https://", true},
		{"empty string", "", true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := validateURL(tt.url)
			if tt.expectError && err == nil {
				t.Error("expected error, got nil")
			}
			if !tt.expectError && err != nil {
				t.Errorf("expected no error, got: %v", err)
			}
		})
	}
}

// TestValidateEmail tests the validateEmail helper function.
func TestValidateEmail(t *testing.T) {
	tests := []struct {
		name        string
		email       string
		expectError bool
	}{
		{"valid email", "user@example.com", false},
		{"valid email with subdomain", "user@mail.example.com", false},
		{"valid email with plus", "user+tag@example.com", false},
		{"missing @", "userexample.com", true},
		{"missing domain", "user@", true},
		{"empty string", "", true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := validateEmail(tt.email)
			if tt.expectError && err == nil {
				t.Error("expected error, got nil")
			}
			if !tt.expectError && err != nil {
				t.Errorf("expected no error, got: %v", err)
			}
		})
	}
}

// TestIsValidUUID tests the isValidUUID helper function.
func TestIsValidUUID(t *testing.T) {
	tests := []struct {
		name     string
		uuid     string
		expected bool
	}{
		{"valid uuid lowercase", "ad881159-0593-4502-96e4-e2698b790a3d", true},
		{"valid uuid uppercase", "AD881159-0593-4502-96E4-E2698B790A3D", true},
		{"valid uuid mixed case", "Ad881159-0593-4502-96e4-E2698b790a3d", true},
		{"invalid - missing dashes", "ad8811590593450296e4e2698b790a3d", false},
		{"invalid - wrong length", "ad881159-0593-4502-96e4-e2698b790a3", false},
		{"invalid - contains non-hex", "ad881159-0593-4502-96e4-e2698b790aXX", false},
		{"empty string", "", false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := isValidUUID(tt.uuid)
			if result != tt.expected {
				t.Errorf("expected %v, got %v", tt.expected, result)
			}
		})
	}
}

// TestIsValidARN tests the isValidARN helper function.
func TestIsValidARN(t *testing.T) {
	tests := []struct {
		name     string
		arn      string
		expected bool
	}{
		{"valid sso arn", "arn:aws:sso:::instance/ssoins-7758e707bb6ea352", true},
		{"valid s3 arn", "arn:aws:s3:::my-bucket", true},
		{"valid iam arn", "arn:aws:iam::123456789012:user/johndoe", true},
		{"valid gov cloud arn", "arn:aws-us-gov:s3:::my-bucket", true},
		{"invalid - missing arn prefix", "aws:sso:::instance/ssoins-7758e707bb6ea352", false},
		{"invalid - wrong format", "arn:aws", false},
		{"empty string", "", false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := isValidARN(tt.arn)
			if result != tt.expected {
				t.Errorf("expected %v, got %v", tt.expected, result)
			}
		})
	}
}

// Helper functions for tests

// createValidConfig creates a minimal valid configuration for testing.
func createValidConfig() *Config {
	return &Config{
		Feishu: FeishuConfig{
			AppID:     "test-app-id",
			AppSecret: "test-app-secret",
			BaseURL:   "https://open.feishu.cn",
		},
		Database: DatabaseConfig{
			Host:         "127.0.0.1",
			Port:         3306,
			User:         "testuser",
			Password:     "testpass",
			Database:     "testdb",
			MaxOpenConns: 10,
			MaxIdleConns: 5,
			MaxLifetime:  time.Hour,
		},
		Runtime: RuntimeConfig{
			PollInterval:        5 * time.Second,
			ExpireCheckInterval: time.Hour,
			GracePeriodDays:     3,
			HTTPTimeout:         10 * time.Second,
			MaxRetries:          3,
			LogLevel:            "info",
		},
	}
}

// containsFieldError checks if an error contains a validation error for a specific field.
func containsFieldError(err error, field string) bool {
	errs := GetValidationErrors(err)
	for _, e := range errs {
		if e.Field == field {
			return true
		}
	}
	return false
}
