// Package provider provides property-based tests for cloud account ID to provider type mapping.
// This file contains property tests that verify the Registry correctly maps cloud account IDs
// to their corresponding provider types.
package provider

import (
	"testing"

	"AutoSSO/internal/config"

	"pgregory.net/rapid"
)

// Feature: autosso-refactoring, Property 4: 云账号 ID 到提供商类型映射
// For any configured cloud account ID, querying through configuration mapping
// should return the correct cloud platform type.
//
// **Validates: Requirements 2.6, 3.5, 9.5**

// genNonEmptyString generates a non-empty alphanumeric string suitable for account IDs.
func genNonEmptyString() *rapid.Generator[string] {
	return rapid.StringMatching(`[a-zA-Z][a-zA-Z0-9_-]{0,30}`)
}

// genAccountID generates a realistic cloud account ID.
func genAccountID() *rapid.Generator[string] {
	return rapid.OneOf(
		// AWS-style account ID (12 digits)
		rapid.StringMatching(`[0-9]{12}`),
		// GCP-style project ID
		rapid.StringMatching(`[a-z][a-z0-9-]{5,28}[a-z0-9]`),
		// Azure-style subscription ID (UUID format)
		rapid.StringMatching(`[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}`),
		// Alibaba-style account ID (16 digits)
		rapid.StringMatching(`[0-9]{16}`),
		// Generic alphanumeric ID
		genNonEmptyString(),
	)
}

// genAccountName generates a realistic cloud account name.
func genAccountName() *rapid.Generator[string] {
	return rapid.OneOf(
		// Descriptive names with environment
		rapid.StringMatching(`[a-z]+-[a-z]+-[a-z]+`),
		// Simple names
		genNonEmptyString(),
	)
}

// genAccountType generates a valid account type.
func genAccountType() *rapid.Generator[string] {
	return rapid.SampledFrom([]string{"prod", "test", "dev", "staging"})
}

// genRoleSuffix generates an optional role suffix for Azure.
func genRoleSuffix() *rapid.Generator[string] {
	return rapid.OneOf(
		rapid.Just(""),
		rapid.StringMatching(`-[a-z0-9]{1,5}`),
	)
}

// genCloudAccount generates a valid CloudAccount with unique ID.
func genCloudAccount() *rapid.Generator[config.CloudAccount] {
	return rapid.Custom(func(t *rapid.T) config.CloudAccount {
		return config.CloudAccount{
			ID:         genAccountID().Draw(t, "id"),
			Name:       genAccountName().Draw(t, "name"),
			Type:       genAccountType().Draw(t, "type"),
			RoleSuffix: genRoleSuffix().Draw(t, "role_suffix"),
		}
	})
}

// genUniqueCloudAccounts generates a slice of CloudAccounts with unique IDs.
func genUniqueCloudAccounts(minCount, maxCount int) *rapid.Generator[[]config.CloudAccount] {
	return rapid.Custom(func(t *rapid.T) []config.CloudAccount {
		count := rapid.IntRange(minCount, maxCount).Draw(t, "count")
		accounts := make([]config.CloudAccount, 0, count)
		usedIDs := make(map[string]bool)

		for i := 0; i < count; i++ {
			// Generate unique ID
			var id string
			for {
				id = genAccountID().Draw(t, "id")
				if !usedIDs[id] {
					usedIDs[id] = true
					break
				}
			}

			accounts = append(accounts, config.CloudAccount{
				ID:         id,
				Name:       genAccountName().Draw(t, "name"),
				Type:       genAccountType().Draw(t, "type"),
				RoleSuffix: genRoleSuffix().Draw(t, "role_suffix"),
			})
		}
		return accounts
	})
}

// genGloballyUniqueCloudAccounts generates CloudAccounts with IDs unique across all providers.
// The usedIDs map is shared across calls to ensure global uniqueness.
func genGloballyUniqueCloudAccounts(minCount, maxCount int, usedIDs map[string]bool) *rapid.Generator[[]config.CloudAccount] {
	return rapid.Custom(func(t *rapid.T) []config.CloudAccount {
		count := rapid.IntRange(minCount, maxCount).Draw(t, "count")
		accounts := make([]config.CloudAccount, 0, count)

		for i := 0; i < count; i++ {
			// Generate unique ID that hasn't been used by any provider
			var id string
			for {
				id = genAccountID().Draw(t, "id")
				if !usedIDs[id] {
					usedIDs[id] = true
					break
				}
			}

			accounts = append(accounts, config.CloudAccount{
				ID:         id,
				Name:       genAccountName().Draw(t, "name"),
				Type:       genAccountType().Draw(t, "type"),
				RoleSuffix: genRoleSuffix().Draw(t, "role_suffix"),
			})
		}
		return accounts
	})
}

