package config

import (
	"os"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.uber.org/zap"
)

func TestLoad(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalDBPassword := os.Getenv("DB_PASSWORD")
	originalJWTSecret := os.Getenv("JWT_SECRET")
	originalAppPort := os.Getenv("APP_PORT")

	// Nettoyer après le test
	defer func() {
		if originalDBPassword != "" {
			os.Setenv("DB_PASSWORD", originalDBPassword)
		} else {
			os.Unsetenv("DB_PASSWORD")
		}
		if originalJWTSecret != "" {
			os.Setenv("JWT_SECRET", originalJWTSecret)
		} else {
			os.Unsetenv("JWT_SECRET")
		}
		if originalAppPort != "" {
			os.Setenv("APP_PORT", originalAppPort)
		} else {
			os.Unsetenv("APP_PORT")
		}
	}()

	// Définir les variables requises
	os.Setenv("DB_PASSWORD", "test_password")
	os.Setenv("JWT_SECRET", "test_secret")

	config, err := Load()
	require.NoError(t, err)
	require.NotNil(t, config)

	// Vérifier les valeurs par défaut
	assert.Equal(t, 8080, config.AppPort)
	assert.Equal(t, "development", config.AppEnv)
	assert.Equal(t, "localhost", config.DBHost)
	assert.Equal(t, 5432, config.DBPort)
	assert.Equal(t, "veza", config.DBUser)
	assert.Equal(t, "veza_db", config.DBName)
	assert.Equal(t, "redis://localhost:6379", config.RedisURL)

	// Vérifier les valeurs requises
	assert.Equal(t, "test_password", config.DBPassword)
	assert.Equal(t, "test_secret", config.JWTSecret)
}

func TestLoad_WithCustomValues(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalDBPassword := os.Getenv("DB_PASSWORD")
	originalJWTSecret := os.Getenv("JWT_SECRET")
	originalAppPort := os.Getenv("APP_PORT")
	originalDBHost := os.Getenv("DB_HOST")
	originalDBPort := os.Getenv("DB_PORT")

	// Nettoyer après le test
	defer func() {
		if originalDBPassword != "" {
			os.Setenv("DB_PASSWORD", originalDBPassword)
		} else {
			os.Unsetenv("DB_PASSWORD")
		}
		if originalJWTSecret != "" {
			os.Setenv("JWT_SECRET", originalJWTSecret)
		} else {
			os.Unsetenv("JWT_SECRET")
		}
		if originalAppPort != "" {
			os.Setenv("APP_PORT", originalAppPort)
		} else {
			os.Unsetenv("APP_PORT")
		}
		if originalDBHost != "" {
			os.Setenv("DB_HOST", originalDBHost)
		} else {
			os.Unsetenv("DB_HOST")
		}
		if originalDBPort != "" {
			os.Setenv("DB_PORT", originalDBPort)
		} else {
			os.Unsetenv("DB_PORT")
		}
	}()

	// Définir des valeurs personnalisées
	os.Setenv("DB_PASSWORD", "custom_password")
	os.Setenv("JWT_SECRET", "custom_secret")
	os.Setenv("APP_PORT", "9090")
	os.Setenv("DB_HOST", "custom_host")
	os.Setenv("DB_PORT", "3306")

	config, err := Load()
	require.NoError(t, err)

	assert.Equal(t, 9090, config.AppPort)
	assert.Equal(t, "custom_host", config.DBHost)
	assert.Equal(t, 3306, config.DBPort)
	assert.Equal(t, "custom_password", config.DBPassword)
	assert.Equal(t, "custom_secret", config.JWTSecret)
}

