package secret

import (
	"context"
	"fmt"
	"io"
	"log/slog"
	"os"
	"strings"
	"syscall"

	"golang.org/x/term"
)

var (
	debugEnabled bool
	debugLogger  *slog.Logger
)

func init() {
	initDebugLogging()
}

// initDebugLogging initializes the debug logging system based on GODEBUG environment variable
func initDebugLogging() {
	godebug := os.Getenv("GODEBUG")
	debugEnabled = strings.Contains(godebug, "berlin.sneak.pkg.secret")

	if !debugEnabled {
		// Create a no-op logger that discards all output
		debugLogger = slog.New(slog.NewTextHandler(io.Discard, nil))
		return
	}

	// Disable stderr buffering for immediate debug output when debugging is enabled
	_, _, _ = syscall.Syscall(syscall.SYS_FCNTL, os.Stderr.Fd(), syscall.F_SETFL, syscall.O_SYNC)

	// Check if STDERR is a TTY
	isTTY := term.IsTerminal(int(syscall.Stderr))

	var handler slog.Handler
	if isTTY {
		// TTY output: colorized structured format
		handler = newColorizedHandler(os.Stderr)
	} else {
		// Non-TTY output: JSON Lines format
		handler = slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
			Level: slog.LevelDebug,
		})
	}

	debugLogger = slog.New(handler)
}

// IsDebugEnabled returns true if debug logging is enabled
func IsDebugEnabled() bool {
	return debugEnabled
}

// Debug logs a debug message with optional attributes
func Debug(msg string, args ...any) {
	if !debugEnabled {
		return
	}
	debugLogger.Debug(msg, args...)
}

// DebugF logs a formatted debug message with optional attributes
func DebugF(format string, args ...any) {
	if !debugEnabled {
		return
	}
	debugLogger.Debug(fmt.Sprintf(format, args...))
}

// DebugWith logs a debug message with structured attributes
func DebugWith(msg string, attrs ...slog.Attr) {
	if !debugEnabled {
		return
	}
	debugLogger.LogAttrs(context.Background(), slog.LevelDebug, msg, attrs...)
}

// colorizedHandler implements a TTY-friendly structured log handler
type colorizedHandler struct {
	output io.Writer
}

func newColorizedHandler(output io.Writer) slog.Handler {
	return &colorizedHandler{output: output}
}

func (h *colorizedHandler) Enabled(_ context.Context, level slog.Level) bool {
	// Explicitly check that debug is enabled AND the level is DEBUG or higher
	// This ensures we don't default to INFO level when debug is enabled
	return debugEnabled && level >= slog.LevelDebug
}

func (h *colorizedHandler) Handle(_ context.Context, record slog.Record) error {
	if !debugEnabled {
		return nil
	}

	// Format: [DEBUG] message {key=value, key2=value2}
	output := fmt.Sprintf("\033[36m[DEBUG]\033[0m \033[1m%s\033[0m", record.Message)

	if record.NumAttrs() > 0 {
		output += " \033[33m{"
		first := true
		record.Attrs(func(attr slog.Attr) bool {
			if !first {
				output += ", "
			}
			first = false
			output += fmt.Sprintf("%s=%#v", attr.Key, attr.Value.Any())
			return true
		})
		output += "}\033[0m"
	}

	output += "\n"
	_, err := h.output.Write([]byte(output))
	return err
}

func (h *colorizedHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
	// For simplicity, return the same handler
	// In a more complex implementation, we'd create a new handler with the attrs
	return h
}

func (h *colorizedHandler) WithGroup(name string) slog.Handler {
	// For simplicity, return the same handler
	// In a more complex implementation, we'd create a new handler with the group
	return h
}
