package tools

import (
	"crypto/rand"
	"fmt"
	"github.com/holdno/snowFlakeByGo"
	"math/big"
	mathrand "math/rand"
	"time"

	"reflect"
	"regexp"
	"strconv"
	"strings"
	"sync"
)

func ToBool(ok bool) *bool {
	return &ok
}

// 生成序列号，比如用到订单编号上
func GenSerialNo() string {
	worker, _ := snowFlakeByGo.NewWorker(0)
	id := worker.GetId()
	return fmt.Sprintf("%X", id)[:10]
}

func StructToMap(str interface{}) (values map[string]interface{}) {
	values = map[string]interface{}{}
	iVal := reflect.ValueOf(str).Elem()
	typ := iVal.Type()
	for i := 0; i < iVal.NumField(); i++ {
		f := iVal.Field(i)
		// You ca use tags here...
		tag := typ.Field(i).Tag.Get("json")
		tag = strings.Split(tag, ",")[0]
		switch f.Interface().(type) {
		case int, int8, int16, int32, int64:
			values[tag] = f.Int()
		case uint, uint8, uint16, uint32, uint64:
			values[tag] = f.Uint()
		case float32, float64:
			values[tag] = f.Float()
		case bool:
			values[tag] = f.Bool()
		case string:
			values[tag] = f.String()
		case []string:
			values[tag] = f.String()
		}
	}
	return
}

// 正则验证手机号
func VerifyMobileFormat(mobileNum string) bool {
	regular := "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$"

	reg := regexp.MustCompile(regular)
	return reg.MatchString(mobileNum)
}

var IdWorker *snowFlakeByGo.Worker
var once sync.Once

// 单例初始化 SnowFlakeByGo
func InitSnowFlakeByGo() *snowFlakeByGo.Worker {
	once.Do(func() {
		IdWorker, _ = snowFlakeByGo.NewWorker(0)
	})
	return IdWorker
}

func GetSerialNo() int64 {

	id := IdWorker.GetId()

	return id
}

func GetSerialNo32HEXString() string {
	id := IdWorker.GetId()
	inviteCode := strconv.FormatUint(uint64(id), 32)
	return inviteCode
}

func GenPrizeOrderID() string {

	prix := RandomNum(10, 99)
	prixString := strconv.Itoa(int(prix))
	OrderID := RandomLenNum(14)
	return prixString + OrderID
}

func RandomNum(min int64, max int64) int64 {
	r := mathrand.New(mathrand.NewSource(time.Now().UnixNano()))
	num := min + r.Int63n(max-min+1)
	return num
}

func RandomLenNum(length int) string {
	str := ""
	r := mathrand.New(mathrand.NewSource(time.Now().UnixNano()))
	for i := 0; i < length; i++ {
		str += strconv.Itoa(r.Intn(10))
	}
	return str
}

func GenerateRandomNumber19() (string, error) {
	// Define the maximum number for a single digit (0-9)
	const digits = "0123456789"
	const length = 19

	// To store the generated number
	number := make([]byte, length)

	for i := 0; i < length; i++ {
		// Generate a random index from 0 to 9
		index, err := rand.Int(rand.Reader, big.NewInt(int64(len(digits))))
		if err != nil {
			return "", err
		}
		// Convert the index to a byte and add it to the number
		number[i] = digits[index.Int64()]
	}

	return string(number), nil
}
