package auth

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"

	"github.com/hhs/camtalk/internal/trace"
)

// contextKey 用于在 Gin context 中存储 Claims 的 key。
const (
	ContextKeyUserID   = "user_id"
	ContextKeyUsername = "username"
)

// AuthMiddleware 返回 Gin 中间件，从 Authorization: Bearer <token> 提取并校验 JWT。
// 校验成功后将 user_id 和 username 写入 Gin Context。
func AuthMiddleware(tokenMgr *TokenManager) gin.HandlerFunc {
	return func(c *gin.Context) {
		log := trace.FromContext(c.Request.Context())
		authHeader := c.GetHeader("Authorization")
		if authHeader == "" {
			log.Warnw("auth rejected",
				"client_ip", c.ClientIP(),
				"path", c.Request.URL.Path,
				"reason", "missing authorization header")
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    "INVALID_TOKEN",
				"message": "missing authorization header",
			})
			return
		}

		// 提取 Bearer token
		parts := strings.SplitN(authHeader, " ", 2)
		if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") {
			log.Warnw("auth rejected",
				"client_ip", c.ClientIP(),
				"path", c.Request.URL.Path,
				"reason", "invalid authorization format")
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    "INVALID_TOKEN",
				"message": "invalid authorization format",
			})
			return
		}

		claims, err := tokenMgr.ValidateAccess(parts[1])
		if err != nil {
			log.Warnw("auth rejected",
				"client_ip", c.ClientIP(),
				"path", c.Request.URL.Path,
				"reason", "invalid or expired token",
				"error", err)
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    "INVALID_TOKEN",
				"message": "invalid or expired token",
			})
			return
		}

		// 将用户信息写入 context
		c.Set(ContextKeyUserID, claims.UserID)
		c.Set(ContextKeyUsername, claims.Username)

		c.Next()
	}
}
