package gamedata

import (
	"encoding/json"
	"errors"
	"io"
	"os"
	"path/filepath"
	"strconv"
	"sync"

	"server/conf"
	"server/game/mod/item"
	"server/pkg/github.com/name5566/leaf/log"
)

var (
	ConfPath             = "./gamedata/config/"
	G_AllConfigs         = map[string]interface{}{}
	G_AllConfigsJsonData = map[string]*ConfigData{}
	configMutex          sync.RWMutex // 全局配置锁
)

type ConfigData struct {
	data map[string]interface{}
	mu   sync.RWMutex
}

func (cd *ConfigData) GetData() map[string]interface{} {
	cd.mu.RLock()
	defer cd.mu.RUnlock()
	return cd.data
}

func (cd *ConfigData) SetData(data map[string]interface{}) {
	cd.mu.Lock()
	defer cd.mu.Unlock()
	cd.data = data
}

func init() {
	if conf.Server.GameConfPath != "" {
		ConfPath = conf.Server.GameConfPath
	}
}

func Reload() {
	configMutex.RLock()
	keys := make([]string, 0, len(G_AllConfigsJsonData))
	for k := range G_AllConfigsJsonData {
		keys = append(keys, k)
	}
	configMutex.RUnlock()

	for _, k := range keys {
		InitCfg(k)
		log.Debug("配置已重新加载:%s", k)
	}
}

func InitCfg(cfgname string) {
	// 读取文件内容
	filePath := ConfPath + cfgname + ".json"
	absPath, _ := filepath.Abs(filePath)

	file, err := os.Open(absPath)
	if err != nil {
		log.Debug("打开文件失败:%v", err)
		return
	}
	defer file.Close()

	// 读取文件内容到字节数组
	byteValue, err := io.ReadAll(file)
	if err != nil {
		log.Debug("读取文件失败:%v", err)
		return
	}
	// 移除 BOM
	if len(byteValue) >= 3 && byteValue[0] == 0xEF && byteValue[1] == 0xBB && byteValue[2] == 0xBF {
		byteValue = byteValue[3:]
	}
	var data map[string]interface{}
	// 反序列化JSON数据
	err = json.Unmarshal(byteValue, &data)
	if err != nil {
		log.Debug("config name:%s,反序列化失败:%v", cfgname, err)
		return
	}
	// 直接使用data，无需多余拷贝
	rf := new(ConfigData)
	rf.SetData(data)

	// 使用锁保护全局map
	configMutex.Lock()
	G_AllConfigsJsonData[cfgname] = rf
	configMutex.Unlock()
}

// 提取公共的 map 检查逻辑
func getMapValue(a interface{}, key string) (interface{}, bool) {
	if a == nil {
		return nil, false
	}
	if m, ok := a.(map[string]interface{}); ok {
		if v, ok := m[key]; ok {
			return v, true
		}
	}
	return nil, false
}

func GetValue(a interface{}, key string) interface{} {
	v, _ := getMapValue(a, key)
	return v
}

func GetIntValue(a interface{}, key string) int {
	v, ok := getMapValue(a, key)
	if !ok || v == nil {
		return 0
	}
	return Int(v)
}

func GetIntSliceValue(a interface{}, key string) []int {
	v, ok := getMapValue(a, key)
	if !ok || v == nil {
		return nil
	}
	// 安全的类型断言，避免panic
	if slice, ok := v.([]interface{}); ok {
		r := make([]int, 0, len(slice)) // 预分配容量
		for _, item := range slice {
			if num, ok := item.(float64); ok {
				r = append(r, int(num))
			}
		}
		return r
	}
	return nil
}

func GetFloatValue(a interface{}, key string) float64 {
	v, ok := getMapValue(a, key)
	if !ok || v == nil {
		return 0
	}
	// 安全的类型断言
	if f, ok := v.(float64); ok {
		return f
	}
	return 0
}

func GetItemList(a interface{}, key string) []*item.Item {
	v, ok := getMapValue(a, key)
	if !ok || v == nil {
		return nil
	}
	return item.ParseItem(v)
}

func GetStringValue(a interface{}, key string) string {
	v, ok := getMapValue(a, key)
	if !ok || v == nil {
		return ""
	}
	return String(v)
}

func GetData(cfgname string) (map[string]interface{}, error) {
	configMutex.RLock()
	v, ok := G_AllConfigsJsonData[cfgname]
	configMutex.RUnlock()

	if ok {
		return v.GetData(), nil
	}
	return nil, errors.New("config not found: " + cfgname)
}

func GetDataByKey(cfgname, key string) (map[string]interface{}, error) {
	configMutex.RLock()
	v, ok := G_AllConfigsJsonData[cfgname]
	configMutex.RUnlock()

	if ok {
		data := v.GetData()
		if val, ok := data[key]; ok {
			// 安全的类型断言
			if result, ok := val.(map[string]interface{}); ok {
				return result, nil
			}
			return nil, errors.New("invalid data type for key: " + key)
		}
	}
	return nil, errors.New("config or key not found")
}

func GetDataByIntKey(cfgname string, key int) (map[string]interface{}, error) {
	keyStr := strconv.Itoa(key)
	configMutex.RLock()
	v, ok := G_AllConfigsJsonData[cfgname]
	configMutex.RUnlock()

	if ok {
		data := v.GetData()
		if val, ok := data[keyStr]; ok {
			// 安全的类型断言
			if result, ok := val.(map[string]interface{}); ok {
				return result, nil
			}
			return nil, errors.New("invalid data type for key: " + keyStr)
		}
	}
	return nil, errors.New("config or key not found")
}

func Int(a interface{}) int {
	if a == nil {
		return 0
	}
	switch v := a.(type) {
	case int:
		return v
	case int32:
		return int(v)
	case int64:
		return int(v)
	case float64:
		return int(v)
	case string:
		r, err := strconv.Atoi(v)
		if err != nil {
			return 0
		}
		return r
	}
	return 0
}

func String(a interface{}) string {
	if a == nil {
		return ""
	}
	switch v := a.(type) {
	case int:
		return strconv.Itoa(v)
	case int32:
		return strconv.Itoa(int(v))
	case int64:
		return strconv.Itoa(int(v))
	case float64:
		return strconv.FormatFloat(v, 'f', -1, 64)
	case string:
		return v
	}
	return ""
}
