package entity

import (
	"hash/fnv"
	"strings"

	"github.com/google/uuid"
)

// The old system uses uint64 cluster id, while the new system require a base32-encoded-google-uuid string.
// For compatibility reason, we hash 128 bit uuid to uint64, with the trade of less uniqueness.
// Refer to https://pingcap.feishu.cn/wiki/wikcn9TNGienjZJS4aZcJDTna0g?chunked=false.
//
// uint64 max value is 18446744073709551615. We divide [0, 18446744073709551615] into 19 parts, which are:
//
//	[                   0, 00999999999999999999],
//	[01000000000000000000, 01999999999999999999],  <---- cluster IDs from the old CM are in this range
//	[10000000000000000000, 10999999999999999999],
//	...
//	[17000000000000000000, 17999999999999999999],
//	[18000000000000000000, 18446744073709551615]
//
// We use the [10000000000000000000, 10999999999999999999] part to store cluster IDs.
//
// The range of meaningful cluster should be in range [0, 999999999999999999], randomly. For 10000 total clusters, collision rate is 5E-11
//
// The final cluster id is (meaningful cluster + 10000000000000000000).

func GenClusterID() uint64 {
	const (
		clusterIDStartAt = 10000000000000000000
		clusterIDMod     = 1000000000000000000
	)

	h := fnv.New64()
	uuidStr := strings.Replace(uuid.New().String(), "-", "", 4)
	_, _ = h.Write([]byte(uuidStr))

	return h.Sum64()%clusterIDMod + clusterIDStartAt
}