func TestLoad_MissingRequiredVariable_DBPassword(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalDBPassword := os.Getenv("DB_PASSWORD")
	originalJWTSecret := os.Getenv("JWT_SECRET")

	// Nettoyer après le test
	defer func() {
		if originalDBPassword != "" {
			os.Setenv("DB_PASSWORD", originalDBPassword)
		} else {
			os.Unsetenv("DB_PASSWORD")
		}
		if originalJWTSecret != "" {
			os.Setenv("JWT_SECRET", originalJWTSecret)
		} else {
			os.Unsetenv("JWT_SECRET")
		}
	}()

	// Supprimer les variables requises
	os.Unsetenv("DB_PASSWORD")
	os.Setenv("JWT_SECRET", "test_secret")

	// MOD-P0-002: getEnvRequired() returns error, not panic - verify error is returned
	_, err := Load()
	assert.Error(t, err, "Should return error when DB_PASSWORD is missing")
	assert.Contains(t, err.Error(), "DB_PASSWORD", "Error message should mention DB_PASSWORD")
}

func TestLoad_MissingRequiredVariable_JWTSecret(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalDBPassword := os.Getenv("DB_PASSWORD")
	originalJWTSecret := os.Getenv("JWT_SECRET")

	// Nettoyer après le test
	defer func() {
		if originalDBPassword != "" {
			os.Setenv("DB_PASSWORD", originalDBPassword)
		} else {
			os.Unsetenv("DB_PASSWORD")
		}
		if originalJWTSecret != "" {
			os.Setenv("JWT_SECRET", originalJWTSecret)
		} else {
			os.Unsetenv("JWT_SECRET")
		}
	}()

	// Supprimer les variables requises
	os.Setenv("DB_PASSWORD", "test_password")
	os.Unsetenv("JWT_SECRET")

	// MOD-P0-002: getEnvRequired() returns error, not panic - verify error is returned
	_, err := Load()
	assert.Error(t, err, "Should return error when JWT_SECRET is missing")
	assert.Contains(t, err.Error(), "JWT_SECRET", "Error message should mention JWT_SECRET")
}

func TestGetEnv(t *testing.T) {
	// Sauvegarder la valeur originale
	originalValue := os.Getenv("TEST_VAR")

	defer func() {
		if originalValue != "" {
			os.Setenv("TEST_VAR", originalValue)
		} else {
			os.Unsetenv("TEST_VAR")
		}
	}()

	// Test avec valeur définie
	os.Setenv("TEST_VAR", "test_value")
	assert.Equal(t, "test_value", getEnv("TEST_VAR", "default"))

	// Test sans valeur (devrait retourner défaut)
	os.Unsetenv("TEST_VAR")
	assert.Equal(t, "default", getEnv("TEST_VAR", "default"))
}

func TestGetEnvInt(t *testing.T) {
	// Sauvegarder la valeur originale
	originalValue := os.Getenv("TEST_INT")

	defer func() {
		if originalValue != "" {
			os.Setenv("TEST_INT", originalValue)
		} else {
			os.Unsetenv("TEST_INT")
		}
	}()

	// Test avec valeur entière valide
	os.Setenv("TEST_INT", "42")
	assert.Equal(t, 42, getEnvInt("TEST_INT", 10))

	// Test sans valeur (devrait retourner défaut)
	os.Unsetenv("TEST_INT")
	assert.Equal(t, 10, getEnvInt("TEST_INT", 10))

	// Test avec valeur invalide (devrait retourner défaut)
	os.Setenv("TEST_INT", "not_a_number")
	assert.Equal(t, 10, getEnvInt("TEST_INT", 10))
}

func TestGetEnvRequired(t *testing.T) {
	// Sauvegarder la valeur originale
	originalValue := os.Getenv("TEST_REQUIRED")

	defer func() {
		if originalValue != "" {
			os.Setenv("TEST_REQUIRED", originalValue)
		} else {
			os.Unsetenv("TEST_REQUIRED")
		}
	}()

	// Test avec valeur définie
	os.Setenv("TEST_REQUIRED", "required_value")
	val, err := getEnvRequired("TEST_REQUIRED")
	require.NoError(t, err)
	assert.Equal(t, "required_value", val)

	// Test sans valeur (devrait retourner une erreur)
	os.Unsetenv("TEST_REQUIRED")
	_, err = getEnvRequired("TEST_REQUIRED")
	assert.Error(t, err, "Should return error when required variable is missing")
}

