package config

import (
	"os"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.uber.org/zap"
	"veza-backend-api/internal/middleware"
)

func TestConfigReloader_ReloadLogLevel(t *testing.T) {
	// Créer un logger de test
	logger := zap.NewNop()

	// Créer une config minimale
	config := &Config{
		LogLevel: "INFO",
		Logger:   logger,
	}

	reloader := NewConfigReloader(config, logger)

	// Test avec niveau DEBUG
	os.Setenv("LOG_LEVEL", "DEBUG")
	defer os.Unsetenv("LOG_LEVEL")

	err := reloader.ReloadLogLevel()
	require.NoError(t, err)
	assert.Equal(t, "DEBUG", config.LogLevel)

	// Test avec niveau ERROR
	os.Setenv("LOG_LEVEL", "ERROR")
	err = reloader.ReloadLogLevel()
	require.NoError(t, err)
	assert.Equal(t, "ERROR", config.LogLevel)
}

func TestConfigReloader_ReloadRateLimits(t *testing.T) {
	// Créer un logger de test
	logger := zap.NewNop()

	// Créer un simple rate limiter de test
	rateLimiter := middleware.NewSimpleRateLimiter(100, 60*time.Second)
	defer rateLimiter.Stop() // Stop the rate limiter's cleanup goroutine

	// Créer une config minimale
	config := &Config{
		RateLimitLimit:    100,
		RateLimitWindow:   60,
		Logger:            logger,
		SimpleRateLimiter: rateLimiter,
	}

	reloader := NewConfigReloader(config, logger)

	// Test avec nouvelles limites
	os.Setenv("RATE_LIMIT_LIMIT", "200")
	os.Setenv("RATE_LIMIT_WINDOW", "120")
	defer func() {
		os.Unsetenv("RATE_LIMIT_LIMIT")
		os.Unsetenv("RATE_LIMIT_WINDOW")
	}()

	err := reloader.ReloadRateLimits()
	require.NoError(t, err)
	assert.Equal(t, 200, config.RateLimitLimit)
	assert.Equal(t, 120, config.RateLimitWindow)
}

func TestConfigReloader_ReloadAll(t *testing.T) {
	logger := zap.NewNop()

	// Create a simple rate limiter for test
	rateLimiter := middleware.NewSimpleRateLimiter(100, 60*time.Second)
	defer rateLimiter.Stop() // Stop the rate limiter's cleanup goroutine

	config := &Config{
		LogLevel:          "INFO",
		RateLimitLimit:    100,
		RateLimitWindow:   60,
		Logger:            logger,
		SimpleRateLimiter: rateLimiter,
	}

	reloader := NewConfigReloader(config, logger)

	// Définir de nouvelles valeurs
	os.Setenv("LOG_LEVEL", "WARN")
	os.Setenv("RATE_LIMIT_LIMIT", "150")
	os.Setenv("RATE_LIMIT_WINDOW", "90")
	defer func() {
		os.Unsetenv("LOG_LEVEL")
		os.Unsetenv("RATE_LIMIT_LIMIT")
		os.Unsetenv("RATE_LIMIT_WINDOW")
	}()

	err := reloader.ReloadAll()
	require.NoError(t, err)
	assert.Equal(t, "WARN", config.LogLevel)
	assert.Equal(t, 150, config.RateLimitLimit)
	assert.Equal(t, 90, config.RateLimitWindow)
}

func TestConfigReloader_GetCurrentConfig(t *testing.T) {
	logger := zap.NewNop()

	config := &Config{
		LogLevel:        "INFO",
		RateLimitLimit:  100,
		RateLimitWindow: 60,
		Logger:          logger,
	}

	reloader := NewConfigReloader(config, logger)

	currentConfig := reloader.GetCurrentConfig()
	require.NotNil(t, currentConfig)
	assert.Equal(t, "INFO", currentConfig.LogLevel)
	assert.Equal(t, 100, currentConfig.RateLimitLimit)
	assert.Equal(t, 60, currentConfig.RateLimitWindow)
}

func TestNewConfigReloader(t *testing.T) {
	logger := zap.NewNop()

	config := &Config{
		Logger: logger,
	}

	reloader := NewConfigReloader(config, logger)
	require.NotNil(t, reloader)
	assert.Equal(t, config, reloader.config)
	assert.Equal(t, logger, reloader.logger)
}
