package utils

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

const (
	HASH_SIZE_8  = 8
	HASH_SIZE_16 = 16
)

// apm_span_context
type ApmSpanContextT struct {
	type_from      [1]byte
	sample         [1]byte
	host_id        [8]byte
	app_id         [8]byte
	instance_id    [8]byte
	trace_id       [16]byte
	assumed_app_id [8]byte
	span_id        [8]byte
}

type HashByte [HASH_SIZE_8]byte

type HashByte16 [HASH_SIZE_16]byte

type Id_T struct {
	AppID      ID
	HostID     ID
	InstanceID ID
}

type ID struct {
	IntVal   int64
	HashtVal HashByte
}

func init() {

}

var (
	APP_ID_INT64      int64
	HOST_ID_INT64     int64
	INSTANCE_ID_INT64 int64

	APP_ID_BYTE      HashByte
	HOST_ID_BYTE     HashByte
	INSTANCE_ID_BYTE HashByte
)

func SetInsID(str string) (int64, HashByte) {
	srcCode := md5.Sum([]byte(str))
	code := fmt.Sprintf("%x", srcCode)
	id_string := md5ToDec(code)
	fmt.Println(id_string)
	id, err := strconv.ParseInt(id_string, 10, 64)
	if err != nil {
		return 0, HashByte{}
	}
	INSTANCE_ID_INT64 = id
	var charArray HashByte
	hexStringToBPFBytes(id_string, &charArray)
	INSTANCE_ID_BYTE = charArray
	return id, charArray
}

func GetHostID() (int64, HashByte) {
	if HOST_ID_INT64 != 0 {
		return HOST_ID_INT64, HOST_ID_BYTE
	}
	uuid := MachineID()
	str := fmt.Sprintf("%s:%s", "110", uuid)
	srcCode := md5.Sum([]byte(str))
	code := fmt.Sprintf("%x", srcCode)
	host_id_string := md5ToDec(code)
	fmt.Println(host_id_string)
	id, err := strconv.ParseInt(host_id_string, 10, 64)
	if err != nil {
		return 0, HashByte{}
	}

	fmt.Println(host_id_string)
	HOST_ID_INT64 = 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, charArray
}

func GetAppID() (int64, HashByte) {
	if APP_ID_INT64 != 0 {
		return APP_ID_INT64, APP_ID_BYTE
	}
	//str := fmt.Sprintf("%s:%s", "110", uuid)
	//srcCode := md5.Sum([]byte(str))
	//code := fmt.Sprintf("%x", srcCode)
	//id_string := md5ToDec(code)
	id_string := "5410049101545798"
	fmt.Println(id_string)
	id, err := strconv.ParseInt(id_string, 10, 64)
	if err != nil {
		return 0, HashByte{}
	}
	APP_ID_INT64 = id
	var charArray HashByte
	hexStringToBPFBytes(id_string, &charArray)
	APP_ID_BYTE = charArray
	return id, charArray
}

//func GetHostID2() uint64 {
//	if HOST_ID_UINT64 != 0 {
//		return HOST_ID_UINT64
//	}
//	uuid := MachineID()
//	hash := make([]byte, HASH_SIZE)
//	customHash(uuid, hash, HASH_SIZE)
//
//	fmt.Print("Hashed string: ")
//	for i := 0; i < HASH_SIZE; i++ {
//		fmt.Printf("%d", hash[i])
//	}
//	hashInt := byteArrayToInt(hash)
//	fmt.Println("HashByte as integer:", hashInt)
//	str := strconv.FormatInt(int64(hashInt), 10)
//
//	// 将 hash 转换为字符串（可以使用 Base64 或其他编码）
//	fmt.Println("HashByte as string:", str)
//	HOST_ID_UINT64 = hashInt
//	os.Exit(1)
//	return hashInt
//}

func MachineID() string {
	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), "-", "", -1))
		return id
	}
	return ""
}

func customHash(str string, hash []byte, size int) {
	var intHash uint64 = 0
	for i := 0; i < len(str); i++ {
		intHash = (intHash * 31) + uint64(str[i])
	}

	// Convert intHash to 16 bytes
	for i := 0; i < size; i++ {
		hash[i] = byte(intHash % 10)
		intHash /= 10
	}
	if hash[0] == 0 {
		hash[0] = 1
	}
}

func byteArrayToInt(hash []byte) uint64 {
	var result uint64
	for _, b := range hash {
		result = result*10 + uint64(b)
	}
	return result
}

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 hexStringToBPFBytes(str string, size int) []byte {
//	out := make([]byte, size/2)
//	for i := 0; i < size/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
//	}
//	return out
//}

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
	}
}

// hex 表示十六进制字符
var hex = []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}

// bytesToHexString 将字节数组转换为十六进制字符串
func BytesToHexString(pin HashByte) string {
	size := len(pin)
	out := make([]byte, size*2)
	pout := 0
	for i := 0; i < size; i++ {
		out[pout] = hex[(pin[i]>>4)&0xF]
		pout++
		out[pout] = hex[pin[i]&0xF]
		pout++
	}
	return string(out)
}
