package token

import (
	"errors"
	"github.com/dgrijalva/jwt-go"
	"github.com/google/uuid"
	"time"
)

var JwtClaims = new(jwtClaims)

// JwtClaims 创建自己的Claims
type jwtClaims struct {
	*jwt.StandardClaims
	//用户编号
	ID          string
	SysUserName string
	UUID        uuid.UUID
	Time        time.Time
}

var (
	//盐
	secret                 = []byte("6MTY2MDcxMjgzNiwi")               // 后续加密增加盐增加复杂度
	TokenExpired     error = errors.New("Token is expired")            // token错误类型提炼
	TokenNotValidYet error = errors.New("Token not active yet")        // token错误类型提炼
	TokenMalformed   error = errors.New("That's not even a token")     // token错误类型提炼
	TokenInvalid     error = errors.New("Couldn't handle this token:") // token错误类型提炼
)

// CreateJwtToken 生成一个jwttoken
func (jwtClaims) CreateJwtToken(id, userName string, uuid uuid.UUID, ti time.Duration) (string, error) {

	// 定义过期时间
	expireToken := time.Now().Add(time.Hour * ti).Unix()

	claims := jwtClaims{
		&jwt.StandardClaims{
			NotBefore: int64(time.Now().Unix() - 1000), // token信息生效时间
			ExpiresAt: expireToken,                     // 过期时间0=永不过期
			Issuer:    "lc_veterans",                   // 发布者
		},
		id,
		userName,
		uuid,
		time.Now(),
	}
	// 对自定义claims加密,jwt.SigningMethodHS256是加密算法得到第二部分
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	// 给这个token盐加密 第三部分,得到一个完整的三段的加密
	signedToken, err := token.SignedString(secret)
	if err != nil {
		return "", err
	}
	return signedToken, nil
}

// ParseJwtToken 解析token得到是自己创建的Claims
func (jwtClaims) ParseJwtToken(jwtToken string) (*jwtClaims, error) {
	var jwtclaim = &jwtClaims{}
	_, err := jwt.ParseWithClaims(jwtToken, jwtclaim, func(*jwt.Token) (interface{}, error) {
		//得到盐
		return secret, nil
	})
	if err != nil {
		if ve, ok := err.(*jwt.ValidationError); ok {
			if ve.Errors&jwt.ValidationErrorMalformed != 0 {
				return nil, TokenMalformed
			} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
				// Token is expired
				return nil, TokenExpired
			} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
				return nil, TokenNotValidYet
			} else {
				return nil, TokenInvalid
			}
		}
	}
	return jwtclaim, nil
}