// genGloballyUniqueCloudAccountsWithUniqueName generates CloudAccounts with both IDs and Names
// unique across all providers. This is specifically for Azure subscriptions which are mapped
// by both ID and Name.
func genGloballyUniqueCloudAccountsWithUniqueName(minCount, maxCount int, usedIDs map[string]bool) *rapid.Generator[[]config.CloudAccount] {
	return rapid.Custom(func(t *rapid.T) []config.CloudAccount {
		count := rapid.IntRange(minCount, maxCount).Draw(t, "count")
		accounts := make([]config.CloudAccount, 0, count)

		for i := 0; i < count; i++ {
			// Generate unique ID
			var id string
			for {
				id = genAccountID().Draw(t, "id")
				if !usedIDs[id] {
					usedIDs[id] = true
					break
				}
			}

			// Generate unique Name (also tracked in usedIDs since Azure maps by name too)
			var name string
			for {
				name = genAccountName().Draw(t, "name")
				if !usedIDs[name] {
					usedIDs[name] = true
					break
				}
			}

			accounts = append(accounts, config.CloudAccount{
				ID:         id,
				Name:       name,
				Type:       genAccountType().Draw(t, "type"),
				RoleSuffix: genRoleSuffix().Draw(t, "role_suffix"),
			})
		}
		return accounts
	})
}

// genAWSConfig generates a valid AWSConfig with unique account IDs.
func genAWSConfig() *rapid.Generator[config.AWSConfig] {
	return rapid.Custom(func(t *rapid.T) config.AWSConfig {
		return config.AWSConfig{
			IdentityCenterARN: "arn:aws:sso:::instance/" + genNonEmptyString().Draw(t, "instance_id"),
			IdentityStoreID:   "d-" + genNonEmptyString().Draw(t, "store_id"),
			Region:            "ap-northeast-1",
			Accounts:          genUniqueCloudAccounts(0, 10).Draw(t, "accounts"),
		}
	})
}

// genGCPConfig generates a valid GCPConfig with unique project IDs.
func genGCPConfig() *rapid.Generator[config.GCPConfig] {
	return rapid.Custom(func(t *rapid.T) config.GCPConfig {
		return config.GCPConfig{
			CredentialsFile: "./" + genNonEmptyString().Draw(t, "creds_file") + ".json",
			RoleMappingFile: "./" + genNonEmptyString().Draw(t, "role_file") + ".ini",
			Projects:        genUniqueCloudAccounts(0, 10).Draw(t, "projects"),
		}
	})
}

// genAzureConfig generates a valid AzureConfig with unique subscription IDs and names.
func genAzureConfig() *rapid.Generator[config.AzureConfig] {
	return rapid.Custom(func(t *rapid.T) config.AzureConfig {
		return config.AzureConfig{
			TenantID:      genNonEmptyString().Draw(t, "tenant_id"),
			ClientID:      genNonEmptyString().Draw(t, "client_id"),
			ClientSecret:  genNonEmptyString().Draw(t, "client_secret"),
			Subscriptions: genUniqueCloudAccounts(0, 10).Draw(t, "subscriptions"),
		}
	})
}

// genAlibabaConfig generates a valid AlibabaConfig with unique account IDs.
func genAlibabaConfig() *rapid.Generator[config.AlibabaConfig] {
	return rapid.Custom(func(t *rapid.T) config.AlibabaConfig {
		return config.AlibabaConfig{
			AuthType:    "ecs_ram_role",
			RoleName:    genNonEmptyString().Draw(t, "role_name"),
			DirectoryID: "d-" + genNonEmptyString().Draw(t, "directory_id"),
			Endpoint:    "cloudsso.cn-shanghai.aliyuncs.com",
			Accounts:    genUniqueCloudAccounts(0, 10).Draw(t, "accounts"),
		}
	})
}

