package config

import (
	"strings"
	"testing"

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

func TestConfig_Validate(t *testing.T) {
	tests := []struct {
		name    string
		config  *Config
		wantErr bool
		errMsg  string
	}{
		{
			name: "valid config",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: false,
		},
		{
			name: "invalid port too low",
			config: &Config{
				AppPort:         0,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: true,
			errMsg:  "APP_PORT validation failed",
		},
		{
			name: "invalid port too high",
			config: &Config{
				AppPort:         99999,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: true,
			errMsg:  "APP_PORT validation failed",
		},
		{
			name: "JWT secret too short",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       "short",
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: true,
			errMsg:  "JWT_SECRET validation failed",
		},
		{
			name: "JWT secret empty",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       "",
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: true,
			errMsg:  "JWT_SECRET validation failed",
		},
		{
			name: "JWT secret exactly 32 characters",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: false,
		},
		{
			name: "DatabaseURL empty",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: true,
			errMsg:  "DATABASE_URL is required",
		},
		{
			name: "RedisURL empty",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: true,
			errMsg:  "REDIS_URL is required",
		},
		{
			name: "DatabaseURL invalid format",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "invalid://database",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: true,
			errMsg:  "DATABASE_URL validation failed",
		},
		{
			name: "RedisURL invalid format",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "invalid://redis",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: true,
			errMsg:  "REDIS_URL validation failed",
		},
		{
			name: "DatabaseURL postgres format",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgres://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: false,
		},
		{
			name: "DatabaseURL sqlite format",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "sqlite:///path/to/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: false,
		},
		{
			name: "RedisURL rediss format (TLS)",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "rediss://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: false,
		},
		{
			name: "valid port boundaries",
			config: &Config{
				AppPort:         1,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: false,
		},
		{
			name: "valid port upper boundary",
			config: &Config{
				AppPort:         65535,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: false,
		},
		{
			name: "invalid LogLevel",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				LogLevel:        "INVALID",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: true,
			errMsg:  "LOG_LEVEL validation failed",
		},
		{
			name: "valid LogLevel",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				LogLevel:        "DEBUG",
				RateLimitLimit:  100, // Added
				RateLimitWindow: 60,  // Added
			},
			wantErr: false,
		},
		{
			name: "invalid RateLimitLimit zero",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  0,
				RateLimitWindow: 60, // Added
			},
			wantErr: true,
			errMsg:  "RATE_LIMIT_LIMIT validation failed",
		},
		{
			name: "invalid RateLimitWindow negative",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100, // Added
				RateLimitWindow: -1,
			},
			wantErr: true,
			errMsg:  "RATE_LIMIT_WINDOW validation failed",
		},
		{
			name: "valid RateLimit values",
			config: &Config{
				AppPort:         8080,
				JWTSecret:       strings.Repeat("a", 32),
				DatabaseURL:     "postgresql://user:pass@localhost:5432/db",
				RedisURL:        "redis://localhost:6379",
				RateLimitLimit:  100,
				RateLimitWindow: 60,
			},
			wantErr: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Ajouter un logger minimal si nécessaire pour éviter nil pointer
			if tt.config.Logger == nil {
				logger, _ := zap.NewDevelopment()
				tt.config.Logger = logger
			}

			err := tt.config.Validate()
			if tt.wantErr {
				require.Error(t, err)
				if tt.errMsg != "" {
					assert.Contains(t, err.Error(), tt.errMsg)
				}
			} else {
				require.NoError(t, err)
			}
		})
	}
}
