package config

import (
	"fmt"
	"github.com/coroot/coroot-node-agent/utils"
	"strings"
	"sync"

	klog "github.com/sirupsen/logrus"
	"github.com/spf13/viper"

	"github.com/coroot/coroot-node-agent/flags"
)

var (
	configOnce          sync.Once
	configInstance      *viper.Viper // 运行时配置（用于读取）
	configMutex         sync.RWMutex
	cmdLineFlagsSet     map[string]bool // 记录通过命令行参数设置的配置项
	cmdLineFlagsSetOnce sync.Once
)

// InitConfig 初始化 Viper 配置
func InitConfig(configPath string) error {
	var err error
	configOnce.Do(func() {
		v := viper.New()

		// 设置配置文件路径
		if configPath != "" {
			v.SetConfigFile(configPath)
		} else {
			v.SetConfigFile(utils.GetDefaultConfigPath())
		}

		// 设置环境变量前缀和键替换规则
		v.SetEnvPrefix("EUSPACE")
		// 设置环境变量键替换规则：将点号替换为下划线
		v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
		v.AutomaticEnv()

		// 读取配置文件
		// 注意：配置文件读取失败（不存在、格式错误、权限问题等）都不是致命错误
		// 程序会继续启动，使用默认值、命令行参数和环境变量
		if err = v.ReadInConfig(); err != nil {
			// 所有配置文件读取错误都视为非致命错误，只记录警告
			if _, ok := err.(viper.ConfigFileNotFoundError); ok {
				klog.Warnf("⚠️  [CONFIG] Config file not found, using defaults: %v", err)
			} else {
				klog.Warnf("⚠️  [CONFIG] Error reading config file (will use defaults): %v", err)
			}
			err = nil // 不返回错误，允许程序继续启动
		} else {
			actualConfigFile := v.ConfigFileUsed()
			klog.Infof("✓ [CONFIG] Using config file: %s", actualConfigFile)
			// 启动配置文件轮询监听
			startConfigFileWatcher(actualConfigFile, v)
		}

		// 监控 common.ini 文件（如果 RunInOmniagent 为 true）
		// 注意：RunInOmniagent 是启动时确定的标志，不支持热更新
		// 只有在启动时 RunInOmniagent 为 true 时，才会启动此监控
		if *flags.RunInOmniagent && *flags.CommonIni != "" {
			watchCommonIni(*flags.CommonIni)
		}

		configInstance = v

		// 初始化 Config 管理器
		cfg := Get()
		cfg.Init(v)

		// 应用初始配置（首次加载，可以覆盖默认值）
		// 注意：现在通过 Config 管理器统一处理，applyConfig 主要用于向后兼容
		applyConfig(v, false)
	})

	return err
}

// GetConfig 获取配置实例
func GetConfig() *viper.Viper {
	if configInstance == nil {
		// 如果未初始化，使用默认配置
		InitConfig("")
	}
	return configInstance
}

// ReloadConfig 手动重新加载配置
func ReloadConfig() error {
	configMutex.Lock()
	defer configMutex.Unlock()

	if configInstance == nil {
		return fmt.Errorf("config not initialized")
	}

	if err := configInstance.ReadInConfig(); err != nil {
		return fmt.Errorf("error reading config file: %w", err)
	}

	applyConfig(configInstance, false)
	return nil
}

// GetConfigValue 获取配置值（支持热加载）
func GetConfigValue(key string) interface{} {
	configMutex.RLock()
	defer configMutex.RUnlock()

	if configInstance == nil {
		return nil
	}

	return configInstance.Get(key)
}