func TestLoad_DefaultValues(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalDBPassword := os.Getenv("DB_PASSWORD")
	originalJWTSecret := os.Getenv("JWT_SECRET")
	originalAppEnv := os.Getenv("APP_ENV")
	originalRedisURL := os.Getenv("REDIS_URL")

	// Nettoyer après le test
	defer func() {
		if originalDBPassword != "" {
			os.Setenv("DB_PASSWORD", originalDBPassword)
		} else {
			os.Unsetenv("DB_PASSWORD")
		}
		if originalJWTSecret != "" {
			os.Setenv("JWT_SECRET", originalJWTSecret)
		} else {
			os.Unsetenv("JWT_SECRET")
		}
		if originalAppEnv != "" {
			os.Setenv("APP_ENV", originalAppEnv)
		} else {
			os.Unsetenv("APP_ENV")
		}
		if originalRedisURL != "" {
			os.Setenv("REDIS_URL", originalRedisURL)
		} else {
			os.Unsetenv("REDIS_URL")
		}
	}()

	// Définir seulement les variables requises
	os.Setenv("DB_PASSWORD", "test")
	os.Setenv("JWT_SECRET", "secret")

	// Supprimer les variables optionnelles pour tester les valeurs par défaut
	os.Unsetenv("APP_ENV")
	os.Unsetenv("REDIS_URL")

	config, err := Load()
	require.NoError(t, err)

	// Vérifier que les valeurs par défaut sont utilisées
	assert.Equal(t, "development", config.AppEnv)
	assert.Equal(t, "redis://localhost:6379", config.RedisURL)
}

// TestNewConfig_RequiresJWTSecret vérifie que NewConfig() refuse de démarrer sans JWT_SECRET
// Ce test valide la correction de sécurité qui empêche l'utilisation d'une valeur par défaut hardcodée
func TestNewConfig_RequiresJWTSecret(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalJWTSecret := os.Getenv("JWT_SECRET")
	originalDatabaseURL := os.Getenv("DATABASE_URL")

	// Nettoyer après le test
	defer func() {
		if originalJWTSecret != "" {
			os.Setenv("JWT_SECRET", originalJWTSecret)
		} else {
			os.Unsetenv("JWT_SECRET")
		}
		if originalDatabaseURL != "" {
			os.Setenv("DATABASE_URL", originalDatabaseURL)
		} else {
			os.Unsetenv("DATABASE_URL")
		}
	}()

	// Supprimer JWT_SECRET - devrait causer une erreur
	os.Unsetenv("JWT_SECRET")
	// Définir DATABASE_URL pour éviter une erreur sur cette variable (on teste seulement JWT_SECRET)
	os.Setenv("DATABASE_URL", "postgresql://test:test@localhost:5432/test_db")

	// MOD-P0-002: getEnvRequired() returns error, not panic - verify error is returned
	_, err := NewConfig()
	assert.Error(t, err, "NewConfig should return error when JWT_SECRET is missing")
	assert.Contains(t, err.Error(), "JWT_SECRET", "Error message should mention JWT_SECRET")
}

// TestNewConfig_RequiresDatabaseURL vérifie que NewConfig() refuse de démarrer sans DATABASE_URL
// Ce test valide la correction de sécurité qui empêche l'utilisation d'une valeur par défaut avec credentials
func TestNewConfig_RequiresDatabaseURL(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalJWTSecret := os.Getenv("JWT_SECRET")
	originalDatabaseURL := os.Getenv("DATABASE_URL")

	// Nettoyer après le test
	defer func() {
		if originalJWTSecret != "" {
			os.Setenv("JWT_SECRET", originalJWTSecret)
		} else {
			os.Unsetenv("JWT_SECRET")
		}
		if originalDatabaseURL != "" {
			os.Setenv("DATABASE_URL", originalDatabaseURL)
		} else {
			os.Unsetenv("DATABASE_URL")
		}
	}()

	// Définir JWT_SECRET (minimum 32 caractères pour passer la validation)
	os.Setenv("JWT_SECRET", "test-jwt-secret-key-minimum-32-characters-long")
	// Supprimer DATABASE_URL - devrait causer une erreur
	os.Unsetenv("DATABASE_URL")

	// MOD-P0-002: getEnvRequired() returns error, not panic - verify error is returned
	_, err := NewConfig()
	assert.Error(t, err, "NewConfig should return error when DATABASE_URL is missing")
	assert.Contains(t, err.Error(), "DATABASE_URL", "Error message should mention DATABASE_URL")
}

