package utils

import (
	"crypto/md5"
	"fmt"
	"math"
	"math/big"
	"os"
	"path"
	"strconv"
	"strings"

	. "github.com/coroot/coroot-node-agent/utils/modelse"
)

func SaveNodeInfo(n *NodeInfoT) {
	if n != nil {
		NODE_INFO = n
	}
}

func BuildInt64ID(str string) ID_STRING {
	//srcCode := md5.Sum([]byte(str))
	//code := fmt.Sprintf("%x", srcCode)
	//id_string := md5ToDec(code)
	//return ID_STRING(id_string)
	return ID_STRING(hashTo16DigitString(str))
}

func hexStringToBPFBytes(str string, out *HashByte) {
	for i := 0; i < len(str)/2; i++ {
		ch0 := str[2*i]
		ch1 := str[2*i+1]
		nib0 := (ch0 & 0x0F) + (ch0 >> 6) | ((ch0 >> 3) & 0x08)
		nib1 := (ch1 & 0x0F) + (ch1 >> 6) | ((ch1 >> 3) & 0x08)
		(*out)[i] = (nib0 << 4) | nib1
	}
}

// GetAccountID 获取账户ID，如果未注册则返回0
func GetAccountID() int {
	if NODE_INFO != nil && NODE_INFO.AccountID != 0 {
		return NODE_INFO.AccountID
	}
	// 如果未注册，返回0，等待注册完成后更新
	return 0
}

// GetSys
func GetSysTag() string {
	if NODE_INFO != nil {
		return NODE_INFO.SysTag
	}
	return ""
}

// GetSys
func GetSystemUUID() string {
	if NODE_INFO != nil {
		return NODE_INFO.SystemUUID
	}
	return ""
}

func GetHostIP() string {
	if NODE_INFO != nil {
		return NODE_INFO.HostIp
	}
	return ""
}

func GetHostID() int64 {
	if NODE_INFO != nil && NODE_INFO.HostID != 0 {
		return NODE_INFO.HostID
	}
	uuid := SystemUUID()
	// todo AccountId
	str := fmt.Sprintf("%d:%s", GetAccountID(), uuid)
	srcCode := md5.Sum([]byte(str))
	code := fmt.Sprintf("%x", srcCode)
	host_id_string := md5ToDec(code)
	id, err := strconv.ParseInt(host_id_string, 10, 64)
	if err != nil {
		return 0
	}

	NODE_INFO.HostID = id

	//var charArray HashByte
	//hexStringToBPFBytes(host_id_string, &charArray)
	//HOST_ID_BYTE = charArray
	// 将rune切片复制到char数组中
	//for i := 0; i < HASH_SIZE; i++ {
	//	charArray[i] = []byte(host_id_string)[i]
	//}
	return id
}

func GetHostIDBPFString() HashByte {
	host_id_string := strconv.FormatInt(GetHostID(), 10)
	var charArray HashByte
	hexStringToBPFBytes(host_id_string, &charArray)
	return charArray
}

func SystemUUID() string {
	if NODE_INFO != nil && NODE_INFO.SystemUUID != "" {
		return NODE_INFO.SystemUUID
	}
	for _, p := range []string{"sys/devices/virtual/dmi/id/product_uuid", "etc/machine-id", "var/lib/dbus/machine-id"} {
		payload, err := os.ReadFile(path.Join("/proc/1/root", p))
		if err != nil {
			continue
		}
		id := strings.TrimSpace(strings.Replace(string(payload), "\n", "", -1))
		NODE_INFO.SystemUUID = id
		return id
	}
	return ""
}

func hexdec(hexStr string) int {
	dec, _ := strconv.ParseInt(hexStr, 16, 64)
	return int(dec)
}

func md5ToDec(str string) string {
	strCode := ""
	for i := 0; i < 16; i++ {
		strCode += strconv.Itoa(int(math.Floor(float64(hexdec(string(str[i]))) / 16.0 * 10)))
		if i == 0 && strings.TrimSpace(strCode) == "0" {
			strCode = "1" + strCode
		}
	}
	return strCode
}

func hashTo16DigitString(appName string) string {
	// 计算 MD5 哈希
	hash := md5.Sum([]byte(appName))
	// 将哈希值转换为一个大整数
	bigInt := new(big.Int).SetBytes(hash[:])
	// 转换为十进制字符串
	intStr := bigInt.String()
	// 如果结果少于 16 位，补零
	if len(intStr) < 16 {
		intStr = fmt.Sprintf("%016s", intStr) // 左侧补零
		// 如果第一个字符是 0，将其替换为 1
		if intStr[0] == '0' {
			intStr = "1" + intStr[1:]
		}
	}
	// 截取前 16 位
	return intStr[:16]
}