// TestCloudAccountIDToProviderTypeMapping tests that for any configured cloud account ID,
// querying through configuration mapping returns the correct cloud platform type.
// Note: This test uses globally unique IDs across all providers to ensure each account ID
// maps to exactly one provider type.
//
// Feature: autosso-refactoring, Property 4: 云账号 ID 到提供商类型映射
// **Validates: Requirements 2.6, 3.5, 9.5**
func TestCloudAccountIDToProviderTypeMapping(t *testing.T) {
	rapid.Check(t, func(rt *rapid.T) {
		// Use a shared map to ensure global uniqueness across all providers
		// This prevents the same account ID from appearing in multiple providers
		usedIDs := make(map[string]bool)

		// Generate random cloud account configurations with globally unique IDs
		awsAccounts := genGloballyUniqueCloudAccounts(0, 10, usedIDs).Draw(rt, "aws_accounts")
		gcpProjects := genGloballyUniqueCloudAccounts(0, 10, usedIDs).Draw(rt, "gcp_projects")
		azureSubscriptions := genGloballyUniqueCloudAccountsWithUniqueName(0, 10, usedIDs).Draw(rt, "azure_subscriptions")
		alibabaAccounts := genGloballyUniqueCloudAccounts(0, 10, usedIDs).Draw(rt, "alibaba_accounts")

		// Create config with all providers
		cfg := &config.Config{
			Providers: config.ProvidersConfig{
				AWS: config.AWSConfig{
					IdentityCenterARN: "arn:aws:sso:::instance/" + genNonEmptyString().Draw(rt, "instance_id"),
					IdentityStoreID:   "d-" + genNonEmptyString().Draw(rt, "store_id"),
					Region:            "ap-northeast-1",
					Accounts:          awsAccounts,
				},
				GCP: config.GCPConfig{
					CredentialsFile: "./" + genNonEmptyString().Draw(rt, "creds_file") + ".json",
					RoleMappingFile: "./" + genNonEmptyString().Draw(rt, "role_file") + ".ini",
					Projects:        gcpProjects,
				},
				Azure: config.AzureConfig{
					TenantID:      genNonEmptyString().Draw(rt, "tenant_id"),
					ClientID:      genNonEmptyString().Draw(rt, "client_id"),
					ClientSecret:  genNonEmptyString().Draw(rt, "client_secret"),
					Subscriptions: azureSubscriptions,
				},
				Alibaba: config.AlibabaConfig{
					AuthType:    "ecs_ram_role",
					RoleName:    genNonEmptyString().Draw(rt, "role_name"),
					DirectoryID: "d-" + genNonEmptyString().Draw(rt, "directory_id"),
					Endpoint:    "cloudsso.cn-shanghai.aliyuncs.com",
					Accounts:    alibabaAccounts,
				},
			},
		}

		// Create registry from config
		registry, err := NewRegistry(cfg)
		if err != nil {
			rt.Fatalf("Failed to create registry: %v", err)
		}

		// Verify AWS account mappings
		for _, account := range awsAccounts {
			if account.ID == "" {
				continue // Empty IDs are skipped
			}
			providerType, found := registry.GetProviderType(account.ID)
			if !found {
				rt.Fatalf("AWS account ID %q not found in registry", account.ID)
			}
			if providerType != ProviderAWS {
				rt.Fatalf("AWS account ID %q mapped to wrong provider type: expected %s, got %s",
					account.ID, ProviderAWS, providerType)
			}
		}

		// Verify GCP project mappings
		for _, project := range gcpProjects {
			if project.ID == "" {
				continue // Empty IDs are skipped
			}
			providerType, found := registry.GetProviderType(project.ID)
			if !found {
				rt.Fatalf("GCP project ID %q not found in registry", project.ID)
			}
			if providerType != ProviderGCP {
				rt.Fatalf("GCP project ID %q mapped to wrong provider type: expected %s, got %s",
					project.ID, ProviderGCP, providerType)
			}
		}

		// Verify Azure subscription mappings (both ID and Name)
		for _, subscription := range azureSubscriptions {
			// Verify by ID
			if subscription.ID != "" {
				providerType, found := registry.GetProviderType(subscription.ID)
				if !found {
					rt.Fatalf("Azure subscription ID %q not found in registry", subscription.ID)
				}
				if providerType != ProviderAzure {
					rt.Fatalf("Azure subscription ID %q mapped to wrong provider type: expected %s, got %s",
						subscription.ID, ProviderAzure, providerType)
				}
			}

			// Verify by Name (Azure subscriptions are also mapped by name)
			if subscription.Name != "" {
				providerType, found := registry.GetProviderType(subscription.Name)
				if !found {
					rt.Fatalf("Azure subscription Name %q not found in registry", subscription.Name)
				}
				if providerType != ProviderAzure {
					rt.Fatalf("Azure subscription Name %q mapped to wrong provider type: expected %s, got %s",
						subscription.Name, ProviderAzure, providerType)
				}
			}
		}

		// Verify Alibaba account mappings
		for _, account := range alibabaAccounts {
			if account.ID == "" {
				continue // Empty IDs are skipped
			}
			providerType, found := registry.GetProviderType(account.ID)
			if !found {
				rt.Fatalf("Alibaba account ID %q not found in registry", account.ID)
			}
			if providerType != ProviderAlibaba {
				rt.Fatalf("Alibaba account ID %q mapped to wrong provider type: expected %s, got %s",
					account.ID, ProviderAlibaba, providerType)
			}
		}
	})
}

