package middleware

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"slices"
	"strings"
	"time"
	"wireguard-ui/component"
	"wireguard-ui/global/constant"
	"wireguard-ui/http/response"
	"wireguard-ui/service"
	"wireguard-ui/utils"
)

// Authorization
// @description: 授权中间件
// @return gin.HandlerFunc
func Authorization() gin.HandlerFunc {
	return func(c *gin.Context) {
		token := c.GetHeader("Authorization")
		if token == "" || !strings.HasPrefix(token, "Bearer ") {
			response.R(c).AuthorizationFailed("未登陆")
			c.Abort()
			return
		}

		hashPassword := c.Request.Header.Get("X-TOKEN")
		if hashPassword == "" {
			response.R(c).AuthorizationFailed("未登陆")
			c.Abort()
			return
		}

		userClaims, err := component.JWT().ParseToken(token, hashPassword, "http")
		if err != nil {
			response.R(c).AuthorizationFailed("未登陆")
			c.Abort()
			return
		}

		// 如果token的颁发者与请求的站点不一致那么就给它抬出去
		if !slices.Contains(strings.Split(userClaims.Issuer, ","), utils.WebSite().GetHost(c.Request.Header.Get("Referer"))) {
			response.R(c).AuthorizationFailed("未登陆")
			c.Abort()
			return
		}

		// 查询用户
		user, err := service.User().GetUserById(userClaims.ID)
		if err != nil {
			response.R(c).AuthorizationFailed("用户不存在")
			c.Abort()
			return
		}

		if user.Status != constant.Enabled {
			response.R(c).AuthorizationFailed("用户状态异常，请联系管理员处理！")
			c.Abort()
			return
		}

		// 将用户信息放入上下文
		c.Set("user", &user)

		if c.Request.RequestURI == "/api/user/logout" {
			c.Next()
		}

		// 生成一个新token
		secret := component.JWT().GenerateSecret(user.Password, uuid.NewString(), time.Now().Local().String())
		tokenStr, _, err := component.JWT().GenerateToken(user.Id, secret, "http", userClaims.ExpiresAt.Time, time.Now().Local())
		if err != nil {
			response.R(c).AuthorizationFailed("校验失败")
			c.Abort()
			return
		}

		c.Writer.Header().Set("Authorization", fmt.Sprintf("Bearer %s", tokenStr))
		c.Writer.Header().Set("X-TOKEN", secret)
		c.Next()
	}
}