// ============================================================================
// P0-SECURITY: Tests pour la sécurisation de la configuration CORS
// ============================================================================

// TestLoadConfig_DevDefaults vérifie que les defaults dev sont corrects (P0-SECURITY)
func TestLoadConfig_DevDefaults(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalEnv := os.Getenv("APP_ENV")
	originalJWTSecret := os.Getenv("JWT_SECRET")
	originalDatabaseURL := os.Getenv("DATABASE_URL")
	originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS")

	// Nettoyer après le test
	defer func() {
		if originalEnv != "" {
			os.Setenv("APP_ENV", originalEnv)
		} else {
			os.Unsetenv("APP_ENV")
		}
		if originalJWTSecret != "" {
			os.Setenv("JWT_SECRET", originalJWTSecret)
		} else {
			os.Unsetenv("JWT_SECRET")
		}
		if originalDatabaseURL != "" {
			os.Setenv("DATABASE_URL", originalDatabaseURL)
		} else {
			os.Unsetenv("DATABASE_URL")
		}
		if originalCORSOrigins != "" {
			os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins)
		} else {
			os.Unsetenv("CORS_ALLOWED_ORIGINS")
		}
	}()

	// Configuration pour développement
	os.Setenv("APP_ENV", "development")
	os.Setenv("JWT_SECRET", "test-jwt-secret-key-minimum-32-characters-long")
	os.Setenv("DATABASE_URL", "postgresql://test:test@localhost:5432/test_db")
	os.Unsetenv("CORS_ALLOWED_ORIGINS") // Pas défini pour tester les defaults

	// Note: NewConfig() nécessite Redis et DB, donc on teste seulement getCORSOrigins
	origins := getCORSOrigins("development")
	require.NotEmpty(t, origins, "Development should have default CORS origins")
	assert.Contains(t, origins, "http://localhost:3000", "Should include localhost:3000")
	assert.Contains(t, origins, "http://127.0.0.1:3000", "Should include 127.0.0.1:3000")
	assert.NotContains(t, origins, "*", "Should not contain wildcard")
}

