package pay

import (
	"crypto/md5"
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io"
	mathrand "math/rand"
	"strconv"
	"strings"
	"time"
)

const SALT = "xHDRofyCylff8BRZ"

//func RandomNum(min int64, max int64) int64 {
//	r := rand.New(rand.NewSource(time.Now().UnixNano()))
//	num := min + r.Int63n(max-min+1)
//	return num
//}
//
//func RandomNumString(min int64, max int64) string {
//	num := RandomNum(min, max)
//	return strconv.FormatInt(num, 10)
//}

func GenerateUid(uid uint32, sub uint32) string {
	chars := []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i",
		"j", "k", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E",
		"F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
	var randStr []string
	md := md5.New()
	md.Write([]byte(fmt.Sprintf("%s%d", SALT, uid*10+sub)))
	a := hex.EncodeToString(md.Sum(nil))
	for i := 0; i < 8; i++ {
		subString := []byte(a)[i*4 : i*4+4]
		vv := 0
		for _, v := range subString {
			vv += int(v)
		}
		randStr = append(randStr, chars[vv%len(chars)])
	}
	return strings.Join(randStr, "")
}

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

func GenOrderID() string {
	now := time.Now()
	strTime := fmt.Sprintf("%04d%02d%02d%02d%02d%02d", now.Year(), now.Month(), now.Day(), now.Hour(),
		now.Minute(), now.Second())
	return strTime + GenerateUid(uint32(RandomNum(0, 999999)), 0)
}

func GenerateTradeNO(prefix string) string {
	now := time.Now()
	strTime := fmt.Sprintf("%04d%02d%02d%02d%02d%02d", now.Year(), now.Month(), now.Day(), now.Hour(),
		now.Minute(), now.Second())
	return prefix + strTime + RandomNumString(1000, 9999)
}

const (
	KC_RAND_KIND_NUM   = 0 // 纯数字
	KC_RAND_KIND_LOWER = 1 // 小写字母
	KC_RAND_KIND_UPPER = 2 // 大写字母
	KC_RAND_KIND_ALL   = 3 // 数字、大小写字母
)

func GenRandomSalt(size int) (string, error) {
	if size < 0 {
		return "", fmt.Errorf("Size %v not valid, Size must be larger than 1", size)
	}

	buf := make([]byte, size)

	_, err := io.ReadFull(rand.Reader, buf)
	if err != nil {
		return "", err
	}

	return fmt.Sprintf("%x", buf), nil
}

func GenRandNum(len int) string {
	r := mathrand.New(mathrand.NewSource(time.Now().UnixNano()))
	key := strconv.Itoa(int(r.Int31n(9) + 1))
	for i := 0; i < len-1; i++ {
		r := mathrand.Int31n(10)
		key += strconv.Itoa(int(r))
	}
	return key
}

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 RandomNumString(min int64, max int64) string {
	num := RandomNum(min, max)
	return strconv.FormatInt(num, 10)
}

func GenRandomKey() string {
	lenStr := 6
	str := "123456789"
	bytes := []byte(str)
	result := []byte{}
	r := mathrand.New(mathrand.NewSource(time.Now().UnixNano()))
	for i := 0; i < lenStr; i++ {
		result = append(result, bytes[r.Intn(len(str))])
	}
	return string(result)
}

func GenRandStr(size int) string {
	if size <= 0 {
		return ""
	}
	return randStr(size, KC_RAND_KIND_ALL)
}

func GenRandomMac() string {
	var mac string
	r := mathrand.New(mathrand.NewSource(time.Now().UnixNano()))

	for i := 0; i < 6; i++ {
		num := r.Int31n(int32(256))
		if i == 0 {
			mac = fmt.Sprintf("%02x", num)
		} else {
			mac += ":" + fmt.Sprintf("%02x", num)
		}
	}
	return mac
}

func GenRandomLoraMac() string {
	var mac string
	r := mathrand.New(mathrand.NewSource(time.Now().UnixNano()))

	for i := 0; i < 2; i++ {
		num := r.Int31n(int32(0x100))
		mac += fmt.Sprintf("%02x", num) + ":"
	}
	num := r.Int31n(int32(0x20))
	mac += fmt.Sprintf("%02x", num) + ":00:00:00"
	return mac
}

// 随机字符串
func randStr(size int, kind int) string {
	ikind, kinds, result := kind, [][]int{[]int{10, 48}, []int{26, 97}, []int{26, 65}}, make([]byte, size)
	isAll := kind > 2 || kind < 0
	mathrand.Seed(time.Now().UnixNano())
	for i := 0; i < size; i++ {
		if isAll {
			ikind = mathrand.Intn(3)
		}
		scope, base := kinds[ikind][0], kinds[ikind][1]
		result[i] = uint8(base + mathrand.Intn(scope))
	}
	return string(result)
}

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
}
