package utils

import (
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"strconv"
	"time"
)

//创建token,
/*
uid:用户名
secret:密匙
alg:加密算法类型
exp：过期时间，单位是秒
*/
func CreateJwt(uid string, secret []byte, alg string, exp int64) (tokenString string, err error) {
	//get SigningMethod
	signingMethon := jwt.GetSigningMethod(alg)
	//time.Sleep(time.Nanosecond * time.Duration(RandomInt(0, 10)))
	iat := time.Now().Unix()
	// Create a new token object, specifying signing method and the claims
	// you would like it to contain.

	token := jwt.NewWithClaims(signingMethon, jwt.MapClaims{
		"iss": "Authen Center",
		"iat": iat,
		"exp": iat + exp,
		"jti": uid,
	})

	// Sign and get the complete encoded token as a string using the secret
	tokenString, err = token.SignedString(secret)
	//fmt.Printf("get jwt:%v,%v,%v\n%s\n", iat, iat+exp, uid, tokenString)
	return
}

//获取token的用户名
//tokenString token字符串
//tag 字段名 如jti
func GetUid(tokenString string, tag string) (string, error) {
	tokens, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		// Don't forget to validate the alg is what you expect:

		// hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key")
		return []byte(""), nil
	})
	if tokens == nil {
		return "", err
	}
	//fmt.Printf("%#v",tokens.Claims.(jwt.MapClaims))
	uid := tokens.Claims.(jwt.MapClaims)[tag]
	switch t := uid.(type) {
	case int:
		_ = t
		return strconv.Itoa(uid.(int)), nil
	case float64:
		_ = t
		return strconv.FormatFloat(uid.(float64), 'g', 12, 64), nil
		//... etc
	}
	return uid.(string), nil
}

//验证token
//secret 秘钥
//tokenString token的字符串
func VerifyJwt(secret []byte, tokenString string) (state int) {
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		// Don't forget to validate the alg is what you expect:
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		}
		// secret is a []byte containing your secret, e.g. []byte("my_secret_key")
		return secret, nil
	})

	if err != nil {
		state := -1 // jwt解析错误
		tempError := err.(*jwt.ValidationError)
		//fmt.Println("jwt error")
		//fmt.Println(tempError)

		//jwt过期
		if tempError.Errors == jwt.ValidationErrorExpired {
			//fmt.Println("jwt expired")
			state = -2
		}
		// jwt IAT 错误
		if tempError.Errors == jwt.ValidationErrorIssuedAt {
			//fmt.Printf("jwt iat error")
			state = -3
		}
		return state
	}

	if _, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		// fmt.Println(claims["iat"], claims["exp"])
		// 验证通过
		return 0
	}
	return 5
}
