package jwtx

import (
	"encoding/json"
	"errors"
	"time"

	"github.com/golang-jwt/jwt/v4"
)

const ExtraKey = "extra"

type JwtClaims struct {
	UserId   string `json:"userId"`
	AgentId  string `json:"agentId"`
	Platform string `json:"platform"`
	// 用户身份类型：0-临时用户，1-正式用户
	UserType int64 `json:"userType"`
	// 是否代理：0-否，1-是
	IsAgent  int64  `json:"isAgent"`
	AuthType string `json:"authType"`
	AuthKey  string `json:"authKey"`
}

// MapToJwtClaims 将 map[string]interface{} 转换为 JwtClaims 结构体
func MapToJwtClaims(claimsMap map[string]interface{}) (*JwtClaims, error) {
	// 使用JSON序列化/反序列化的方式自动转换
	jsonData, err := json.Marshal(claimsMap)
	if err != nil {
		return nil, errors.New("序列化claims失败")
	}

	var claims JwtClaims
	if err := json.Unmarshal(jsonData, &claims); err != nil {
		return nil, errors.New("反序列化claims失败")
	}

	return &claims, nil
}

// GenerateJwtToken 生成JWT token
func GenerateJwtToken(claims JwtClaims, secret string, expire int64) (string, error) {
	now := time.Now().Unix()

	// 将 claims 结构体转换为 map[string]interface{}
	claimsBytes, err := json.Marshal(claims)
	if err != nil {
		return "", err
	}

	var claimsMap map[string]interface{}
	if err := json.Unmarshal(claimsBytes, &claimsMap); err != nil {
		return "", err
	}

	jwtClaims := jwt.MapClaims{
		"exp":    now + expire,
		"iat":    now,
		"userId": claims.UserId,
		ExtraKey: claimsMap,
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtClaims)
	return token.SignedString([]byte(secret))
}

func ParseJwtToken(tokenStr string, secret string) (*JwtClaims, error) {
	token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
		return []byte(secret), nil
	})

	if err != nil {
		// 检查是否是JWT验证错误
		if validationErr, ok := err.(*jwt.ValidationError); ok {
			// 如果是过期错误，返回更明确的错误信息
			if validationErr.Errors&jwt.ValidationErrorExpired != 0 {
				return nil, errors.New("token已过期")
			}
			// 如果是签名错误，返回签名错误信息
			if validationErr.Errors&jwt.ValidationErrorSignatureInvalid != 0 {
				return nil, errors.New("token签名无效")
			}
			// 其他验证错误
			return nil, errors.New("token验证失败")
		}
		return nil, errors.New("invalid JWT")
	}

	if !token.Valid {
		return nil, errors.New("token无效")
	}

	claims, ok := token.Claims.(jwt.MapClaims)
	if !ok {
		return nil, errors.New("invalid JWT claims")
	}

	extraInfo, exists := claims[ExtraKey]
	if !exists {
		return nil, errors.New("extra not found in JWT")
	}

	// 尝试直接断言为 JwtClaims 结构体
	if jwtClaims, ok := extraInfo.(JwtClaims); ok {
		return &jwtClaims, nil
	}

	// 尝试从 map[string]interface{} 中解析
	if claimsMap, ok := extraInfo.(map[string]interface{}); ok {
		return MapToJwtClaims(claimsMap)
	}

	return nil, errors.New("unsupported extra type in JWT")
}
