package config

import (
	"errors"
	"fmt"
	"strings"

	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/config"
	"github.com/spf13/viper"
)

const (
	Separator = "."

	// EnvSeparator is a section separator in ENV variables.
	EnvSeparator = "_"
)

var errProvideViperInOpts = errors.New("provide viper in opts")

func CreateViper(opts ...Option) (*viper.Viper, error) {
	o := defaultOpts()
	for i := range opts {
		opts[i](o)
	}

	var v *viper.Viper
	if o.v != nil {
		v = o.v
	} else {
		v = viper.New()
	}

	if o.envPrefix != "" {
		v.SetEnvPrefix(o.envPrefix)
		v.AutomaticEnv()
		v.SetEnvKeyReplacer(strings.NewReplacer(Separator, EnvSeparator))
	}

	if o.path != "" {
		v.SetConfigFile(o.path)

		err := v.ReadInConfig()
		if err != nil {
			return nil, fmt.Errorf("failed to read config: %w", err)
		}
	}

	if o.configDir != "" {
		if err := config.ReadConfigDir(v, o.configDir); err != nil {
			return nil, fmt.Errorf("failed to read config dir: %w", err)
		}
	}

	return v, nil
}

func ReloadViper(opts ...Option) error {
	o := defaultOpts()
	for i := range opts {
		opts[i](o)
	}

	if o.v == nil {
		return errProvideViperInOpts
	}

	if o.path != "" {
		err := o.v.ReadInConfig()
		if err != nil {
			return fmt.Errorf("rereading configuration file: %w", err)
		}
	}

	if o.configDir != "" {
		if err := config.ReadConfigDir(o.v, o.configDir); err != nil {
			return fmt.Errorf("rereading configuration dir: %w", err)
		}
	}

	return nil
}