// internal/middleware/jwt_middleware.go
package middleware

import (
	"lost-and-found/internal/config"
	"lost-and-found/internal/repositories"
	"lost-and-found/internal/utils"
	"net/http"
	"strings"

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

// JWTMiddleware validates JWT token
func JWTMiddleware(db *gorm.DB) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		// Get token from Authorization header
		authHeader := ctx.GetHeader("Authorization")
		if authHeader == "" {
			utils.ErrorResponse(ctx, http.StatusUnauthorized, "Authorization header required", "")
			ctx.Abort()
			return
		}

		// Check if Bearer token
		parts := strings.Split(authHeader, " ")
		if len(parts) != 2 || parts[0] != "Bearer" {
			utils.ErrorResponse(ctx, http.StatusUnauthorized, "Invalid authorization format", "")
			ctx.Abort()
			return
		}

		tokenString := parts[1]

		// Validate token
		claims, err := config.ValidateToken(tokenString)
		if err != nil {
			utils.ErrorResponse(ctx, http.StatusUnauthorized, "Invalid or expired token", err.Error())
			ctx.Abort()
			return
		}

		// Get user from database
		userRepo := repositories.NewUserRepository(db)
		user, err := userRepo.FindByID(claims.UserID)
		if err != nil {
			utils.ErrorResponse(ctx, http.StatusUnauthorized, "User not found", "")
			ctx.Abort()
			return
		}

		// Check if user is blocked
		if user.IsBlocked() {
			utils.ErrorResponse(ctx, http.StatusForbidden, "Account is blocked", "")
			ctx.Abort()
			return
		}

		// Set user in context
		ctx.Set("user", user)
		ctx.Set("user_id", user.ID)
		ctx.Set("user_role", user.Role.Name)

		ctx.Next()
	}
}

// OptionalJWTMiddleware validates JWT token if present (for public routes that can benefit from auth)
func OptionalJWTMiddleware(db *gorm.DB) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		authHeader := ctx.GetHeader("Authorization")
		if authHeader == "" {
			ctx.Next()
			return
		}

		parts := strings.Split(authHeader, " ")
		if len(parts) != 2 || parts[0] != "Bearer" {
			ctx.Next()
			return
		}

		tokenString := parts[1]
		claims, err := config.ValidateToken(tokenString)
		if err != nil {
			ctx.Next()
			return
		}

		userRepo := repositories.NewUserRepository(db)
		user, err := userRepo.FindByID(claims.UserID)
		if err != nil {
			ctx.Next()
			return
		}

		if !user.IsBlocked() {
			ctx.Set("user", user)
			ctx.Set("user_id", user.ID)
			ctx.Set("user_role", user.Role.Name)
		}

		ctx.Next()
	}
}