package main

import (
	"fmt"
	"log"
	"strings"

	"github.com/spf13/viper"
)

type Config struct {
	Server   ServerConfig   `mapstructure:"server"`
	Database DatabaseConfig `mapstructure:"database"`
}

type ServerConfig struct {
	Host string `mapstructure:"host"`
	Port int    `mapstructure:"port"`
}

type DatabaseConfig struct {
	Driver string `mapstructure:"driver"`
	DSN    string `mapstructure:"dsn"`
}

func main() {
	// Set default values
	viper.SetDefault("server.host", "localhost")
	viper.SetDefault("server.port", 8080)
	viper.SetDefault("database.driver", "postgres")

	// Configure file lookup
	viper.SetConfigName("config")       // config.yaml, config.json, etc.
	viper.SetConfigType("yaml")         // file format
	viper.AddConfigPath(".")            // look in current directory
	viper.AddConfigPath("$HOME/.myapp") // look in home directory

	// Enable environment variable overrides
	viper.SetEnvPrefix("MYAPP")                            // e.g., MYAPP_SERVER_PORT
	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) // server.port -> SERVER_PORT
	viper.AutomaticEnv()

	// Try to read config file (optional)
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			fmt.Println("No config file found, using defaults and env vars")
		} else {
			log.Fatalf("Error reading config: %v", err)
		}
	} else {
		fmt.Printf("Using config file: %s\n", viper.ConfigFileUsed())
	}

	// Access configuration values
	fmt.Printf("\nServer Host: %s\n", viper.GetString("server.host"))
	fmt.Printf("Server Port: %d\n", viper.GetInt("server.port"))
	fmt.Printf("DB Driver: %s\n", viper.GetString("database.driver"))

	// Unmarshal into struct
	var config Config
	if err := viper.Unmarshal(&config); err != nil {
		log.Fatalf("Unable to decode config: %v", err)
	}
	fmt.Printf("\nConfig struct: %+v\n", config)
}
