package config

import (
	"flag"
	"fmt"
	"os"
	"time"

	"github.com/ilyakaznacheev/cleanenv"
)

type Config struct {
	Env              string `yaml:"env" env-required:"true"`
	HTTPServerConfig `yaml:"http-server"`
	Postgresql       struct {
		DBName   string `yaml:"db_name" env-required:"true"`
		User     string `yaml:"user" env-required:"true"`
		Password string `yaml:"password" env-required:"true"`
		Address  string `yaml:"address" env-required:"true"`
	} `yaml:"postgresql"`
	Redis struct {
		Password string `yaml:"password" env-required:"true"`
		Address  string `yaml:"address" env-required:"true"`
	} `yaml:"redis"`
	Minio struct {
		User     string `yaml:"user" env-required:"true"`
		Password string `yaml:"password" env-required:"true"`
		Address  string `yaml:"address" env-required:"true"`
	} `yaml:"minio"`
}

type HTTPServerConfig struct {
	Address     string        `yaml:"address" env-required:"true"`
	Timeout     time.Duration `yaml:"timeout" env-default:"4s"`
	IdleTimeout time.Duration `yaml:"idle_timeout" env-default:"60s"`
}

// MustLoad returns config or panic.
func MustLoad() *Config {
	configPath := fetchConfigPath()
	if configPath == "" {
		panic("CONFIG_PATH is not set")
	}
	// check if file exists
	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		panic(fmt.Sprintf("config file does not exist: %s", configPath))
	}

	var cfg Config
	// read config
	if err := cleanenv.ReadConfig(configPath, &cfg); err != nil {
		panic(fmt.Errorf("cannot read config: %w", err))
	}

	return &cfg
}

// fetchConfigPath returns config path from env or flag.
func fetchConfigPath() string {
	var res string = os.Getenv("CONFIG_PATH")

	if res == "" {
		flag.StringVar(&res, "config", "", "path to config file")
		flag.Parse()
	}

	return res
}