package config

import (
	"os"
	"strings"
	"time"

	"github.com/adrg/xdg"
	"github.com/spf13/viper"
)

type Config struct {
	Env        string        `mapstructure:"env"`
	BinaryPath string        `mapstructure:"binaryPath"`
	HTTP       ConfigHTTP    `mapstructure:"http"`
	Cache      ConfigCache   `mapstructure:"cache"`
	Cookies    ConfigCookies `mapstructure:"cookies"`
}

func (c *Config) IsProduction() bool {
	return c.Env == "Production"
}

func (c *Config) IsDevelopment() bool {
	return c.Env == "Development"
}

func (c *Config) IsStaging() bool {
	return c.Env == "Staging"
}

type ConfigHTTP struct {
	Port           int      `mapstructure:"port"`
	Listen         string   `mapstructure:"listen"`
	BasePath       string   `mapstructure:"basePath"`
	TrustedProxies []string `mapstructure:"trustedProxies"`
}

type ConfigCache struct {
	TTL     time.Duration `mapstructure:"ttl"`
	DirPath string        `mapstructure:"dirPath"`
}

type ConfigCookies struct {
	Enabled     bool                     `mapstructure:"enabled"`
	FilePath    string                   `mapstructure:"filePath"`
	FromBrowser ConfigCookiesFromBrowser `mapstructure:"fromBrowser"`
}

type ConfigCookiesFromBrowser struct {
	Browser   string `mapstructure:"browser"`
	Keyring   string `mapstructure:"keyring"`
	Profile   string `mapstructure:"profile"`
	Container string `mapstructure:"container"`
}

func DefaultConfig() *Config {
	return &Config{
		Env:        "Production",
		BinaryPath: "yt-dlp",
		HTTP: ConfigHTTP{
			Port:     8080,
			Listen:   "127.0.0.1",
			BasePath: "/",
		},
		Cache: ConfigCache{
			TTL:     time.Hour,
			DirPath: "/tmp/ytdl-web",
		},
		Cookies: ConfigCookies{
			Enabled:     false,
			FilePath:    "./cookies.txt",
			FromBrowser: ConfigCookiesFromBrowser{},
		},
	}
}

func LoadConfig(paths ...string) (*Config, error) {
	v := viper.New()

	v.SetEnvPrefix("YTDL")
	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
	v.AutomaticEnv()

	v.SetConfigName("config")
	v.SetConfigType("yaml")

	if len(paths) > 0 {
		for _, path := range paths {
			v.AddConfigPath(path)
		}
	} else {
		envDir := os.Getenv("YTDL_CONFIGDIR")
		if envDir != "" {
			v.AddConfigPath(envDir)
		}

		v.AddConfigPath(".")

		homeDir, err := os.UserHomeDir()
		if err == nil {
			v.AddConfigPath(homeDir + "/.config/ytdl-web")
		}

		v.AddConfigPath(xdg.ConfigHome + "/ytdl-web")
		for _, dir := range xdg.ConfigDirs {
			v.AddConfigPath(dir + "/ytdl-web")
		}
	}

	if err := v.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
			return nil, err
		}
	}

	config := DefaultConfig()
	if err := v.Unmarshal(config); err != nil {
		return nil, err
	}

	return config, nil
}
