// Package config provides configuration management for hdmistat
package config

import (
	"context"
	"log/slog"
	"os"
	"time"

	"git.eeqj.de/sneak/smartconfig"
)

const (
	defaultWidth  = 1920
	defaultHeight = 1080
)

// Config holds the application configuration
type Config struct {
	FramebufferDevice string
	RotationInterval  string
	UpdateInterval    string
	Screens           []string
	LogLevel          string
	Width             int
	Height            int

	// Parsed durations (not from config)
	rotationDuration time.Duration
	updateDuration   time.Duration
}

// Load loads configuration from all available sources
func Load(_ context.Context) (*Config, error) {
	// Start with defaults
	cfg := &Config{
		FramebufferDevice: "/dev/fb0",
		RotationInterval:  "10s",
		UpdateInterval:    "1s",
		Screens:           []string{"overview", "top_cpu", "top_memory"},
		LogLevel:          "info",
		Width:             defaultWidth,
		Height:            defaultHeight,
	}

	// Try to load from the default location for hdmistat
	sc, err := smartconfig.NewFromAppName("hdmistat")
	if err == nil {
		// Override defaults with config file values if they exist
		if val, err := sc.GetString("framebuffer_device"); err == nil && val != "" {
			cfg.FramebufferDevice = val
		}

		if val, err := sc.GetString("rotation_interval"); err == nil && val != "" {
			cfg.RotationInterval = val
		}

		if val, err := sc.GetString("update_interval"); err == nil && val != "" {
			cfg.UpdateInterval = val
		}

		if val, err := sc.GetString("log_level"); err == nil && val != "" {
			cfg.LogLevel = val
		}

		if val, err := sc.GetInt("width"); err == nil && val > 0 {
			cfg.Width = val
		}

		if val, err := sc.GetInt("height"); err == nil && val > 0 {
			cfg.Height = val
		}

		// Load screens array
		if screensRaw, exists := sc.Get("screens"); exists {
			if screens, ok := screensRaw.([]interface{}); ok && len(screens) > 0 {
				cfg.Screens = make([]string, 0, len(screens))
				for _, s := range screens {
					if str, ok := s.(string); ok {
						cfg.Screens = append(cfg.Screens, str)
					}
				}
			}
		}
	}

	// Override with environment variables if set
	if envLogLevel := os.Getenv("HDMISTAT_LOG_LEVEL"); envLogLevel != "" {
		cfg.LogLevel = envLogLevel
	}

	// Parse durations
	cfg.rotationDuration, err = time.ParseDuration(cfg.RotationInterval)
	if err != nil {
		return nil, err
	}

	cfg.updateDuration, err = time.ParseDuration(cfg.UpdateInterval)
	if err != nil {
		return nil, err
	}

	return cfg, nil
}

// GetRotationDuration returns the parsed rotation interval
func (c *Config) GetRotationDuration() time.Duration {
	return c.rotationDuration
}

// GetUpdateDuration returns the parsed update interval
func (c *Config) GetUpdateDuration() time.Duration {
	return c.updateDuration
}

// GetLogLevel returns the slog level
func (c *Config) GetLogLevel() slog.Level {
	switch c.LogLevel {
	case "debug":
		return slog.LevelDebug
	case "info":
		return slog.LevelInfo
	case "warn":
		return slog.LevelWarn
	case "error":
		return slog.LevelError
	default:
		return slog.LevelInfo
	}
}
