package service

import (
	"context"
	"encoding/json"
	"fmt"
	"regexp"
	"slices"
	"strings"

	coremodel "security-center-backend/internal/model"
	caasmmodel "security-center-backend/internal/modules/caasm/model"
	"security-center-backend/internal/modules/caasm/repository"
)

type ConfigService struct {
	repo repository.ConfigRepository
}

func NewConfigService(repo repository.ConfigRepository) *ConfigService {
	return &ConfigService{repo: repo}
}

func (s *ConfigService) Get(ctx context.Context) (caasmmodel.Config, error) {
	cfg, err := s.repo.Get(ctx)
	if err != nil {
		return caasmmodel.Config{}, err
	}
	ensureDefaults(cfg)
	return *cfg, nil
}

func (s *ConfigService) Update(ctx context.Context, data map[string]interface{}) (caasmmodel.Config, error) {
	// Fetch existing config to preserve timestamps
	existing, err := s.repo.Get(ctx)
	if err != nil {
		return caasmmodel.Config{}, fmt.Errorf("failed to get existing config: %w", err)
	}

	// Update data
	existing.Data = data

	// Ensure required defaults are present (e.g., type display mappings)
	ensureDefaults(existing)

	// Validate the config data
	if err := s.Validate(existing.Data); err != nil {
		return caasmmodel.Config{}, fmt.Errorf("config validation failed: %w", err)
	}

	if err := s.repo.Upsert(ctx, *existing); err != nil {
		return caasmmodel.Config{}, err
	}
	return *existing, nil
}

// GetDefaults returns the default configuration
func (s *ConfigService) GetDefaults(ctx context.Context) caasmmodel.ConfigData {
	return caasmmodel.ConfigDefaults()
}

// Validate validates the entire config data structure
func (s *ConfigService) Validate(data map[string]interface{}) error {
	if err := validateRawThrottlingShape(data); err != nil {
		return err
	}
	if err := validateRawCollectionScopeShape(data); err != nil {
		return err
	}
	if err := validateRawSyncSettingsShape(data); err != nil {
		return err
	}

	// Convert to ConfigData for validation
	var configData caasmmodel.ConfigData
	jsonBytes, err := json.Marshal(data)
	if err != nil {
		return fmt.Errorf("failed to marshal config data: %w", err)
	}

	if err := json.Unmarshal(jsonBytes, &configData); err != nil {
		return fmt.Errorf("failed to unmarshal config data: %w", err)
	}

	// Validate port catalog
	if configData.PortCatalog != nil {
		if err := s.ValidatePortCatalog(configData.PortCatalog); err != nil {
			return err
		}
	}

	// Validate tagging rules
	for i, rule := range configData.TaggingRules {
		if err := s.ValidateTaggingRule(&rule); err != nil {
			return fmt.Errorf("tagging rule %d (%s) validation failed: %w", i, rule.Name, err)
		}
	}

	// Validate ephemeral asset policy
	if configData.EphemeralAssetPolicy != nil {
		if err := s.ValidateEphemeralAssetPolicy(configData.EphemeralAssetPolicy); err != nil {
			return err
		}
	}

	if configData.CollectionScope != nil {
		if err := s.ValidateCollectionScope(configData.CollectionScope); err != nil {
			return err
		}
	}

	// Validate sync settings
	if configData.SyncSettings != nil {
		if err := s.ValidateSyncSettings(configData.SyncSettings); err != nil {
			return err
		}
	}
	if configData.Throttling != nil {
		if err := s.ValidateThrottling(configData.Throttling); err != nil {
			return err
		}
	}

	return nil
}

func validateRawCollectionScopeShape(data map[string]interface{}) error {
	if data == nil {
		return nil
	}

	raw, ok := data["collection_scope"]
	if !ok || raw == nil {
		return nil
	}

	scopeMap, ok := raw.(map[string]interface{})
	if !ok {
		return fmt.Errorf("collection_scope must be an object")
	}

	allowedKeys := map[string]struct{}{
		"ip_collection_scope":     {},
		"port_collection_scope":   {},
		"domain_collection_scope": {},
	}
	for key := range scopeMap {
		if _, allowed := allowedKeys[key]; !allowed {
			return fmt.Errorf("collection_scope.%s is not supported", key)
		}
	}

	return nil
}

