package config

import (
	"strings"
	"testing"
)

// TestValidateProduction_AllValid tests that a fully configured production setup passes validation
func TestValidateProduction_AllValid(t *testing.T) {
	cfg := &Config{
		App: AppConfig{
			Environment: "production",
		},
		JWT: JWTConfig{
			Secret: "this-is-a-very-secure-secret-key-with-more-than-32-characters",
		},
		Database: DatabaseConfig{
			Hosts:    []string{"cassandra1.prod.example.com:9042"},
			Keyspace: "maplefile_prod",
			Username: "admin",
			Password: "secure_password_123",
		},
		S3: S3Config{
			AccessKey:  "AKIAIOSFODNN7EXAMPLE",
			SecretKey:  "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
			BucketName: "maplefile-production",
			Endpoint:   "https://s3.amazonaws.com",
		},
		Mailgun: MailgunConfig{
			APIKey:      "key-1234567890abcdef1234567890abcdef",
			Domain:      "mg.example.com",
			SenderEmail: "noreply@example.com",
		},
		Cache: CacheConfig{
			Host: "redis.prod.example.com",
		},
		Security: SecurityConfig{
			AllowedOrigins: []string{"https://app.example.com"},
		},
	}

	err := cfg.ValidateProduction()
	if err != nil {
		t.Errorf("Expected valid production config to pass validation, got error: %v", err)
	}
}

// TestValidateProduction_MissingJWTSecret tests JWT secret validation
func TestValidateProduction_MissingJWTSecret(t *testing.T) {
	cfg := &Config{
		App: AppConfig{
			Environment: "production",
		},
		JWT: JWTConfig{
			Secret: "", // Missing
		},
		Database: DatabaseConfig{
			Hosts:    []string{"localhost:9042"},
			Keyspace: "test",
		},
		S3: S3Config{
			AccessKey:  "test",
			SecretKey:  "test",
			BucketName: "test",
			Endpoint:   "http://localhost:9000",
		},
		Mailgun: MailgunConfig{
			APIKey:      "test",
			Domain:      "test.com",
			SenderEmail: "test@test.com",
		},
		Cache: CacheConfig{
			Host: "localhost",
		},
	}

	err := cfg.ValidateProduction()
	if err == nil {
		t.Error("Expected error for missing JWT_SECRET in production")
	}
	if !strings.Contains(err.Error(), "JWT_SECRET is required") {
		t.Errorf("Expected JWT_SECRET error, got: %v", err)
	}
}

// TestValidateProduction_ShortJWTSecret tests JWT secret length validation
func TestValidateProduction_ShortJWTSecret(t *testing.T) {
	cfg := &Config{
		App: AppConfig{
			Environment: "production",
		},
		JWT: JWTConfig{
			Secret: "short", // Too short (less than 32 chars)
		},
		Database: DatabaseConfig{
			Hosts:    []string{"localhost:9042"},
			Keyspace: "test",
		},
		S3: S3Config{
			AccessKey:  "test",
			SecretKey:  "test",
			BucketName: "test",
			Endpoint:   "http://localhost:9000",
		},
		Mailgun: MailgunConfig{
			APIKey:      "test",
			Domain:      "test.com",
			SenderEmail: "test@test.com",
		},
		Cache: CacheConfig{
			Host: "localhost",
		},
	}

	err := cfg.ValidateProduction()
	if err == nil {
		t.Error("Expected error for short JWT_SECRET in production")
	}
	if !strings.Contains(err.Error(), "at least 32 characters") {
		t.Errorf("Expected JWT_SECRET length error, got: %v", err)
	}
}