// TestLoadConfig_ProdMissingCritical vérifie que prod refuse si CORS manquant (P0-SECURITY)
func TestLoadConfig_ProdMissingCritical(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalEnv := os.Getenv("APP_ENV")
	originalJWTSecret := os.Getenv("JWT_SECRET")
	originalDatabaseURL := os.Getenv("DATABASE_URL")
	originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS")

	// Nettoyer après le test
	defer func() {
		if originalEnv != "" {
			os.Setenv("APP_ENV", originalEnv)
		} else {
			os.Unsetenv("APP_ENV")
		}
		if originalJWTSecret != "" {
			os.Setenv("JWT_SECRET", originalJWTSecret)
		} else {
			os.Unsetenv("JWT_SECRET")
		}
		if originalDatabaseURL != "" {
			os.Setenv("DATABASE_URL", originalDatabaseURL)
		} else {
			os.Unsetenv("DATABASE_URL")
		}
		if originalCORSOrigins != "" {
			os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins)
		} else {
			os.Unsetenv("CORS_ALLOWED_ORIGINS")
		}
	}()

	// Configuration pour production sans CORS
	os.Setenv("APP_ENV", "production")
	os.Setenv("JWT_SECRET", "test-jwt-secret-key-minimum-32-characters-long")
	os.Setenv("DATABASE_URL", "postgresql://test:test@localhost:5432/test_db")
	os.Unsetenv("CORS_ALLOWED_ORIGINS") // Manquant intentionnellement

	// Créer une config minimale pour tester la validation
	cfg := &Config{
		Env:             "production",
		JWTSecret:       "test-jwt-secret-key-minimum-32-characters-long",
		DatabaseURL:     "postgresql://test:test@localhost:5432/test_db",
		RedisURL:        "redis://localhost:6379",
		AppPort:         8080,
		LogLevel:        "INFO",
		RateLimitLimit:  100,        // Valeur valide pour passer Validate()
		RateLimitWindow: 60,         // Valeur valide pour passer Validate()
		CORSOrigins:     []string{}, // Vide - mode strict (rejette toutes origines) - MOD-P0-001: Acceptable en prod
	}

	// Créer un logger minimal pour la config
	logger, _ := zap.NewDevelopment()
	cfg.Logger = logger

	// MOD-P0-001: CORS_ALLOWED_ORIGINS vide en production doit échouer (fail-fast)
	// La validation doit retourner une erreur car CORS vide rend le service inaccessible
	err := cfg.ValidateForEnvironment()
	require.Error(t, err, "Production config with empty CORS_ALLOWED_ORIGINS should fail validation (fail-fast)")
	assert.Contains(t, err.Error(), "CORS_ALLOWED_ORIGINS is required", "Error message should mention CORS_ALLOWED_ORIGINS requirement")
}

// TestNewConfig_ProductionCORSRequired vérifie que NewConfig() refuse de démarrer en production sans CORS
// MOD-P0-001: Fail-fast si CORS_ALLOWED_ORIGINS est vide en production
func TestNewConfig_ProductionCORSRequired(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalEnv := os.Getenv("APP_ENV")
	originalJWTSecret := os.Getenv("JWT_SECRET")
	originalDatabaseURL := os.Getenv("DATABASE_URL")
	originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS")
	originalRedisEnable := os.Getenv("REDIS_ENABLE")
	originalRabbitMQEnable := os.Getenv("RABBITMQ_ENABLE")

	// Nettoyer après le test
	defer func() {
		if originalEnv != "" {
			os.Setenv("APP_ENV", originalEnv)
		} else {
			os.Unsetenv("APP_ENV")
		}
		if originalJWTSecret != "" {
			os.Setenv("JWT_SECRET", originalJWTSecret)
		} else {
			os.Unsetenv("JWT_SECRET")
		}
		if originalDatabaseURL != "" {
			os.Setenv("DATABASE_URL", originalDatabaseURL)
		} else {
			os.Unsetenv("DATABASE_URL")
		}
		if originalCORSOrigins != "" {
			os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins)
		} else {
			os.Unsetenv("CORS_ALLOWED_ORIGINS")
		}
		if originalRedisEnable != "" {
			os.Setenv("REDIS_ENABLE", originalRedisEnable)
		} else {
			os.Unsetenv("REDIS_ENABLE")
		}
		if originalRabbitMQEnable != "" {
			os.Setenv("RABBITMQ_ENABLE", originalRabbitMQEnable)
		} else {
			os.Unsetenv("RABBITMQ_ENABLE")
		}
	}()

	// Configuration pour production sans CORS
	os.Setenv("APP_ENV", "production")
	os.Setenv("JWT_SECRET", "test-jwt-secret-key-minimum-32-characters-long")
	os.Setenv("DATABASE_URL", "postgresql://test:test@localhost:5432/test_db")
	os.Unsetenv("CORS_ALLOWED_ORIGINS")   // Manquant intentionnellement
	os.Setenv("REDIS_ENABLE", "false")    // Désactiver Redis pour éviter erreur de connexion
	os.Setenv("RABBITMQ_ENABLE", "false") // Désactiver RabbitMQ pour éviter erreur de connexion

	// MOD-P0-001: NewConfig() doit retourner une erreur car CORS est vide en production
	// La validation ValidateForEnvironment() est appelée dans NewConfig() et doit échouer
	_, err := NewConfig()
	require.Error(t, err, "NewConfig should return error when CORS_ALLOWED_ORIGINS is empty in production")
	// Le message d'erreur peut varier, vérifier qu'il mentionne CORS_ALLOWED_ORIGINS
	assert.Contains(t, err.Error(), "CORS_ALLOWED_ORIGINS", "Error message should mention CORS_ALLOWED_ORIGINS requirement")
}