func validateRawThrottlingShape(data map[string]interface{}) error {
	if data == nil {
		return nil
	}

	raw, ok := data["throttling"]
	if !ok || raw == nil {
		return nil
	}

	throttlingMap, ok := raw.(map[string]interface{})
	if !ok {
		return fmt.Errorf("throttling must be an object")
	}

	allowedThrottlingKeys := map[string]struct{}{
		"enabled":              {},
		"token_capacity":       {},
		"token_refill_per_sec": {},
		"adaptive_threshold":   {},
		"adaptive_window_sec":  {},
		"cool_off_sec":         {},
		"max_concurrency":      {},
		"min_concurrency":      {},
		"circuit_breaker":      {},
		"service_limits":       {},
	}
	for key := range throttlingMap {
		if _, allowed := allowedThrottlingKeys[key]; !allowed {
			return fmt.Errorf("throttling.%s is not supported", key)
		}
	}

	if rawCircuitBreaker, ok := throttlingMap["circuit_breaker"]; ok && rawCircuitBreaker != nil {
		circuitBreakerMap, ok := rawCircuitBreaker.(map[string]interface{})
		if !ok {
			return fmt.Errorf("throttling.circuit_breaker must be an object")
		}
		allowedCircuitBreakerKeys := map[string]struct{}{
			"threshold":    {},
			"cool_off_sec": {},
		}
		for key := range circuitBreakerMap {
			if _, allowed := allowedCircuitBreakerKeys[key]; !allowed {
				return fmt.Errorf("throttling.circuit_breaker.%s is not supported", key)
			}
		}
	}

	if rawServiceLimits, ok := throttlingMap["service_limits"]; ok && rawServiceLimits != nil {
		serviceLimitMap, ok := rawServiceLimits.(map[string]interface{})
		if !ok {
			return fmt.Errorf("throttling.service_limits must be an object")
		}
		allowedServiceLimitKeys := map[string]struct{}{
			"token_capacity":       {},
			"token_refill_per_sec": {},
			"max_concurrency":      {},
			"min_concurrency":      {},
		}
		for serviceName, rawSpec := range serviceLimitMap {
			specMap, ok := rawSpec.(map[string]interface{})
			if !ok {
				return fmt.Errorf("throttling.service_limits.%s must be an object", serviceName)
			}
			for key := range specMap {
				if _, allowed := allowedServiceLimitKeys[key]; !allowed {
					return fmt.Errorf("throttling.service_limits.%s.%s is not supported", serviceName, key)
				}
			}
		}
	}

	return nil
}

func validateRawSyncSettingsShape(data map[string]interface{}) error {
	if data == nil {
		return nil
	}

	raw, ok := data["sync_settings"]
	if !ok || raw == nil {
		return nil
	}

	var settingsMap map[string]interface{}
	switch typed := raw.(type) {
	case map[string]interface{}:
		settingsMap = typed
	case caasmmodel.SyncSettings:
		settingsMap = map[string]interface{}{
			"mode":                      typed.Mode,
			"lambda_function_name":      typed.LambdaFunctionName,
			"kill_switch_enabled":       typed.KillSwitchEnabled,
			"execution_timeout_minutes": typed.ExecutionTimeoutMinutes,
			"running_timeout_minutes":   typed.RunningTimeoutMinutes,
			"queued_timeout_minutes":    typed.QueuedTimeoutMinutes,
		}
	case *caasmmodel.SyncSettings:
		if typed == nil {
			return nil
		}
		settingsMap = map[string]interface{}{
			"mode":                      typed.Mode,
			"lambda_function_name":      typed.LambdaFunctionName,
			"kill_switch_enabled":       typed.KillSwitchEnabled,
			"execution_timeout_minutes": typed.ExecutionTimeoutMinutes,
			"running_timeout_minutes":   typed.RunningTimeoutMinutes,
			"queued_timeout_minutes":    typed.QueuedTimeoutMinutes,
		}
	default:
		return fmt.Errorf("sync_settings must be an object")
	}

	allowedKeys := map[string]struct{}{
		"mode":                      {},
		"lambda_function_name":      {},
		"kill_switch_enabled":       {},
		"execution_timeout_minutes": {},
		"running_timeout_minutes":   {},
		"queued_timeout_minutes":    {},
	}
	for key := range settingsMap {
		if _, allowed := allowedKeys[key]; !allowed {
			return fmt.Errorf("sync_settings.%s is not supported", key)
		}
	}

	return nil
}

