package config

import (
	"errors"
	"flag"
	"os"

	"github.com/spf13/viper"
)

// SetUpTestConfig sets up the config for testing, with the help of viper library.
// One can set the config value by setting the environment variable or writing a config file.
//
// # How to pass Config File?
//
//	$ go test -args -config-name=config.yaml -config-path=.
//
// # How to use Environment Variable?
//
//	The environment variable takes precedence over the config file.
//	Environment variable format: envPrefix + "_" + the key name in ALL CAPS.
//
// # How to access config values?
//
//	First, call this function in the `TestMain(m *testing.M)` function, or any other `TestXXX(t *testing.T)` function.
//	Then, one can access the config value by viper.GetString("key_name").
//	Please refer to [Getting Values From Viper](https://github.com/spf13/viper#getting-values-from-viper).
func SetUpTestConfig(envPrefix string) {
	viper.SetEnvPrefix(envPrefix)
	viper.AutomaticEnv() // will check for an environment variable any time a viper.Get request is made

	// Read config from file
	viper.SetConfigType("yaml")

	configName := flag.String("config-name", "config.yaml", "test config file name")
	configPath := flag.String("config-path", ".", "test config file path")

	if !flag.Parsed() {
		if err := flag.CommandLine.Parse(os.Args[1:]); err != nil {
			panic(err)
		}
	}

	viper.SetConfigName(*configName)
	viper.AddConfigPath(*configPath)

	if err := viper.ReadInConfig(); err != nil {
		var configFileNotFoundError viper.ConfigFileNotFoundError
		if !errors.As(err, &configFileNotFoundError) {
			// If the error is not due to a missing config file, it's considered fatal.
			panic(err)
		}
		// Note: Config file not found is allowed. One can pass config values by environment variable.
	}
}