// TestCloudAccountIDMappingWithMixedProviders tests that the registry correctly
// handles configurations with accounts from multiple providers.
// Note: When the same ID appears in multiple providers, the last one wins (Alibaba > Azure > GCP > AWS).
//
// Feature: autosso-refactoring, Property 4: 云账号 ID 到提供商类型映射
// **Validates: Requirements 2.6, 3.5, 9.5**
func TestCloudAccountIDMappingWithMixedProviders(t *testing.T) {
	rapid.Check(t, func(rt *rapid.T) {
		// Generate a mix of accounts from different providers with globally unique IDs
		// to avoid ID collisions across providers
		usedIDs := make(map[string]bool)

		awsAccounts := genGloballyUniqueCloudAccounts(1, 5, usedIDs).Draw(rt, "aws_accounts")
		gcpProjects := genGloballyUniqueCloudAccounts(1, 5, usedIDs).Draw(rt, "gcp_projects")
		azureSubscriptions := genGloballyUniqueCloudAccountsWithUniqueName(1, 5, usedIDs).Draw(rt, "azure_subscriptions")
		alibabaAccounts := genGloballyUniqueCloudAccounts(1, 5, usedIDs).Draw(rt, "alibaba_accounts")

		cfg := &config.Config{
			Providers: config.ProvidersConfig{
				AWS: config.AWSConfig{
					Accounts: awsAccounts,
				},
				GCP: config.GCPConfig{
					Projects: gcpProjects,
				},
				Azure: config.AzureConfig{
					Subscriptions: azureSubscriptions,
				},
				Alibaba: config.AlibabaConfig{
					Accounts: alibabaAccounts,
				},
			},
		}

		registry, err := NewRegistry(cfg)
		if err != nil {
			rt.Fatalf("Failed to create registry: %v", err)
		}

		// Count expected mappings (all IDs are unique now)
		expectedCount := 0
		for _, acc := range awsAccounts {
			if acc.ID != "" {
				expectedCount++
			}
		}
		for _, proj := range gcpProjects {
			if proj.ID != "" {
				expectedCount++
			}
		}
		for _, sub := range azureSubscriptions {
			if sub.ID != "" {
				expectedCount++
			}
			if sub.Name != "" {
				expectedCount++ // Azure also maps by name
			}
		}
		for _, acc := range alibabaAccounts {
			if acc.ID != "" {
				expectedCount++
			}
		}

		// Verify total account count
		actualCount := registry.AccountCount()
		if actualCount != expectedCount {
			rt.Fatalf("Account count mismatch: expected %d, got %d", expectedCount, actualCount)
		}

		// Verify each provider type can be looked up correctly
		for _, acc := range awsAccounts {
			if acc.ID == "" {
				continue
			}
			pt, found := registry.GetProviderType(acc.ID)
			if !found || pt != ProviderAWS {
				rt.Fatalf("AWS account %q: expected AWS, got %s (found=%v)", acc.ID, pt, found)
			}
		}

		for _, proj := range gcpProjects {
			if proj.ID == "" {
				continue
			}
			pt, found := registry.GetProviderType(proj.ID)
			if !found || pt != ProviderGCP {
				rt.Fatalf("GCP project %q: expected GCP, got %s (found=%v)", proj.ID, pt, found)
			}
		}

		for _, sub := range azureSubscriptions {
			if sub.ID != "" {
				pt, found := registry.GetProviderType(sub.ID)
				if !found || pt != ProviderAzure {
					rt.Fatalf("Azure subscription ID %q: expected Azure, got %s (found=%v)", sub.ID, pt, found)
				}
			}
			if sub.Name != "" {
				pt, found := registry.GetProviderType(sub.Name)
				if !found || pt != ProviderAzure {
					rt.Fatalf("Azure subscription Name %q: expected Azure, got %s (found=%v)", sub.Name, pt, found)
				}
			}
		}

		for _, acc := range alibabaAccounts {
			if acc.ID == "" {
				continue
			}
			pt, found := registry.GetProviderType(acc.ID)
			if !found || pt != ProviderAlibaba {
				rt.Fatalf("Alibaba account %q: expected Alibaba, got %s (found=%v)", acc.ID, pt, found)
			}
		}
	})
}