func (s *ConfigService) ValidateCollectionScope(scope *caasmmodel.CollectionScope) error {
	if scope == nil {
		return nil
	}

	validScopes := map[caasmmodel.CollectionScopeMode]struct{}{
		caasmmodel.CollectionScopeAll:        {},
		caasmmodel.CollectionScopePublicOnly: {},
	}

	ipScope := scope.IPCollectionScope
	if ipScope == "" {
		ipScope = caasmmodel.CollectionScopeAll
	}
	if _, ok := validScopes[ipScope]; !ok {
		return fmt.Errorf("collection_scope.ip_collection_scope must be one of: all, public_only")
	}

	portScope := scope.PortCollectionScope
	if portScope == "" {
		portScope = caasmmodel.CollectionScopeAll
	}
	if _, ok := validScopes[portScope]; !ok {
		return fmt.Errorf("collection_scope.port_collection_scope must be one of: all, public_only")
	}

	domainScope := scope.DomainCollectionScope
	if domainScope == "" {
		domainScope = caasmmodel.CollectionScopeAll
	}
	if _, ok := validScopes[domainScope]; !ok {
		return fmt.Errorf("collection_scope.domain_collection_scope must be one of: all, public_only")
	}

	return nil
}

// ensureDefaults injects default values for optional sections (non-destructive to user overrides).
func ensureDefaults(cfg *caasmmodel.Config) {
	if cfg == nil {
		return
	}
	if cfg.Data == nil {
		cfg.Data = coremodel.JSONB{}
	}
	// Note: asset_type_display is now fully dynamic from database, no defaults injected
}

// ValidatePortCatalog validates port catalog entries
func (s *ConfigService) ValidatePortCatalog(catalog *caasmmodel.PortCatalog) error {
	if catalog == nil {
		return nil
	}

	// Check for duplicate ports
	portMap := make(map[string]bool)
	for _, portDef := range catalog.HighRiskPorts {
		key := fmt.Sprintf("%d:%s", portDef.Port, portDef.Protocol)
		if portMap[key] {
			return fmt.Errorf("duplicate port definition: %s", key)
		}
		portMap[key] = true

		// Validate port range
		if portDef.Port < 1 || portDef.Port > 65535 {
			return fmt.Errorf("invalid port number: %d (must be 1-65535)", portDef.Port)
		}

		// Validate protocol
		if portDef.Protocol != "tcp" && portDef.Protocol != "udp" {
			return fmt.Errorf("invalid protocol for port %d: %s (must be 'tcp' or 'udp')", portDef.Port, portDef.Protocol)
		}

		// Validate risk level
		validRiskLevels := map[string]bool{"critical": true, "high": true, "medium": true, "low": true}
		if !validRiskLevels[portDef.RiskLevel] {
			return fmt.Errorf("invalid risk level for port %d: %s", portDef.Port, portDef.RiskLevel)
		}
	}

	return nil
}

// ValidateTaggingRule validates a single tagging rule
func (s *ConfigService) ValidateTaggingRule(rule *caasmmodel.TaggingRule) error {
	if rule == nil {
		return fmt.Errorf("rule cannot be nil")
	}

	if rule.Name == "" {
		return fmt.Errorf("rule name cannot be empty")
	}

	// Validate conditions
	if err := s.ValidateRuleConditions(&rule.Conditions); err != nil {
		return err
	}

	// Ensure at least one tag is defined
	if len(rule.Tags) == 0 {
		return fmt.Errorf("rule must define at least one tag")
	}

	return nil
}

