package middleware

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-admin-team/go-admin-core/sdk/pkg"
	"go-admin/common/middleware/dto"
	"go-admin/common/service/sysservice/sysstatuscode"
	statuscode "go-admin/common/status_code"
	"go-admin/pkg/cryptohelper/jwthelper"
	"strconv"
	"strings"
	"time"

	"github.com/go-admin-team/go-admin-core/sdk/config"
	jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
	"go-admin/common/middleware/handler"
)

// AuthInit jwt验证new
func AuthInit() (*jwt.GinJWTMiddleware, error) {
	timeout := time.Hour
	if config.ApplicationConfig.Mode == "dev" {
		timeout = time.Duration(876010) * time.Hour
	} else {
		if config.JwtConfig.Timeout != 0 {
			timeout = time.Duration(config.JwtConfig.Timeout) * time.Second
		}
	}
	return jwt.New(&jwt.GinJWTMiddleware{
		Realm:           "test zone",
		Key:             []byte(config.JwtConfig.Secret),
		Timeout:         timeout,
		MaxRefresh:      time.Hour,
		PayloadFunc:     handler.PayloadFunc,
		IdentityHandler: handler.IdentityHandler,
		Authenticator:   handler.Authenticator,
		Authorizator:    handler.Authorizator,
		Unauthorized:    handler.Unauthorized,
		TokenLookup:     "header: Authorization, query: token, cookie: jwt",
		TokenHeadName:   "Bearer",
		TimeFunc:        time.Now,
	})

}

func FrontedAuth(c *gin.Context) {
	// 从请求头中获取 token 和 os
	token := c.GetHeader("Authorization")
	source, _ := strconv.Atoi(c.GetHeader("os"))
	// 如果 token 不存在，返回未登录的状态
	if len(token) == 0 {
		err := ResponseWithStatus(c, dto.NotLoginStatus, statuscode.NotLoggedIn)
		if err != nil {
			return
		}
		c.Abort() // 停止后续中间件的执行
		return
	}
	// 验证 token 并获取结果
	flag, rew := jwthelper.MidValidToken(token, source)
	if flag < 0 || len(rew) == 0 {
		if flag == -1 {
			ResponseWithStatus(c, dto.NotLoginStatus, statuscode.NotLoggedIn)
		} else if flag == -2 {
			ResponseWithStatus(c, dto.ReLoginStatus, statuscode.ReLogin)
		}
		c.Abort() // 停止后续中间件的执行
		return
	}
	// 将解析后的 token 设置到请求头中
	c.Request.Header.Set("ParseToken", rew)
	// 继续处理请求
	c.Next()
}

// ResponseWithStatus 带状态的响应
func ResponseWithStatus(ctx *gin.Context, status int, code int, data ...interface{}) error {
	// 获取语言对应的 msg
	msg := sysstatuscode.GetStatusCodeDescription(ctx, code)
	if msg == `` {
		msg = strconv.Itoa(code)
	} else {
		// 配置了语言包参数
		if strings.Contains(msg, "%") && len(data) > 1 {
			msg = fmt.Sprintf(msg, data[1:]...)
		}
	}

	resp := dto.Response{
		Status: status,
		Code:   code,
		Msg:    msg,
	}

	resp.RequestID = pkg.GenerateMsgIDFromContext(ctx)
	if len(data) > 0 {
		resp.Data = data[0]
	}

	ctx.JSON(200, resp)

	return nil
}
