package config

import (
	"fmt"
	"log/slog"
	"os"

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

type EntryConfig struct {
	NostrRelays   []string `env:"NOSTR_RELAYS" envSeparator:";"`
	PublicAddress string   `env:"PUBLIC_ADDRESS"`
}

type ExitConfig struct {
	NostrRelays     []string `env:"NOSTR_RELAYS" envSeparator:";"`
	NostrPrivateKey string   `env:"NOSTR_PRIVATE_KEY"`
	BackendHost     string   `env:"BACKEND_HOST"`
	BackendScheme   string   `env:"BACKEND_SCHEME"`
	HttpsPort       int32
	HttpsTarget     string
	Public          bool `env:"PUBLIC"`
}

var DefaultRelays = []string{
	"wss://relay.8333.space",
}

// load the and marshal Configuration from .env file from the UserHomeDir
// if this file was not found, fallback to the os environment variables
func LoadConfig[T any]() (*T, error) {
	// load current users home directory as a string
	homeDir, err := os.UserHomeDir()
	if err != nil {
		slog.Error("error loading home directory", err)
	}
	// check if .env file exist in the home directory
	// if it does, load the configuration from it
	// else fallback to the os environment variables
	if _, err := os.Stat(homeDir + "/.env"); err == nil {
		// load configuration from .env file
		return loadFromEnv[T](homeDir + "/.env")
	} else if _, err := os.Stat(".env"); err == nil {
		// load configuration from .env file in current directory
		return loadFromEnv[T]("")
	} else {
		// load configuration from os environment variables
		return loadFromEnv[T]("")
	}
}

// loadFromEnv loads the configuration from the specified .env file path.
// If the path is empty, it does not load any configuration.
// It returns an error if there was a problem loading the configuration.
func loadFromEnv[T any](path string) (*T, error) {
	// check path

	// load configuration from .env file
	err := godotenv.Load()
	if err != nil {
		cfg, err := env.ParseAs[T]()
		if err != nil {
			fmt.Printf("%+v\n", err)
		}
		return &cfg, nil
	}

	// or you can use generics
	cfg, err := env.ParseAs[T]()
	if err != nil {
		fmt.Printf("%+v\n", err)
	}
	return &cfg, nil
}