// ValidateRuleConditions validates rule conditions structure
func (s *ConfigService) ValidateRuleConditions(conditions *caasmmodel.RuleConditions) error {
	if conditions == nil {
		return fmt.Errorf("conditions cannot be nil")
	}

	// Ensure at least one condition type is specified
	if len(conditions.AllOf) == 0 && len(conditions.AnyOf) == 0 && len(conditions.NoneOf) == 0 {
		return fmt.Errorf("at least one condition must be specified (all_of, any_of, or none_of)")
	}

	// Validate each condition
	for _, cond := range conditions.AllOf {
		if err := s.ValidateCondition(&cond); err != nil {
			return fmt.Errorf("all_of condition validation failed: %w", err)
		}
	}
	for _, cond := range conditions.AnyOf {
		if err := s.ValidateCondition(&cond); err != nil {
			return fmt.Errorf("any_of condition validation failed: %w", err)
		}
	}
	for _, cond := range conditions.NoneOf {
		if err := s.ValidateCondition(&cond); err != nil {
			return fmt.Errorf("none_of condition validation failed: %w", err)
		}
	}

	return nil
}

// ValidateCondition validates a single condition
func (s *ConfigService) ValidateCondition(cond *caasmmodel.Condition) error {
	if cond == nil {
		return fmt.Errorf("condition cannot be nil")
	}

	if cond.Field == "" {
		return fmt.Errorf("condition field cannot be empty")
	}

	// Validate operator
	validOperators := map[string]bool{
		"equals":       true,
		"in":           true,
		"contains":     true,
		"regex":        true,
		"greater_than": true,
		"less_than":    true,
		"exists":       true,
	}
	if !validOperators[cond.Operator] {
		return fmt.Errorf("invalid operator: %s", cond.Operator)
	}

	// For regex operator, validate the regex pattern
	if cond.Operator == "regex" {
		if valueStr, ok := cond.Value.(string); ok {
			if _, err := regexp.Compile(valueStr); err != nil {
				return fmt.Errorf("invalid regex pattern: %w", err)
			}
		}
	}

	return nil
}

// ValidateEphemeralAssetPolicy validates ephemeral asset policy settings
func (s *ConfigService) ValidateEphemeralAssetPolicy(policy *caasmmodel.EphemeralAssetPolicy) error {
	if policy == nil {
		return nil
	}

	if policy.TTLHours < 1 {
		return fmt.Errorf("TTL hours must be at least 1")
	}

	if policy.TTLHours > 720 { // 30 days max
		return fmt.Errorf("TTL hours cannot exceed 720 (30 days)")
	}

	// Validate cron schedule if provided
	if policy.CleanupCronSchedule != "" {
		// Basic cron validation (5 or 6 fields)
		fields := strings.Fields(policy.CleanupCronSchedule)
		if len(fields) != 5 && len(fields) != 6 {
			return fmt.Errorf("invalid cron schedule format: must have 5 or 6 fields")
		}
	}

	return nil
}

// EvaluateTaggingRules evaluates tagging rules against asset properties and returns applicable tags
func (s *ConfigService) EvaluateTaggingRules(assetProps map[string]interface{}, rules []caasmmodel.TaggingRule) map[string]string {
	resultTags := make(map[string]string)

	// Sort rules by priority (higher priority first)
	// For now, just process in order
	for _, rule := range rules {
		if !rule.Enabled {
			continue
		}

		if s.evaluateConditions(assetProps, &rule.Conditions) {
			// Apply tags from this rule
			for k, v := range rule.Tags {
				// Higher priority rules can override lower priority ones
				resultTags[k] = v
			}
		}
	}

	return resultTags
}

