package main

import (
	"fmt"
	"log"
	"time"

	"github.com/caarlos0/env/v11"
)

// Config holds all configuration from environment variables
type Config struct {
	// Basic types with defaults
	Host    string `env:"HOST" envDefault:"localhost"`
	Port    int    `env:"PORT" envDefault:"8080"`
	Debug   bool   `env:"DEBUG" envDefault:"false"`
	Timeout int    `env:"TIMEOUT" envDefault:"30"`

	// Required field (will error if not set)
	DatabaseURL string `env:"DATABASE_URL,required"`

	// Expand environment variables in value
	LogPath string `env:"LOG_PATH" envDefault:"${HOME}/logs" envExpand:"true"`

	// Slice from comma-separated values
	AllowedHosts []string `env:"ALLOWED_HOSTS" envSeparator:","`

	// Duration parsing
	RequestTimeout time.Duration `env:"REQUEST_TIMEOUT" envDefault:"5s"`

	// Nested structs
	Database DatabaseConfig
	Redis    RedisConfig `envPrefix:"REDIS_"`
}

type DatabaseConfig struct {
	Host     string `env:"DB_HOST" envDefault:"localhost"`
	Port     int    `env:"DB_PORT" envDefault:"5432"`
	User     string `env:"DB_USER" envDefault:"postgres"`
	Password string `env:"DB_PASSWORD"`
	Name     string `env:"DB_NAME" envDefault:"app"`
	SSLMode  string `env:"DB_SSLMODE" envDefault:"disable"`
}

type RedisConfig struct {
	Host     string `env:"HOST" envDefault:"localhost"` // becomes REDIS_HOST
	Port     int    `env:"PORT" envDefault:"6379"`      // becomes REDIS_PORT
	Password string `env:"PASSWORD"`                     // becomes REDIS_PASSWORD
	DB       int    `env:"DB" envDefault:"0"`           // becomes REDIS_DB
}

func main() {
	// Parse environment variables into struct
	cfg := Config{}
	if err := env.Parse(&cfg); err != nil {
		log.Fatalf("Failed to parse config: %v", err)
	}

	fmt.Printf("Server: %s:%d\n", cfg.Host, cfg.Port)
	fmt.Printf("Debug: %v\n", cfg.Debug)
	fmt.Printf("Database: %s@%s:%d/%s\n",
		cfg.Database.User, cfg.Database.Host,
		cfg.Database.Port, cfg.Database.Name)
	fmt.Printf("Redis: %s:%d\n", cfg.Redis.Host, cfg.Redis.Port)
	fmt.Printf("Request Timeout: %v\n", cfg.RequestTimeout)
	fmt.Printf("Allowed Hosts: %v\n", cfg.AllowedHosts)
	fmt.Printf("Log Path: %s\n", cfg.LogPath)
}

// Example usage:
//
// export DATABASE_URL="postgres://user:pass@localhost/db"
// export PORT=3000
// export DEBUG=true
// export ALLOWED_HOSTS="localhost,example.com,api.example.com"
// export REQUEST_TIMEOUT="10s"
// export REDIS_HOST="redis.example.com"
// export REDIS_PASSWORD="secret"
// go run main.go

// Custom types can implement env.UnmarshalText:
//
// type LogLevel string
//
// func (l *LogLevel) UnmarshalText(text []byte) error {
//     switch strings.ToLower(string(text)) {
//     case "debug", "info", "warn", "error":
//         *l = LogLevel(strings.ToLower(string(text)))
//         return nil
//     default:
//         return fmt.Errorf("invalid log level: %s", text)
//     }
// }
