package middleware

import (
	"crypto/subtle"
	"log"
	"net/http"

	"metazone.cc/metalab/internal/config"

	"github.com/gin-gonic/gin"
)

const (
	csrfCookieName = "mlb_csrf"
	csrfHeaderName = "X-CSRF-Token"
	csrfMetaName   = "csrf_token"
)

// CSRF 中间件：Double Submit Cookie 模式
func CSRF(cfg *config.Config) gin.HandlerFunc {
	return func(c *gin.Context) {
		if c.Request.Method == http.MethodGet ||
			c.Request.Method == http.MethodHead ||
			c.Request.Method == http.MethodOptions {
			c.Next()
			return
		}

		cookieToken, err := c.Cookie(csrfCookieName)
		if err != nil || cookieToken == "" {
			c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
				"success": false, "message": "CSRF 验证失败",
			})
			return
		}

		headerToken := c.GetHeader(csrfHeaderName)
		if headerToken == "" {
			headerToken = c.PostForm(csrfMetaName)
		}
		if headerToken == "" {
			c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
				"success": false, "message": "CSRF 验证失败：缺少令牌",
			})
			return
		}

		if subtle.ConstantTimeCompare([]byte(cookieToken), []byte(headerToken)) != 1 {
			log.Printf("[CSRF] MISMATCH | path=%s | cookie(len=%d)=%q | header(len=%d)=%q",
				c.Request.URL.Path, len(cookieToken), cookieToken, len(headerToken), headerToken)
			c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
				"success": false, "message": "CSRF 验证失败",
			})
			return
		}

		log.Printf("[CSRF] OK | path=%s | token(len=%d)=%q", c.Request.URL.Path, len(cookieToken), cookieToken)

		c.Set(csrfMetaName, cookieToken)
		c.Next()
	}
}
