package config

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

	"github.com/sethvargo/go-envconfig"
)

type Cfg struct {
	FileSystem *WebdavConfig `env:", prefix=FILESYSTEM_"`
	Cache      *Valkey       `env:", prefix=CACHE_"`
	Image      *Image        `env:", prefix=IMAGE_"`
	Tracking   *Umami        `env:", prefix=TRACKING_"`
	Gallery    *Gallery      `env:", prefix=GALLERY_"`

	LogLevel slog.Level `env:"LOG_LEVEL, default=DEBUG"`
	LogJSON  bool       `env:"LOG_JSON"`
}

type WebdavConfig struct {
	URL      string `env:"URL"`
	User     string `env:"USERNAME"`
	Password string `env:"PASSWORD"`
}

type Valkey struct {
	ClientName string `env:"CLIENTNAME"`
	Username   string `env:"USERNAME"`
	Password   string `env:"PASSWORD"`

	RefreshTime time.Duration `env:"REFRESH_TIME"`
	LifeTime    time.Duration `env:"LIFE_TIME"`

	// InitAddress point to valkey nodes.
	// Valkey will connect to them one by one and issue a CLUSTER SLOT command to initialize the cluster client until success.
	// If len(InitAddress) == 1 and the address is not running in cluster mode, valkey will fall back to the single client mode.
	// If ClientOption.Sentinel.MasterSet is set, then InitAddress will be used to connect sentinels
	// You can bypass this behavior by using ClientOption.ForceSingleClient.
	InitAddress []string `env:"ADDRESS"`
}

type Image struct {
	Concurency    int64         `env:"CONCURENCY"`
	Quality       int           `env:"QUALITY"`
	CacheLifetime time.Duration `env:"CACHE_LIFETIME"`
}

type Gallery struct {
	Path string `env:"PATH"`
}

type Umami struct {
	ScriptSrc string `env:"SCRIPT_SRC"`
	WebsiteID string `env:"WEBSITE_ID"`
}

func Read(ctx context.Context) (cfg Cfg, err error) {
	cfg = Default()
	err = envconfig.ProcessWith(ctx, &envconfig.Config{
		Target: &cfg,

		// All fields will use a ";" delimiter and "@" separator, unless locally
		// overridden.
		DefaultDelimiter: ";",
		DefaultSeparator: "@",
		DefaultOverwrite: true,

		Lookuper: envconfig.MultiLookuper(secretLookuper(), envconfig.OsLookuper()),
	})
	if err != nil {
		return
	}

	slog.Info("rft", "rft", cfg.Cache.RefreshTime)

	return
}