// TestAzureSubscriptionIDAndNameLookup specifically tests that Azure subscriptions
// can be looked up by both ID and Name.
//
// Feature: autosso-refactoring, Property 4: 云账号 ID 到提供商类型映射
// **Validates: Requirements 2.6, 3.5, 9.5**
func TestAzureSubscriptionIDAndNameLookup(t *testing.T) {
	rapid.Check(t, func(rt *rapid.T) {
		// Generate Azure subscriptions with both ID and Name
		subscriptions := rapid.SliceOfN(
			rapid.Custom(func(t *rapid.T) config.CloudAccount {
				return config.CloudAccount{
					ID:         genAccountID().Draw(t, "id"),
					Name:       genAccountName().Draw(t, "name"),
					Type:       genAccountType().Draw(t, "type"),
					RoleSuffix: genRoleSuffix().Draw(t, "role_suffix"),
				}
			}),
			1, 10,
		).Draw(rt, "subscriptions")

		cfg := &config.Config{
			Providers: config.ProvidersConfig{
				Azure: config.AzureConfig{
					TenantID:      genNonEmptyString().Draw(rt, "tenant_id"),
					ClientID:      genNonEmptyString().Draw(rt, "client_id"),
					ClientSecret:  genNonEmptyString().Draw(rt, "client_secret"),
					Subscriptions: subscriptions,
				},
			},
		}

		registry, err := NewRegistry(cfg)
		if err != nil {
			rt.Fatalf("Failed to create registry: %v", err)
		}

		// Verify each subscription can be looked up by both ID and Name
		for _, sub := range subscriptions {
			// Lookup by ID
			if sub.ID != "" {
				pt, found := registry.GetProviderType(sub.ID)
				if !found {
					rt.Fatalf("Azure subscription ID %q not found in registry", sub.ID)
				}
				if pt != ProviderAzure {
					rt.Fatalf("Azure subscription ID %q: expected Azure, got %s", sub.ID, pt)
				}
			}

			// Lookup by Name
			if sub.Name != "" {
				pt, found := registry.GetProviderType(sub.Name)
				if !found {
					rt.Fatalf("Azure subscription Name %q not found in registry", sub.Name)
				}
				if pt != ProviderAzure {
					rt.Fatalf("Azure subscription Name %q: expected Azure, got %s", sub.Name, pt)
				}
			}
		}
	})
}

// TestUnknownAccountIDReturnsNotFound tests that querying for an unknown account ID
// returns not found.
//
// Feature: autosso-refactoring, Property 4: 云账号 ID 到提供商类型映射
// **Validates: Requirements 2.6, 3.5, 9.5**
func TestUnknownAccountIDReturnsNotFound(t *testing.T) {
	rapid.Check(t, func(rt *rapid.T) {
		// Generate some configured accounts
		awsAccounts := genUniqueCloudAccounts(1, 5).Draw(rt, "aws_accounts")
		gcpProjects := genUniqueCloudAccounts(1, 5).Draw(rt, "gcp_projects")

		cfg := &config.Config{
			Providers: config.ProvidersConfig{
				AWS: config.AWSConfig{
					Accounts: awsAccounts,
				},
				GCP: config.GCPConfig{
					Projects: gcpProjects,
				},
			},
		}

		registry, err := NewRegistry(cfg)
		if err != nil {
			rt.Fatalf("Failed to create registry: %v", err)
		}

		// Collect all configured IDs
		configuredIDs := make(map[string]bool)
		for _, acc := range awsAccounts {
			if acc.ID != "" {
				configuredIDs[acc.ID] = true
			}
		}
		for _, proj := range gcpProjects {
			if proj.ID != "" {
				configuredIDs[proj.ID] = true
			}
		}

		// Generate a random ID that is not in the configured IDs
		var unknownID string
		for {
			unknownID = genAccountID().Draw(rt, "unknown_id")
			if !configuredIDs[unknownID] {
				break
			}
		}

		// Verify that unknown ID returns not found
		_, found := registry.GetProviderType(unknownID)
		if found {
			rt.Fatalf("Unknown account ID %q should not be found in registry", unknownID)
		}
	})
}