// evaluateConditions evaluates complex rule conditions
func (s *ConfigService) evaluateConditions(props map[string]interface{}, conditions *caasmmodel.RuleConditions) bool {
	// Evaluate AllOf (AND logic)
	if len(conditions.AllOf) > 0 {
		for _, cond := range conditions.AllOf {
			if !s.evaluateSingleCondition(props, &cond) {
				return false // All must match
			}
		}
	}

	// Evaluate AnyOf (OR logic)
	if len(conditions.AnyOf) > 0 {
		anyMatch := false
		for _, cond := range conditions.AnyOf {
			if s.evaluateSingleCondition(props, &cond) {
				anyMatch = true
				break
			}
		}
		if !anyMatch {
			return false
		}
	}

	// Evaluate NoneOf (NOT logic)
	if len(conditions.NoneOf) > 0 {
		for _, cond := range conditions.NoneOf {
			if s.evaluateSingleCondition(props, &cond) {
				return false // None should match
			}
		}
	}

	return true
}

// evaluateSingleCondition evaluates a single condition against properties
func (s *ConfigService) evaluateSingleCondition(props map[string]interface{}, cond *caasmmodel.Condition) bool {
	value, exists := props[cond.Field]

	switch cond.Operator {
	case "exists":
		return exists
	case "equals":
		if !exists {
			return false
		}
		return fmt.Sprintf("%v", value) == fmt.Sprintf("%v", cond.Value)
	case "contains":
		if !exists {
			return false
		}
		valueStr := fmt.Sprintf("%v", value)
		searchStr := fmt.Sprintf("%v", cond.Value)
		return strings.Contains(strings.ToLower(valueStr), strings.ToLower(searchStr))
	case "in":
		if !exists {
			return false
		}
		// Expect cond.Value to be a slice
		if slice, ok := cond.Value.([]interface{}); ok {
			valueStr := fmt.Sprintf("%v", value)
			for _, item := range slice {
				if valueStr == fmt.Sprintf("%v", item) {
					return true
				}
			}
		}
		return false
	case "regex":
		if !exists {
			return false
		}
		valueStr := fmt.Sprintf("%v", value)
		pattern := fmt.Sprintf("%v", cond.Value)
		matched, _ := regexp.MatchString(pattern, valueStr)
		return matched
	default:
		return false
	}
}

// ValidateSyncSettings validates sync settings
func (s *ConfigService) ValidateSyncSettings(settings *caasmmodel.SyncSettings) error {
	if settings == nil {
		return nil
	}

	if settings.Mode != "queue" && settings.Mode != "serverless" {
		return fmt.Errorf("invalid sync mode: %s (must be 'queue' or 'serverless')", settings.Mode)
	}
	if settings.ExecutionTimeoutMinutes <= 0 {
		return fmt.Errorf("execution_timeout_minutes must be greater than 0")
	}
	if settings.RunningTimeoutMinutes <= 0 {
		return fmt.Errorf("running_timeout_minutes must be greater than 0")
	}
	if settings.QueuedTimeoutMinutes <= 0 {
		return fmt.Errorf("queued_timeout_minutes must be greater than 0")
	}

	return nil
}

func (s *ConfigService) ResolveSyncSettings(ctx context.Context) (caasmmodel.SyncSettings, error) {
	defaults := caasmmodel.ConfigDefaults().SyncSettings
	if defaults == nil {
		defaults = &caasmmodel.SyncSettings{Mode: "queue"}
	}

	resolved := *defaults
	if s == nil || s.repo == nil {
		return resolved, nil
	}

	cfg, err := s.Get(ctx)
	if err != nil {
		return resolved, err
	}
	if cfg.Data == nil {
		return resolved, nil
	}

	var configData caasmmodel.ConfigData
	jsonBytes, err := json.Marshal(cfg.Data)
	if err != nil {
		return resolved, fmt.Errorf("marshal config data: %w", err)
	}
	if err := json.Unmarshal(jsonBytes, &configData); err != nil {
		return resolved, fmt.Errorf("unmarshal config data: %w", err)
	}
	if configData.SyncSettings == nil {
		return resolved, nil
	}

	if strings.TrimSpace(configData.SyncSettings.Mode) != "" {
		resolved.Mode = configData.SyncSettings.Mode
	}
	if strings.TrimSpace(configData.SyncSettings.LambdaFunctionName) != "" {
		resolved.LambdaFunctionName = configData.SyncSettings.LambdaFunctionName
	}
	resolved.KillSwitchEnabled = configData.SyncSettings.KillSwitchEnabled
	if configData.SyncSettings.ExecutionTimeoutMinutes > 0 {
		resolved.ExecutionTimeoutMinutes = configData.SyncSettings.ExecutionTimeoutMinutes
	}
	if configData.SyncSettings.RunningTimeoutMinutes > 0 {
		resolved.RunningTimeoutMinutes = configData.SyncSettings.RunningTimeoutMinutes
	}
	if configData.SyncSettings.QueuedTimeoutMinutes > 0 {
		resolved.QueuedTimeoutMinutes = configData.SyncSettings.QueuedTimeoutMinutes
	}

	return resolved, nil
}

