package config

import (
	"flag"
	"github.com/pingcap/dbaas/cost-metering-service/billing_errors"
	"github.com/pingcap/dbaas/cost-metering-service/log"
	"log/slog"

	"github.com/fsnotify/fsnotify"
	slogzap "github.com/samber/slog-zap/v2"

	"github.com/spf13/viper"
	ov "github.com/tidbcloud/config-service/oneconfig/viper"
	"go.uber.org/zap"
)

var (
	configPath = flag.String("conf", "/etc/cost/", "cost system configuration file")
)

func LoadRemote() error {
	remote := "oneconfig-cost/config.yaml"
	log.Info("Read From Remote", zap.String("remote", remote))
	err := Get().AddRemoteProvider(ov.Provider, ov.Endpoint, remote)
	Get().SetConfigType("yaml")
	if err != nil {
		return billing_errors.NewSystemError(err)
	}

	err = Get().WatchRemoteConfig()
	if err != nil {
		return billing_errors.NewSystemError(err)
	}

	err = Get().WatchRemoteConfigOnChannel()
	if err != nil {
		return billing_errors.NewSystemError(err)
	}

	log.Info("Read From Remote all", zap.Any("AllSettings ", Get().AllSettings()))
	return nil
}

var viperInstance = viper.NewWithOptions(viper.WithLogger(slog.New(slogzap.Option{Level: slog.LevelInfo, Logger: log.L()}.NewZapHandler())))

func Get() *viper.Viper {
	return viperInstance
}

func Reset() {
	viperInstance = viper.NewWithOptions(viper.WithLogger(slog.New(slogzap.Option{Level: slog.LevelInfo, Logger: log.L()}.NewZapHandler())))
}

// Init init the viper
func Init() error {

	err := InitLocal()
	if err != nil {
		return err
	}

	err = LoadRemote()
	if err != nil {
		log.Warn("load remote config failed, just ignore it in persnonal project", zap.Error(err))
	}

	Get().OnConfigChange(func(e fsnotify.Event) {
		log.Info("Config file changed :", zap.String("path", e.Name))
	})

	return nil
}

func InitLocal() error {
	flag.Parse()

	SetDefault()

	Get().AddConfigPath(*configPath)
	Get().AutomaticEnv()
	err := Get().ReadInConfig()
	if err != nil {
		return billing_errors.NewSystemError(err)
	}

	Get().WatchConfig()
	return nil
}
