package controllers

import (
	"WorldEpcho/src/config"
	"WorldEpcho/src/config/e"
	"WorldEpcho/src/models"
	"WorldEpcho/src/service"
	"WorldEpcho/src/utils"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"time"
)

// jwtSecret 应该定义在安全的地方，比如环境变量或配置文件中

//var jwtSecret = []byte("your_jwt_secret")

// 用户登录控制器
func LoginJWT1(c *gin.Context) {
	// 获取表单信息
	username := c.PostForm("username")
	password := c.PostForm("password")

	fmt.Println("username:", username, ",password:", password)

	// 调用工具类的MD5加盐的函数
	salt := config.Conf.Md5Salt
	md5String, err := utils.MD5BySalf(password, salt)
	if err != nil {
		log.Println("密码加盐失败！")
		c.JSON(http.StatusOK, gin.H{"code": 0, "message": "密码加盐失败"})
		return
	}

	// 根据用户名和密码从数据库中查询
	Userid, level, status, tags, _, err := models.QueryUserWithParam2(username, md5String)
	if err != nil || Userid <= 0 {
		c.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户名或密码错误"})
		return
	}

	if status == -1 {
		c.JSON(http.StatusOK, gin.H{"code": 0, "message": "该用户已经注销!"})
		return
	}

	// 用户验证通过后，生成JWT Token
	token, err := GenerateLoginJWTToken(Userid, level)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 0, "message": "生成令牌失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    1,
		"message": "登录成功",
		"level":   level,
		"token":   token,
		"tags":    tags,
	})
}

// 定义一个结构体来匹配JSON数据格式
type LoginRequest struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

func LoginJWT(c *gin.Context) {
	var loginReq LoginRequest

	// 将请求的JSON数据绑定到结构体
	if err := c.ShouldBindJSON(&loginReq); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": e.InvalidParams, "data": nil, "message": "请求数据格式错误"})
		return
	}

	fmt.Println("username:", loginReq.Username, ", password:", loginReq.Password)

	// 调用工具类的MD5加盐的函数
	salt := config.Conf.Md5Salt
	md5String, err := utils.MD5BySalf(loginReq.Password, salt)
	if err != nil {
		log.Println("密码加盐失败！")
		c.JSON(http.StatusOK, gin.H{"code": e.InternalError, "data": nil, "message": "密码加盐失败"})
		return
	}

	// 根据用户名和密码从数据库中查询
	Userid, level, status, _, _, err := models.QueryUserWithParam2(loginReq.Username, md5String)
	if err != nil || Userid <= 0 {
		c.JSON(http.StatusOK, gin.H{"code": e.NotExistIdentifier, "data": nil, "message": "用户名或密码错误"})
		return
	}

	if status == -1 {
		c.JSON(http.StatusOK, gin.H{"code": e.NotExistUser, "data": nil, "message": "该用户已经注销!"})
		return
	}

	// 用户验证通过后，生成JWT Token
	token, err := GenerateLoginJWTToken(Userid, level)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": e.InternalError, "data": nil, "message": "生成令牌失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    e.SUCCESS,
		"message": "获取token成功",
		"data": gin.H{
			"level": level,
			"token": token,
		},
	})
}

// generateToken 生成JWT令牌

func GenerateLoginJWTToken(userId int64, level int) (string, error) {
	jwtSecret := config.Conf.JwtSecret

	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"user_id": userId,
		"level":   level,
		"exp":     time.Now().Add(3 * time.Hour).Unix(),
	})
	token, err := tokenClaims.SignedString([]byte(jwtSecret))
	if err != nil {
		return "", fmt.Errorf("%d: %w", e.InternalError, err) // Return an error with the internal error code
	}
	return token, nil
}

func AuthJwtIsValid() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 获取 Authorization 头部的 JWT 令牌
		tokenString := c.GetHeader("Authorization")
		if tokenString == "" {
			c.JSON(http.StatusUnauthorized, gin.H{"code": 0, "message": "请求未授权"})
			c.Abort()
			return
		}

		// 解析并验证 token
		token, isValid, err := service.ParseMIGUToken(tokenString)

		if err != nil || !isValid {
			// 处理解析或验证失败的情况，返回 401 Unauthorized 错误
			c.JSON(http.StatusUnauthorized, gin.H{"code": 0, "message": "令牌无效或过期"})
			c.Abort()
			return
		}

		// 提取 Token 中的声明（Claims）
		if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
			// 你可以提取相关的用户信息并存储到上下文中，供后续处理使用
			userID := claims["user_id"]
			level := claims["level"]

			// 将 userID 和其他信息保存在上下文中，以便后续使用
			c.Set("userID", userID)
			c.Set("userLevel", level)
		} else {
			// 如果 Claims 无法被解析或无效，也返回未授权
			c.JSON(http.StatusUnauthorized, gin.H{"code": 0, "message": "令牌无效"})
			c.Abort()
			return
		}

		// 令牌有效，继续处理请求
		c.Next()
	}
}

func AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {

		// 获取 Authorization 头部的 JWT 令牌
		tokenString := c.GetHeader("Authorization")
		if tokenString == "" {
			c.JSON(http.StatusUnauthorized, gin.H{"code": 0, "message": "请求未授权"})
			c.Abort()
			return
		}

		// 解析并验证 token
		token, isValid, err := service.ParseMIGUToken(tokenString)

		if err != nil || !isValid {
			// 处理解析或验证失败的情况，返回 401 Unauthorized 错误
			c.JSON(http.StatusUnauthorized, gin.H{"code": 0, "message": "令牌无效或过期"})
			c.Abort()
			return
		}

		// 提取 Token 中的声明（Claims）
		if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
			// 你可以提取相关的用户信息并存储到上下文中，供后续处理使用
			userID := claims["user_id"]
			level := claims["level"]

			// 将 userID 和其他信息保存在上下文中，以便后续使用
			c.Set("userID", userID)
			c.Set("userLevel", level)
		} else {
			// 如果 Claims 无法被解析或无效，也返回未授权
			c.JSON(http.StatusUnauthorized, gin.H{"code": 0, "message": "令牌无效"})
			c.Abort()
			return
		}

		// 令牌有效，继续处理请求
		c.Next()
	}
}

func LoginTest(c *gin.Context) {
	uid, islogin := service.IsUserLoggedIn(c)
	fmt.Println("uid ==> ", uid, "islogin ==>", islogin)
	c.JSON(http.StatusOK, gin.H{
		"code":    1,
		"uid":     uid,
		"islogin": islogin,
	})
}
