package logging

import (
	"strings"

	"github.com/orchard9/rdev/internal/envutil"
)

// Config holds logging configuration.
type Config struct {
	// Level is the default log level.
	Level Level

	// Format is the output format (json or text).
	Format Format

	// ComponentLevels overrides log levels per component.
	// Example: {"handlers": LevelDebug, "worker": LevelWarn}
	ComponentLevels map[string]Level

	// RedactEnabled enables automatic redaction of sensitive data.
	RedactEnabled bool

	// AddSource adds source file/line to log entries (performance impact).
	AddSource bool
}

// DefaultConfig returns sensible defaults for production.
func DefaultConfig() Config {
	return Config{
		Level:           LevelInfo,
		Format:          FormatJSON,
		ComponentLevels: make(map[string]Level),
		RedactEnabled:   true,
		AddSource:       false,
	}
}

// ConfigFromEnv creates a Config from environment variables.
//
// Environment variables:
//   - LOG_LEVEL: default level (debug, info, warn, error)
//   - LOG_FORMAT: output format (json, text)
//   - LOG_LEVELS: per-component levels (handlers:debug,worker:warn)
//   - LOG_REDACT: enable/disable sensitive data redaction (true/false)
//   - LOG_SOURCE: add source file/line to logs (true/false)
func ConfigFromEnv() Config {
	cfg := DefaultConfig()

	cfg.Level = ParseLevel(envutil.GetEnv("LOG_LEVEL", "info"))
	cfg.Format = ParseFormat(envutil.GetEnv("LOG_FORMAT", "json"))
	cfg.RedactEnabled = envutil.GetEnvBool("LOG_REDACT", true)
	cfg.AddSource = envutil.GetEnvBool("LOG_SOURCE", false)

	// Parse per-component log levels: "handlers:debug,worker:warn"
	if levels := envutil.GetEnv("LOG_LEVELS", ""); levels != "" {
		cfg.ComponentLevels = parseComponentLevels(levels)
	}

	return cfg
}

// parseComponentLevels parses a comma-separated list of component:level pairs.
func parseComponentLevels(s string) map[string]Level {
	result := make(map[string]Level)
	for pair := range strings.SplitSeq(s, ",") {
		pair = strings.TrimSpace(pair)
		if pair == "" {
			continue
		}
		parts := strings.SplitN(pair, ":", 2)
		if len(parts) != 2 {
			continue
		}
		component := strings.TrimSpace(parts[0])
		level := ParseLevel(parts[1])
		if component != "" {
			result[component] = level
		}
	}
	return result
}

// LevelFor returns the log level for a component, falling back to the default.
func (c Config) LevelFor(component string) Level {
	if level, ok := c.ComponentLevels[component]; ok {
		return level
	}
	return c.Level
}