// TestValidateProduction_MissingS3Credentials tests S3 credential validation
func TestValidateProduction_MissingS3Credentials(t *testing.T) {
	tests := []struct {
		name      string
		accessKey string
		secretKey string
		wantError string
	}{
		{
			name:      "missing access key",
			accessKey: "",
			secretKey: "valid-secret",
			wantError: "S3_ACCESS_KEY is required",
		},
		{
			name:      "missing secret key",
			accessKey: "valid-access",
			secretKey: "",
			wantError: "S3_SECRET_KEY is required",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cfg := &Config{
				App: AppConfig{
					Environment: "production",
				},
				JWT: JWTConfig{
					Secret: "this-is-a-very-secure-secret-key-with-more-than-32-characters",
				},
				Database: DatabaseConfig{
					Hosts:    []string{"localhost:9042"},
					Keyspace: "test",
				},
				S3: S3Config{
					AccessKey:  tt.accessKey,
					SecretKey:  tt.secretKey,
					BucketName: "test",
					Endpoint:   "http://localhost:9000",
				},
				Mailgun: MailgunConfig{
					APIKey:      "test",
					Domain:      "test.com",
					SenderEmail: "test@test.com",
				},
				Cache: CacheConfig{
					Host: "localhost",
				},
			}

			err := cfg.ValidateProduction()
			if err == nil {
				t.Errorf("Expected error for %s in production", tt.name)
			}
			if !strings.Contains(err.Error(), tt.wantError) {
				t.Errorf("Expected error containing '%s', got: %v", tt.wantError, err)
			}
		})
	}
}

// TestValidateProduction_MissingMailgunCredentials tests email service validation
func TestValidateProduction_MissingMailgunCredentials(t *testing.T) {
	cfg := &Config{
		App: AppConfig{
			Environment: "production",
		},
		JWT: JWTConfig{
			Secret: "this-is-a-very-secure-secret-key-with-more-than-32-characters",
		},
		Database: DatabaseConfig{
			Hosts:    []string{"localhost:9042"},
			Keyspace: "test",
		},
		S3: S3Config{
			AccessKey:  "test",
			SecretKey:  "test",
			BucketName: "test",
			Endpoint:   "http://localhost:9000",
		},
		Mailgun: MailgunConfig{
			APIKey:      "", // Missing
			Domain:      "test.com",
			SenderEmail: "test@test.com",
		},
		Cache: CacheConfig{
			Host: "localhost",
		},
	}

	err := cfg.ValidateProduction()
	if err == nil {
		t.Error("Expected error for missing MAILGUN_API_KEY in production")
	}
	if !strings.Contains(err.Error(), "MAILGUN_API_KEY is required") {
		t.Errorf("Expected MAILGUN_API_KEY error, got: %v", err)
	}
}

// TestValidateProduction_MissingDatabaseConfig tests database configuration validation
func TestValidateProduction_MissingDatabaseConfig(t *testing.T) {
	cfg := &Config{
		App: AppConfig{
			Environment: "production",
		},
		JWT: JWTConfig{
			Secret: "this-is-a-very-secure-secret-key-with-more-than-32-characters",
		},
		Database: DatabaseConfig{
			Hosts:    []string{}, // Missing
			Keyspace: "",         // Missing
		},
		S3: S3Config{
			AccessKey:  "test",
			SecretKey:  "test",
			BucketName: "test",
			Endpoint:   "http://localhost:9000",
		},
		Mailgun: MailgunConfig{
			APIKey:      "test",
			Domain:      "test.com",
			SenderEmail: "test@test.com",
		},
		Cache: CacheConfig{
			Host: "localhost",
		},
	}

	err := cfg.ValidateProduction()
	if err == nil {
		t.Error("Expected error for missing database configuration in production")
	}
	if !strings.Contains(err.Error(), "DATABASE_HOSTS is required") {
		t.Errorf("Expected DATABASE_HOSTS error, got: %v", err)
	}
}

