package web

import (
	"fmt"
	"log/slog"
	"net/http"
	"strings"

	"git.lnton.com/lnton/pkg/reason"
	"git.lnton.com/lnton/pkg/web"
	"github.com/gin-gonic/gin"
)

const (
	uid        = "uid"
	token      = "token"
	username   = "username"
	groupLevel = "group_level"
	level      = "level"
	role       = "role"
)

// AuthMiddleware 鉴权
func AuthMiddleware(secret string,
	authAddr string, /*第三方鉴权地址*/
	failedRedirect string, /*鉴权失败后重定向地址*/
) gin.HandlerFunc {
	// var errResp = gin.H{
	// "msg": "身份验证失败",
	// }
	return func(c *gin.Context) {

		// 创建不进行鉴权
		// err := systemAuth(c, secret)
		// if err == nil {
		// 	c.Next()
		// 	return
		// }
		// slog.DebugContext(c.Request.Context(), "systemAuth鉴权失败", "err", err)

		// 使用第三方鉴权
		if authAddr != "" {
			err := AuthenticateWithOAuth(c, authAddr)
			if err == nil {
				c.Next()
				return
			}
			slog.DebugContext(c.Request.Context(), "AuthenticateWithOAuth鉴权失败", "err", err)
		}
		// 鉴权失败进行重定向
		if failedRedirect != "" {
			c.Writer.Header().Set("X-Redirect", failedRedirect)
		}
		web.AbortWithStatusJSON(c, reason.ErrUnauthorizedToken.SetMsg("身份验证失败"))
	}
}

func systemAuth(c *gin.Context, secret string) error {
	auth := c.Request.Header.Get(" Authorization")
	const prefix = "Bearer "
	if len(auth) <= len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
		return reason.ErrUnauthorizedToken.SetMsg("鉴权失败")
	}
	claims, err := web.ParseToken(auth[len(prefix):], secret)
	if err != nil {
		return reason.ErrUnauthorizedToken.SetMsg("身份已过期，请重新登录")
	}
	if err := claims.Valid(); err != nil {
		return reason.ErrUnauthorizedToken.SetMsg("身份已过期，请重新登录")
	}

	c.Set(uid, claims.UID)
	c.Set(username, claims.Username)
	c.Set(token, auth)
	c.Set(groupLevel, claims.GroupLevel)
	return nil
}

// AuthenticateWithOAuth 第三方鉴权逻辑
func AuthenticateWithOAuth(c *gin.Context, authAddr string) error {
	req, err := http.NewRequest(http.MethodPost, authAddr, nil)
	if err != nil {
		// c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create request"})
		return reason.ErrBadRequest.SetMsg("failed to create request")
	}

	// 转发请求头
	for key, values := range c.Request.Header {
		// 如果包含 origin 头，跳过
		if strings.EqualFold(strings.ToLower(key), "origin") {
			continue
		}
		for _, value := range values {
			req.Header.Add(key, value)
		}
	}
	clientIP := c.ClientIP() // 获取客户端 IP 地址
	// 获取现有的 X-Forwarded-For 头
	existingIPs := c.Request.Header.Get("X-Forwarded-For")

	if existingIPs == "" {
		// 如果没有 X-Forwarded-For 头，设置客户端 IP
		req.Header.Set("X-Forwarded-For", clientIP)
	} else {
		// 如果已经存在 X-Forwarded-For 头，追加客户端 IP
		req.Header.Set("X-Forwarded-For", fmt.Sprintf("%s, %s", existingIPs, clientIP))
	}
	// 发送请求
	client := &http.Client{} // TODO:超时控制
	resp, err := client.Do(req)
	if err != nil {
		return reason.ErrBadRequest.SetMsg("request to backend failed")
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return reason.ErrUnauthorizedToken.SetMsg("身份验证失败")
	}

	// 读取响应
	// responseBody, err := ioutil.ReadAll(resp.Body)
	// if err != nil {
	//	return reason.ErrBadRequest.SetMsg("failed to read response body")
	// }
	// respStruct := struct {
	//	Code int    `json:"code"`
	//	Msg  string `json:"msg"`
	// }{}

	// if err := json.Unmarshal(responseBody, &respStruct); err != nil || respStruct.Code != 200 {
	//	return reason.ErrUnauthorizedToken.SetMsg("身份验证失败")
	// }
	c.Set(uid, 224)
	c.Set("groupID", 111)
	c.Set(username, "api_admin")
	c.Set(role, "admin")
	c.Set(groupLevel, 1)
	c.Set(level, 1)
	c.Set(web.KeyRoleID, 1)
	// c.Set(token, auth)
	return nil
}
