package otherutils

import (
	"bytes"
	"fmt"
	"math"
	"math/rand"
	"strings"
	"sync/atomic"
	"time"
)

var orderIncrId uint32 //订单自增ID，每次重启从头开始即可
const charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

func ConvertToBase62(decimalNum int64, base int64) string {
	if base <= 0 || base > 62 {
		return ""
	}

	var buf bytes.Buffer

	for decimalNum > 0 {
		remainder := decimalNum % base
		decimalNum /= base
		buf.WriteByte(charset[remainder])
	}

	// 将结果反转
	result := buf.Bytes()
	for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 {
		result[i], result[j] = result[j], result[i]
	}
	return string(result)
}

// ConvertToDecimal 将 62 进制数转换为十进制数
func ConvertToDecimal(base62 string, base int64) int64 {
	// const charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	// base := int64(62)
	var result int64

	for i, char := range base62 {
		// 找到字符对应的索引
		index := strings.IndexRune(charset, char)
		// 根据62进制，累加对应的值
		result += int64(index) * int64(math.Pow(float64(base), float64(len(base62)-i-1)))
	}

	return result
}

func CreateOutTradeNo(playerId int64, serverId int64, zoneId int) string {

	n := atomic.AddUint32(&orderIncrId, 1)

	ct := time.Now()
	y, m, d := ct.Date()
	h := ct.Hour()
	mi := ct.Minute()
	s := ct.Second()

	num := int64(float64(y)*math.Pow10(10) +
		float64(m)*math.Pow10(8) +
		float64(d)*math.Pow10(6) +
		float64(h)*math.Pow10(4) +
		float64(mi)*math.Pow10(2) +
		float64(s))

	return fmt.Sprintf("%sZ%sZ%sZ%sZ%d",
		ConvertToBase62(num, 61),
		ConvertToBase62(serverId, 61),
		ConvertToBase62(playerId, 61),
		ConvertToBase62(int64(n%65536), 61),
		zoneId)

	// return fmt.Sprintf("%sZ%sZ%sZ%sZ%d",
	// 	ConvertToBase62(num, 36),
	// 	ConvertToBase62(serverId, 36),
	// 	ConvertToBase62(playerId, 36),
	// 	ConvertToBase62(int64(orderNum%65536), 36),
	// 	zoneId)
}

func TestCreateOutTradeNo() {
	var (
		playerId = 1
		serverId = 102
		// orderNum = 1
		zoneId = 1
	)

	for i := 0; i < 10000; i += 1 {
		playerId += 10000000
		// orderNum += 10
		orderCode := CreateOutTradeNo(int64(playerId), int64(serverId), zoneId)
		fmt.Println(orderCode)
	}
}

// 随机不含重复字符的字符串
// l长度 超过20需修改逻辑 命中会降低
func RandString(l int) string {
	cl := len(charset)
	if l > cl || l <= 0 {
		return ""
	}

	bytes := make([]byte, l)
	selected := make(map[byte]bool)

	for i := 0; i < l; {
		b := rand.Intn(cl)
		char := charset[b]

		if !selected[char] {
			bytes[i] = char
			selected[char] = true
			i++
		}
	}

	return string(bytes)
}