// TestValidateProduction_UnsafeOrigins tests CORS wildcard detection
func TestValidateProduction_UnsafeOrigins(t *testing.T) {
	cfg := &Config{
		App: AppConfig{
			Environment: "production",
		},
		JWT: JWTConfig{
			Secret: "this-is-a-very-secure-secret-key-with-more-than-32-characters",
		},
		Database: DatabaseConfig{
			Hosts:    []string{"localhost:9042"},
			Keyspace: "test",
		},
		S3: S3Config{
			AccessKey:  "test",
			SecretKey:  "test",
			BucketName: "test",
			Endpoint:   "http://localhost:9000",
		},
		Mailgun: MailgunConfig{
			APIKey:      "test",
			Domain:      "test.com",
			SenderEmail: "test@test.com",
		},
		Cache: CacheConfig{
			Host: "localhost",
		},
		Security: SecurityConfig{
			AllowedOrigins: []string{"*"}, // Unsafe wildcard
		},
	}

	err := cfg.ValidateProduction()
	if err == nil {
		t.Error("Expected error for wildcard CORS origin in production")
	}
	if !strings.Contains(err.Error(), "SECURITY_ALLOWED_ORIGINS='*'") {
		t.Errorf("Expected CORS wildcard warning, got: %v", err)
	}
}

// TestValidateProduction_MultipleErrors tests that all validation errors are collected
func TestValidateProduction_MultipleErrors(t *testing.T) {
	cfg := &Config{
		App: AppConfig{
			Environment: "production",
		},
		JWT: JWTConfig{
			Secret: "", // Missing
		},
		Database: DatabaseConfig{
			Hosts:    []string{}, // Missing
			Keyspace: "",         // Missing
		},
		S3: S3Config{
			AccessKey:  "", // Missing
			SecretKey:  "", // Missing
			BucketName: "",
			Endpoint:   "",
		},
		Mailgun: MailgunConfig{
			APIKey:      "", // Missing
			Domain:      "",
			SenderEmail: "",
		},
		Cache: CacheConfig{
			Host: "",
		},
	}

	err := cfg.ValidateProduction()
	if err == nil {
		t.Fatal("Expected multiple validation errors")
	}

	errorMsg := err.Error()
	expectedErrors := []string{
		"JWT_SECRET is required",
		"DATABASE_HOSTS is required",
		"DATABASE_KEYSPACE is required",
		"S3_ACCESS_KEY is required",
		"S3_SECRET_KEY is required",
		"S3_BUCKET is required",
		"S3_ENDPOINT is required",
		"MAILGUN_API_KEY is required",
		"MAILGUN_DOMAIN is required",
		"CACHE_HOST is required",
	}

	for _, expected := range expectedErrors {
		if !strings.Contains(errorMsg, expected) {
			t.Errorf("Expected error message to contain '%s', got: %v", expected, errorMsg)
		}
	}
}

// TestValidate_Development tests that development environments use basic validation
func TestValidate_Development(t *testing.T) {
	cfg := &Config{
		App: AppConfig{
			Environment: "development",
		},
		JWT: JWTConfig{
			Secret: "dev-secret", // Short secret OK in development
		},
		Database: DatabaseConfig{
			Hosts:    []string{"localhost:9042"},
			Keyspace: "maplefile_dev",
		},
		S3: S3Config{
			AccessKey:  "", // OK in development
			SecretKey:  "", // OK in development
			BucketName: "test",
		},
	}

	// Should not fail with lenient development validation
	err := cfg.Validate()
	if err != nil {
		t.Errorf("Development environment should not require strict validation, got: %v", err)
	}
}

// TestValidate_ProductionCallsValidateProduction tests integration
func TestValidate_ProductionCallsValidateProduction(t *testing.T) {
	cfg := &Config{
		App: AppConfig{
			Environment: "production",
		},
		JWT: JWTConfig{
			Secret: "", // This should trigger production validation
		},
	}

	err := cfg.Validate()
	if err == nil {
		t.Error("Expected production Validate() to call ValidateProduction() and fail")
	}
	if !strings.Contains(err.Error(), "JWT_SECRET is required") {
		t.Errorf("Expected ValidateProduction error, got: %v", err)
	}
}
