package secret

import (
	"bytes"
	"log/slog"
	"os"
	"strings"
	"syscall"
	"testing"

	"golang.org/x/term"
)

func TestDebugLogging(t *testing.T) {
	// Save original GODEBUG and restore it
	originalGodebug := os.Getenv("GODEBUG")
	defer func() {
		if originalGodebug == "" {
			os.Unsetenv("GODEBUG")
		} else {
			os.Setenv("GODEBUG", originalGodebug)
		}
		// Re-initialize debug system with original setting
		initDebugLogging()
	}()

	tests := []struct {
		name          string
		godebug       string
		expectEnabled bool
	}{
		{
			name:          "debug enabled",
			godebug:       "berlin.sneak.pkg.secret",
			expectEnabled: true,
		},
		{
			name:          "debug enabled with other flags",
			godebug:       "other=1,berlin.sneak.pkg.secret,another=value",
			expectEnabled: true,
		},
		{
			name:          "debug disabled",
			godebug:       "other=1",
			expectEnabled: false,
		},
		{
			name:          "debug disabled empty",
			godebug:       "",
			expectEnabled: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Set GODEBUG
			if tt.godebug == "" {
				os.Unsetenv("GODEBUG")
			} else {
				os.Setenv("GODEBUG", tt.godebug)
			}

			// Re-initialize debug system
			initDebugLogging()

			// Test if debug is enabled
			enabled := IsDebugEnabled()
			if enabled != tt.expectEnabled {
				t.Errorf("IsDebugEnabled() = %v, want %v", enabled, tt.expectEnabled)
			}

			// If debug should be enabled, test that debug output works
			if tt.expectEnabled {
				// Capture debug output by redirecting the colorized handler
				var buf bytes.Buffer

				// Override the debug logger for testing
				oldLogger := debugLogger
				if term.IsTerminal(int(syscall.Stderr)) {
					// TTY: use colorized handler with our buffer
					debugLogger = slog.New(newColorizedHandler(&buf))
				} else {
					// Non-TTY: use JSON handler with our buffer
					debugLogger = slog.New(slog.NewJSONHandler(&buf, &slog.HandlerOptions{
						Level: slog.LevelDebug,
					}))
				}

				// Test debug output
				Debug("test message", "key", "value")

				// Restore original logger
				debugLogger = oldLogger

				// Check that output was generated
				output := buf.String()
				if !strings.Contains(output, "test message") {
					t.Errorf("Debug output does not contain expected message. Got: %s", output)
				}
			}
		})
	}
}

func TestDebugFunctions(t *testing.T) {
	// Enable debug for testing
	originalGodebug := os.Getenv("GODEBUG")
	os.Setenv("GODEBUG", "berlin.sneak.pkg.secret")
	defer func() {
		if originalGodebug == "" {
			os.Unsetenv("GODEBUG")
		} else {
			os.Setenv("GODEBUG", originalGodebug)
		}
		initDebugLogging()
	}()

	initDebugLogging()

	if !IsDebugEnabled() {
		t.Log("Debug not enabled, but continuing with debug function tests anyway")
	}

	// Test that debug functions don't panic and can be called
	t.Run("Debug", func(t *testing.T) {
		Debug("test debug message")
		Debug("test with args", "key", "value", "number", 42)
	})

	t.Run("DebugF", func(t *testing.T) {
		DebugF("formatted message: %s %d", "test", 123)
	})

	t.Run("DebugWith", func(t *testing.T) {
		DebugWith("structured message",
			slog.String("string_key", "string_value"),
			slog.Int("int_key", 42),
			slog.Bool("bool_key", true),
		)
	})
}