// TestNewConfig_JWTSecretTooShort vérifie que NewConfig() refuse de démarrer si JWT_SECRET < 32 chars
// MOD-P0-002: Validation JWT secret length
func TestNewConfig_JWTSecretTooShort(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalJWTSecret := os.Getenv("JWT_SECRET")
	originalDatabaseURL := os.Getenv("DATABASE_URL")

	// Nettoyer après le test
	defer func() {
		if originalJWTSecret != "" {
			os.Setenv("JWT_SECRET", originalJWTSecret)
		} else {
			os.Unsetenv("JWT_SECRET")
		}
		if originalDatabaseURL != "" {
			os.Setenv("DATABASE_URL", originalDatabaseURL)
		} else {
			os.Unsetenv("DATABASE_URL")
		}
	}()

	// Définir JWT_SECRET trop court (< 32 chars)
	os.Setenv("JWT_SECRET", "short-secret") // 12 chars seulement
	os.Setenv("DATABASE_URL", "postgresql://test:test@localhost:5432/test_db")
	os.Setenv("REDIS_ENABLE", "false")
	os.Setenv("RABBITMQ_ENABLE", "false")

	// MOD-P0-002: NewConfig() doit retourner une erreur car JWT_SECRET est trop court
	// La validation Validate() est appelée dans NewConfig() et doit échouer
	_, err := NewConfig()
	require.Error(t, err, "NewConfig should return error when JWT_SECRET is too short")
	assert.Contains(t, err.Error(), "JWT_SECRET validation failed", "Error message should mention JWT_SECRET validation")
	assert.Contains(t, err.Error(), "32", "Error message should mention minimum length of 32")
}

// TestLoadConfig_ProdWildcard vérifie que prod refuse le wildcard (P0-SECURITY)
func TestLoadConfig_ProdWildcard(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalEnv := os.Getenv("APP_ENV")
	originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS")

	// Nettoyer après le test
	defer func() {
		if originalEnv != "" {
			os.Setenv("APP_ENV", originalEnv)
		} else {
			os.Unsetenv("APP_ENV")
		}
		if originalCORSOrigins != "" {
			os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins)
		} else {
			os.Unsetenv("CORS_ALLOWED_ORIGINS")
		}
	}()

	// Configuration pour production avec wildcard
	os.Setenv("APP_ENV", "production")

	// Créer une config minimale avec wildcard
	cfg := &Config{
		Env:             "production",
		JWTSecret:       "test-jwt-secret-key-minimum-32-characters-long",
		DatabaseURL:     "postgresql://test:test@localhost:5432/test_db",
		RedisURL:        "redis://localhost:6379",
		AppPort:         8080,
		LogLevel:        "INFO",
		RateLimitLimit:  100,           // Valeur valide pour passer Validate()
		RateLimitWindow: 60,            // Valeur valide pour passer Validate()
		CORSOrigins:     []string{"*"}, // Wildcard - devrait échouer en prod
	}

	// Créer un logger minimal pour la config
	logger, _ := zap.NewDevelopment()
	cfg.Logger = logger

	// La validation devrait échouer
	err := cfg.ValidateForEnvironment()
	require.Error(t, err, "Production config should fail validation when CORS contains wildcard")
	assert.Contains(t, err.Error(), "wildcard", "Error should mention wildcard prohibition")
}