// TestEmptyAccountIDsAreSkipped tests that empty account IDs are not registered.
//
// Feature: autosso-refactoring, Property 4: 云账号 ID 到提供商类型映射
// **Validates: Requirements 2.6, 3.5, 9.5**
func TestEmptyAccountIDsAreSkipped(t *testing.T) {
	rapid.Check(t, func(rt *rapid.T) {
		// Generate accounts with some empty IDs
		accountsWithEmptyIDs := rapid.SliceOfN(
			rapid.Custom(func(t *rapid.T) config.CloudAccount {
				// 50% chance of empty ID
				hasID := rapid.Bool().Draw(t, "has_id")
				id := ""
				if hasID {
					id = genAccountID().Draw(t, "id")
				}
				return config.CloudAccount{
					ID:   id,
					Name: genAccountName().Draw(t, "name"),
					Type: genAccountType().Draw(t, "type"),
				}
			}),
			1, 10,
		).Draw(rt, "accounts")

		cfg := &config.Config{
			Providers: config.ProvidersConfig{
				AWS: config.AWSConfig{
					Accounts: accountsWithEmptyIDs,
				},
			},
		}

		registry, err := NewRegistry(cfg)
		if err != nil {
			rt.Fatalf("Failed to create registry: %v", err)
		}

		// Count unique non-empty IDs (registry deduplicates by ID)
		uniqueIDs := make(map[string]bool)
		for _, acc := range accountsWithEmptyIDs {
			if acc.ID != "" {
				uniqueIDs[acc.ID] = true
			}
		}
		expectedCount := len(uniqueIDs)

		// Verify account count matches unique non-empty IDs
		actualCount := registry.AccountCount()
		if actualCount != expectedCount {
			rt.Fatalf("Account count mismatch: expected %d (unique non-empty IDs), got %d",
				expectedCount, actualCount)
		}

		// Verify empty string is not found
		_, found := registry.GetProviderType("")
		if found {
			rt.Fatalf("Empty account ID should not be found in registry")
		}
	})
}

// TestRegistryAccountCountMatchesConfiguredAccounts tests that the registry's
// account count matches the number of configured accounts.
// Note: This test uses globally unique IDs to avoid collisions across providers.
//
// Feature: autosso-refactoring, Property 4: 云账号 ID 到提供商类型映射
// **Validates: Requirements 2.6, 3.5, 9.5**
func TestRegistryAccountCountMatchesConfiguredAccounts(t *testing.T) {
	rapid.Check(t, func(rt *rapid.T) {
		// Use a shared map to ensure global uniqueness across all providers
		usedIDs := make(map[string]bool)

		// Generate random configurations with globally unique IDs
		awsAccounts := genGloballyUniqueCloudAccounts(0, 10, usedIDs).Draw(rt, "aws_accounts")
		gcpProjects := genGloballyUniqueCloudAccounts(0, 10, usedIDs).Draw(rt, "gcp_projects")
		azureSubscriptions := genGloballyUniqueCloudAccountsWithUniqueName(0, 10, usedIDs).Draw(rt, "azure_subscriptions")
		alibabaAccounts := genGloballyUniqueCloudAccounts(0, 10, usedIDs).Draw(rt, "alibaba_accounts")

		cfg := &config.Config{
			Providers: config.ProvidersConfig{
				AWS: config.AWSConfig{
					Accounts: awsAccounts,
				},
				GCP: config.GCPConfig{
					Projects: gcpProjects,
				},
				Azure: config.AzureConfig{
					Subscriptions: azureSubscriptions,
				},
				Alibaba: config.AlibabaConfig{
					Accounts: alibabaAccounts,
				},
			},
		}

		registry, err := NewRegistry(cfg)
		if err != nil {
			rt.Fatalf("Failed to create registry: %v", err)
		}

		// Calculate expected count
		expectedCount := 0
		for _, acc := range awsAccounts {
			if acc.ID != "" {
				expectedCount++
			}
		}
		for _, proj := range gcpProjects {
			if proj.ID != "" {
				expectedCount++
			}
		}
		for _, sub := range azureSubscriptions {
			if sub.ID != "" {
				expectedCount++
			}
			if sub.Name != "" {
				expectedCount++ // Azure also maps by name
			}
		}
		for _, acc := range alibabaAccounts {
			if acc.ID != "" {
				expectedCount++
			}
		}

		// Verify count
		actualCount := registry.AccountCount()
		if actualCount != expectedCount {
			rt.Fatalf("Account count mismatch: expected %d, got %d", expectedCount, actualCount)
		}
	})
}

