package config

import (
	"reflect"
	"sync"

	klog "github.com/sirupsen/logrus"
)

var (
	// lastConfigValues 记录上一次配置文件中的值，用于热更新时比较
	lastConfigValues   map[string]interface{}
	lastConfigValuesMu sync.RWMutex
)

// initLastConfigValues 初始化 lastConfigValues（如果还未初始化）
func initLastConfigValues() {
	lastConfigValuesMu.Lock()
	defer lastConfigValuesMu.Unlock()
	if lastConfigValues == nil {
		lastConfigValues = make(map[string]interface{})
	}
}

// getLastConfigValue 获取上一次配置文件中的值
func getLastConfigValue(key string) (interface{}, bool) {
	lastConfigValuesMu.RLock()
	defer lastConfigValuesMu.RUnlock()
	val, ok := lastConfigValues[key]
	return val, ok
}

// setLastConfigValue 设置上一次配置文件中的值
func setLastConfigValue(key string, value interface{}) {
	lastConfigValuesMu.Lock()
	defer lastConfigValuesMu.Unlock()
	if lastConfigValues == nil {
		lastConfigValues = make(map[string]interface{})
	}
	lastConfigValues[key] = value
}

// checkAndUpdateConfigValue 检查配置值是否改变，如果改变则执行更新操作
// key: 配置项的键（如 "logging.log_level"）
// newValue: 配置文件中的新值
// isHotReload: 是否为热更新
// updateFunc: 如果值改变，需要执行的更新函数
// 返回: 是否发生了改变
func checkAndUpdateConfigValue(key string, newValue interface{}, isHotReload bool, updateFunc func()) bool {
	initLastConfigValues()

	if isHotReload {
		// 热更新：比较新值和上一次的值
		lastValue, hasLastValue := getLastConfigValue(key)
		if !hasLastValue || !valuesEqual(lastValue, newValue) {
			if hasLastValue {
				klog.Infof("🔄 [CONFIG] %s changed in config file: %v -> %v", key, lastValue, newValue)
			} else {
				klog.Infof("🔄 [CONFIG] %s first detected in config file: %v", key, newValue)
			}
			if updateFunc != nil {
				updateFunc()
			}
			setLastConfigValue(key, newValue)
			return true
		}
		return false
	} else {
		// 初始加载：记录初始值
		setLastConfigValue(key, newValue)
		if updateFunc != nil {
			updateFunc()
		}
		return true
	}
}

// valuesEqual 比较两个值是否相等（支持基本类型和字符串）
func valuesEqual(a, b interface{}) bool {
	if a == nil && b == nil {
		return true
	}
	if a == nil || b == nil {
		return false
	}

	// 使用反射进行深度比较
	return reflect.DeepEqual(a, b)
}