func (s *ConfigService) KillSwitchEnabled(ctx context.Context) (bool, error) {
	settings, err := s.ResolveSyncSettings(ctx)
	if err != nil {
		return false, err
	}
	return settings.KillSwitchEnabled, nil
}

func (s *ConfigService) SetKillSwitch(ctx context.Context, enabled bool) (caasmmodel.Config, error) {
	if s == nil || s.repo == nil {
		return caasmmodel.Config{}, fmt.Errorf("config repository not configured")
	}

	cfg, err := s.Get(ctx)
	if err != nil {
		return caasmmodel.Config{}, err
	}
	if cfg.Data == nil {
		cfg.Data = coremodel.JSONB{}
	}

	settings, err := s.ResolveSyncSettings(ctx)
	if err != nil {
		return caasmmodel.Config{}, err
	}
	settings.KillSwitchEnabled = enabled
	cfg.Data["sync_settings"] = settings

	return s.Update(ctx, cfg.Data)
}

// ValidateThrottling validates throttling config.
func (s *ConfigService) ValidateThrottling(cfg *caasmmodel.ThrottlingConfig) error {
	if cfg == nil {
		return nil
	}
	if cfg.TokenCapacity < 0 {
		return fmt.Errorf("token_capacity must be >=0")
	}
	if cfg.TokenCapacity > caasmmodel.HardCapThrottleTokenCapacity {
		return fmt.Errorf("token_capacity must be <=%d", caasmmodel.HardCapThrottleTokenCapacity)
	}
	if cfg.TokenRefillPerSec < 0 {
		return fmt.Errorf("token_refill_per_sec must be >=0")
	}
	if cfg.TokenRefillPerSec > caasmmodel.HardCapThrottleTokenRefillPerSec {
		return fmt.Errorf("token_refill_per_sec must be <=%d", caasmmodel.HardCapThrottleTokenRefillPerSec)
	}
	if cfg.AdaptiveThreshold < 0 {
		return fmt.Errorf("adaptive_threshold must be >=0")
	}
	if cfg.AdaptiveThreshold > caasmmodel.HardCapThrottleAdaptiveThreshold {
		return fmt.Errorf("adaptive_threshold must be <=%d", caasmmodel.HardCapThrottleAdaptiveThreshold)
	}
	if cfg.AdaptiveWindowSec < 0 || cfg.CoolOffSec < 0 {
		return fmt.Errorf("adaptive_window_sec and cool_off_sec must be >=0")
	}
	if cfg.AdaptiveWindowSec > caasmmodel.HardCapThrottleAdaptiveWindowSec {
		return fmt.Errorf("adaptive_window_sec must be <=%d", caasmmodel.HardCapThrottleAdaptiveWindowSec)
	}
	if cfg.CoolOffSec > caasmmodel.HardCapThrottleCoolOffSec {
		return fmt.Errorf("cool_off_sec must be <=%d", caasmmodel.HardCapThrottleCoolOffSec)
	}
	if cfg.MaxConcurrency < 0 || cfg.MinConcurrency < 0 {
		return fmt.Errorf("max_concurrency and min_concurrency must be >=0")
	}
	if cfg.MaxConcurrency > caasmmodel.HardCapThrottleMaxConcurrency {
		return fmt.Errorf("max_concurrency must be <=%d", caasmmodel.HardCapThrottleMaxConcurrency)
	}
	if cfg.MinConcurrency > caasmmodel.HardCapThrottleMinConcurrency {
		return fmt.Errorf("min_concurrency must be <=%d", caasmmodel.HardCapThrottleMinConcurrency)
	}
	if cfg.MaxConcurrency > 0 && cfg.MinConcurrency > cfg.MaxConcurrency {
		return fmt.Errorf("min_concurrency cannot exceed max_concurrency")
	}
	if cfg.CircuitBreaker != nil {
		if cfg.CircuitBreaker.Threshold < 0 {
			return fmt.Errorf("circuit_breaker.threshold must be >=0")
		}
		if cfg.CircuitBreaker.Threshold > caasmmodel.HardCapThrottleAdaptiveThreshold {
			return fmt.Errorf("circuit_breaker.threshold must be <=%d", caasmmodel.HardCapThrottleAdaptiveThreshold)
		}
		if cfg.CircuitBreaker.CoolOffSec < 0 {
			return fmt.Errorf("circuit_breaker.cool_off_sec must be >=0")
		}
		if cfg.CircuitBreaker.CoolOffSec > caasmmodel.HardCapThrottleCoolOffSec {
			return fmt.Errorf("circuit_breaker.cool_off_sec must be <=%d", caasmmodel.HardCapThrottleCoolOffSec)
		}
	}
	for serviceName, spec := range cfg.ServiceLimits {
		if strings.TrimSpace(serviceName) == "" {
			return fmt.Errorf("service_limits keys must not be empty")
		}
		if !isKnownThrottleServiceKey(serviceName) {
			return fmt.Errorf("service_limits contains unsupported service key: %s", serviceName)
		}
		if spec.TokenCapacity < 0 {
			return fmt.Errorf("service_limits.%s.token_capacity must be >=0", serviceName)
		}
		if spec.TokenCapacity > caasmmodel.HardCapThrottleTokenCapacity {
			return fmt.Errorf("service_limits.%s.token_capacity must be <=%d", serviceName, caasmmodel.HardCapThrottleTokenCapacity)
		}
		if spec.TokenRefillPerSec < 0 {
			return fmt.Errorf("service_limits.%s.token_refill_per_sec must be >=0", serviceName)
		}
		if spec.TokenRefillPerSec > caasmmodel.HardCapThrottleTokenRefillPerSec {
			return fmt.Errorf("service_limits.%s.token_refill_per_sec must be <=%d", serviceName, caasmmodel.HardCapThrottleTokenRefillPerSec)
		}
		if spec.MaxConcurrency < 0 || spec.MinConcurrency < 0 {
			return fmt.Errorf("service_limits.%s.max_concurrency and min_concurrency must be >=0", serviceName)
		}
		if spec.MaxConcurrency > caasmmodel.HardCapThrottleMaxConcurrency {
			return fmt.Errorf("service_limits.%s.max_concurrency must be <=%d", serviceName, caasmmodel.HardCapThrottleMaxConcurrency)
		}
		if spec.MinConcurrency > caasmmodel.HardCapThrottleMinConcurrency {
			return fmt.Errorf("service_limits.%s.min_concurrency must be <=%d", serviceName, caasmmodel.HardCapThrottleMinConcurrency)
		}
		if spec.MaxConcurrency > 0 && spec.MinConcurrency > spec.MaxConcurrency {
			return fmt.Errorf("service_limits.%s.min_concurrency cannot exceed max_concurrency", serviceName)
		}
	}
	return nil
}

func isKnownThrottleServiceKey(serviceName string) bool {
	normalized := strings.ToLower(strings.TrimSpace(serviceName))
	return slices.Contains(SupportedThrottleServiceKeys(), normalized)
}