// TestListAccountsReturnsCorrectAccountsForProviderType tests that ListAccounts
// returns the correct accounts for each provider type.
// Note: This test uses globally unique IDs to avoid collisions across providers.
//
// Feature: autosso-refactoring, Property 4: 云账号 ID 到提供商类型映射
// **Validates: Requirements 2.6, 3.5, 9.5**
func TestListAccountsReturnsCorrectAccountsForProviderType(t *testing.T) {
	rapid.Check(t, func(rt *rapid.T) {
		// Use a shared map to ensure global uniqueness across all providers
		usedIDs := make(map[string]bool)

		// Generate random configurations with at least one account per provider
		awsAccounts := genGloballyUniqueCloudAccounts(1, 5, usedIDs).Draw(rt, "aws_accounts")
		gcpProjects := genGloballyUniqueCloudAccounts(1, 5, usedIDs).Draw(rt, "gcp_projects")
		azureSubscriptions := genGloballyUniqueCloudAccountsWithUniqueName(1, 5, usedIDs).Draw(rt, "azure_subscriptions")
		alibabaAccounts := genGloballyUniqueCloudAccounts(1, 5, usedIDs).Draw(rt, "alibaba_accounts")

		cfg := &config.Config{
			Providers: config.ProvidersConfig{
				AWS: config.AWSConfig{
					Accounts: awsAccounts,
				},
				GCP: config.GCPConfig{
					Projects: gcpProjects,
				},
				Azure: config.AzureConfig{
					Subscriptions: azureSubscriptions,
				},
				Alibaba: config.AlibabaConfig{
					Accounts: alibabaAccounts,
				},
			},
		}

		registry, err := NewRegistry(cfg)
		if err != nil {
			rt.Fatalf("Failed to create registry: %v", err)
		}

		// Verify AWS accounts
		awsAccountIDs := registry.ListAccounts(ProviderAWS)
		expectedAWSCount := 0
		for _, acc := range awsAccounts {
			if acc.ID != "" {
				expectedAWSCount++
			}
		}
		if len(awsAccountIDs) != expectedAWSCount {
			rt.Fatalf("AWS account count mismatch: expected %d, got %d",
				expectedAWSCount, len(awsAccountIDs))
		}

		// Verify GCP projects
		gcpProjectIDs := registry.ListAccounts(ProviderGCP)
		expectedGCPCount := 0
		for _, proj := range gcpProjects {
			if proj.ID != "" {
				expectedGCPCount++
			}
		}
		if len(gcpProjectIDs) != expectedGCPCount {
			rt.Fatalf("GCP project count mismatch: expected %d, got %d",
				expectedGCPCount, len(gcpProjectIDs))
		}

		// Verify Azure subscriptions (includes both ID and Name mappings)
		azureSubIDs := registry.ListAccounts(ProviderAzure)
		expectedAzureCount := 0
		for _, sub := range azureSubscriptions {
			if sub.ID != "" {
				expectedAzureCount++
			}
			if sub.Name != "" {
				expectedAzureCount++
			}
		}
		if len(azureSubIDs) != expectedAzureCount {
			rt.Fatalf("Azure subscription count mismatch: expected %d, got %d",
				expectedAzureCount, len(azureSubIDs))
		}

		// Verify Alibaba accounts
		alibabaAccountIDs := registry.ListAccounts(ProviderAlibaba)
		expectedAlibabaCount := 0
		for _, acc := range alibabaAccounts {
			if acc.ID != "" {
				expectedAlibabaCount++
			}
		}
		if len(alibabaAccountIDs) != expectedAlibabaCount {
			rt.Fatalf("Alibaba account count mismatch: expected %d, got %d",
				expectedAlibabaCount, len(alibabaAccountIDs))
		}
	})
}