// TestLoadConfig_ProdValid vérifie qu'une config prod valide passe (P0-SECURITY)
func TestLoadConfig_ProdValid(t *testing.T) {
	// Sauvegarder les valeurs originales
	originalEnv := os.Getenv("APP_ENV")
	originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS")

	// Nettoyer après le test
	defer func() {
		if originalEnv != "" {
			os.Setenv("APP_ENV", originalEnv)
		} else {
			os.Unsetenv("APP_ENV")
		}
		if originalCORSOrigins != "" {
			os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins)
		} else {
			os.Unsetenv("CORS_ALLOWED_ORIGINS")
		}
	}()

	// Configuration pour production valide
	os.Setenv("APP_ENV", "production")

	// Créer une config minimale valide
	cfg := &Config{
		Env:             "production",
		JWTSecret:       "test-jwt-secret-key-minimum-32-characters-long",
		DatabaseURL:     "postgresql://test:test@localhost:5432/test_db",
		RedisURL:        "redis://localhost:6379",
		AppPort:         8080,
		LogLevel:        "INFO",
		RateLimitLimit:  100,                                                      // Valeur valide pour passer Validate()
		RateLimitWindow: 60,                                                       // Valeur valide pour passer Validate()
		CORSOrigins:     []string{"https://app.veza.com", "https://www.veza.com"}, // Valide - pas de wildcard
	}

	// Créer un logger minimal pour la config
	logger, _ := zap.NewDevelopment()
	cfg.Logger = logger

	// La validation devrait passer
	err := cfg.ValidateForEnvironment()
	assert.NoError(t, err, "Valid production config should pass validation")
}

// TestGetCORSOrigins_EnvironmentDefaults teste les defaults selon l'environnement (P0-SECURITY)
func TestGetCORSOrigins_EnvironmentDefaults(t *testing.T) {
	tests := []struct {
		name     string
		env      string
		expected []string
	}{
		{
			name:     "development defaults",
			env:      "development",
			expected: []string{"http://localhost:3000", "http://127.0.0.1:3000", "http://localhost:5173", "http://127.0.0.1:5173"},
		},
		{
			name:     "staging defaults",
			env:      "staging",
			expected: []string{"http://localhost:3000", "http://127.0.0.1:3000", "http://localhost:5173", "http://127.0.0.1:5173"},
		},
		{
			name:     "production no defaults",
			env:      "production",
			expected: []string{},
		},
		{
			name:     "test no defaults",
			env:      "test",
			expected: []string{},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Sauvegarder CORS_ALLOWED_ORIGINS
			originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS")
			defer func() {
				if originalCORSOrigins != "" {
					os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins)
				} else {
					os.Unsetenv("CORS_ALLOWED_ORIGINS")
				}
			}()

			// S'assurer que CORS_ALLOWED_ORIGINS n'est pas défini
			os.Unsetenv("CORS_ALLOWED_ORIGINS")

			origins := getCORSOrigins(tt.env)
			assert.Equal(t, tt.expected, origins, "CORS origins should match expected defaults for %s", tt.env)
		})
	}
}

// TestGetCORSOrigins_ExplicitValue teste que les valeurs explicites sont utilisées (P0-SECURITY)
func TestGetCORSOrigins_ExplicitValue(t *testing.T) {
	// Sauvegarder CORS_ALLOWED_ORIGINS
	originalCORSOrigins := os.Getenv("CORS_ALLOWED_ORIGINS")
	defer func() {
		if originalCORSOrigins != "" {
			os.Setenv("CORS_ALLOWED_ORIGINS", originalCORSOrigins)
		} else {
			os.Unsetenv("CORS_ALLOWED_ORIGINS")
		}
	}()

	// Définir explicitement CORS_ALLOWED_ORIGINS
	os.Setenv("CORS_ALLOWED_ORIGINS", "https://example.com,https://app.example.com")

	origins := getCORSOrigins("production")
	assert.Equal(t, []string{"https://example.com", "https://app.example.com"}, origins, "Should use explicit CORS_ALLOWED_ORIGINS value")
}
