package logging

import (
	"testing"

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

func TestLogLevelConfiguration_DEBUG(t *testing.T) {
	logger, err := NewLogger("development", "debug")
	require.NoError(t, err)
	require.NotNil(t, logger)

	// Vérifier que le niveau est correct
	// En niveau DEBUG, tous les messages doivent être loggés
	logger.Debug("debug message", zap.String("key", "value"))
	logger.Info("info message", zap.Int("count", 42))
	logger.Warn("warn message", zap.Bool("flag", true))
	logger.Error("error message", zap.String("error", "test error"))

	// Sync peut échouer sur certains systèmes (stderr), c'est OK
	_ = logger.Sync()
}

func TestLogLevelConfiguration_INFO(t *testing.T) {
	logger, err := NewLogger("development", "info")
	require.NoError(t, err)
	require.NotNil(t, logger)

	// En niveau INFO, DEBUG ne devrait pas être loggé
	logger.Debug("debug message - should not appear")
	logger.Info("info message", zap.String("key", "value"))
	logger.Warn("warn message", zap.Int("count", 42))
	logger.Error("error message", zap.Bool("flag", true))

	_ = logger.Sync()
}

func TestLogLevelConfiguration_WARN(t *testing.T) {
	logger, err := NewLogger("development", "warn")
	require.NoError(t, err)
	require.NotNil(t, logger)

	// En niveau WARN, DEBUG et INFO ne devraient pas être loggés
	logger.Debug("debug message - should not appear")
	logger.Info("info message - should not appear")
	logger.Warn("warn message", zap.String("key", "value"))
	logger.Error("error message", zap.Int("count", 42))

	_ = logger.Sync()
}

func TestLogLevelConfiguration_ERROR(t *testing.T) {
	logger, err := NewLogger("development", "error")
	require.NoError(t, err)
	require.NotNil(t, logger)

	// En niveau ERROR, seul ERROR devrait être loggé
	logger.Debug("debug message - should not appear")
	logger.Info("info message - should not appear")
	logger.Warn("warn message - should not appear")
	logger.Error("error message", zap.String("error", "test error"))

	_ = logger.Sync()
}

func TestLogLevelConfiguration_Default(t *testing.T) {
	// Tester sans spécifier de niveau (devrait utiliser INFO par défaut)
	logger, err := NewLogger("development", "")
	require.NoError(t, err)
	require.NotNil(t, logger)

	logger.Info("info message")
	logger.Warn("warn message")
	logger.Error("error message")

	_ = logger.Sync()
}

func TestLogLevelConfiguration_InvalidLevel(t *testing.T) {
	// Tester avec un niveau invalide (devrait utiliser INFO par défaut)
	logger, err := NewLogger("development", "INVALID_LEVEL")
	require.NoError(t, err)
	require.NotNil(t, logger)

	logger.Info("info message")
	logger.Warn("warn message")
	logger.Error("error message")

	_ = logger.Sync()
}

func TestLogLevelConfiguration_CaseInsensitive(t *testing.T) {
	// Tester avec différents cas (debug, DEBUG, Debug)
	testCases := []string{"debug", "DEBUG", "Debug", "info", "INFO", "warn", "WARN", "error", "ERROR"}

	for _, level := range testCases {
		t.Run(level, func(t *testing.T) {
			logger, err := NewLogger("development", level)
			require.NoError(t, err)
			require.NotNil(t, logger)

			logger.Info("test message", zap.String("level", level))
			_ = logger.Sync()
		})
	}
}

func TestLogLevelConfiguration_Production(t *testing.T) {
	// Tester avec environnement production
	logger, err := NewLogger("production", "debug")
	require.NoError(t, err)
	require.NotNil(t, logger)

	logger.Debug("debug message")
	logger.Info("info message", zap.String("key", "value"))
	logger.Warn("warn message")
	logger.Error("error message")

	_ = logger.Sync()
}

func TestLogLevelConfiguration_WithRotation(t *testing.T) {
	// Tester NewLoggerWithRotation avec différents niveaux
	tmpDir := t.TempDir()
	logFile := tmpDir + "/test.log"

	levels := []string{"debug", "info", "warn", "error"}

	for _, level := range levels {
		t.Run(level, func(t *testing.T) {
			logger, err := NewLoggerWithRotation("development", logFile, level)
			require.NoError(t, err)
			require.NotNil(t, logger)

			logger.Info("test message", zap.String("level", level))
			_ = logger.Sync()
		})
	}
}

func TestLogLevelConfiguration_WithRotation_Default(t *testing.T) {
	tmpDir := t.TempDir()
	logFile := tmpDir + "/test.log"

	// Tester sans spécifier de niveau
	logger, err := NewLoggerWithRotation("development", logFile, "")
	require.NoError(t, err)
	require.NotNil(t, logger)

	logger.Info("test message")
	_ = logger.Sync()
}

func TestLogLevelConfiguration_WithRotation_InvalidLevel(t *testing.T) {
	tmpDir := t.TempDir()
	logFile := tmpDir + "/test.log"

	// Tester avec un niveau invalide
	logger, err := NewLoggerWithRotation("development", logFile, "INVALID")
	require.NoError(t, err)
	require.NotNil(t, logger)

	logger.Info("test message")
	_ = logger.Sync()
}

func TestLogLevelConfiguration_ZapLevel(t *testing.T) {
	// Vérifier que les niveaux zap sont correctement configurés
	testCases := []struct {
		levelStr      string
		expectedLevel zapcore.Level
	}{
		{"debug", zapcore.DebugLevel},
		{"DEBUG", zapcore.DebugLevel},
		{"info", zapcore.InfoLevel},
		{"INFO", zapcore.InfoLevel},
		{"warn", zapcore.WarnLevel},
		{"WARN", zapcore.WarnLevel},
		{"error", zapcore.ErrorLevel},
		{"ERROR", zapcore.ErrorLevel},
		{"", zapcore.InfoLevel},        // Par défaut
		{"invalid", zapcore.InfoLevel}, // Invalid -> INFO
	}

	for _, tc := range testCases {
		t.Run(tc.levelStr, func(t *testing.T) {
			logger, err := NewLogger("development", tc.levelStr)
			require.NoError(t, err)
			require.NotNil(t, logger)

			// Vérifier que le logger peut être utilisé
			logger.Info("test message")
			_ = logger.Sync()
		})
	}
}
