package middlewares

import (
	"strings"

	"doormile/config"
	"doormile/utils"

	"github.com/gofiber/fiber/v2"
)

func AuthMiddleware(cfg *config.Config) fiber.Handler {
	return func(c *fiber.Ctx) error {
		authHeader := c.Get("Authorization")
		if authHeader == "" {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"success": false,
				"message": "authorization header is required",
			})
		}

		parts := strings.Split(authHeader, " ")
		if len(parts) != 2 || parts[0] != "Bearer" {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"success": false,
				"message": "authorization header must be in format: Bearer <token>",
			})
		}

		tokenString := parts[1]
		claims, err := utils.ParseToken(tokenString, cfg.JWTSecret)
		if err != nil {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"success": false,
				"message": "invalid or expired token",
			})
		}

		c.Locals("userid", claims.UserID)
		c.Locals("email", claims.Email)
		c.Locals("roleid", claims.RoleID)
		c.Locals("tenantid", claims.TenantID)

		return c.Next()
	}
}

// HubStaffAuth validates the JWT and requires role 6 (hub staff), then
// exposes hubid via c.Locals so hub handlers can scope all queries to it.
func HubStaffAuth(cfg *config.Config) fiber.Handler {
	return func(c *fiber.Ctx) error {
		authHeader := c.Get("Authorization")
		if authHeader == "" {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"success": false,
				"message": "authorization header is required",
			})
		}

		parts := strings.Split(authHeader, " ")
		if len(parts) != 2 || parts[0] != "Bearer" {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"success": false,
				"message": "authorization header must be in format: Bearer <token>",
			})
		}

		claims, err := utils.ParseToken(parts[1], cfg.JWTSecret)
		if err != nil {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"success": false,
				"message": "invalid or expired token",
			})
		}

		if claims.RoleID != 6 {
			return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
				"success": false,
				"message": "access restricted to hub staff",
			})
		}

		c.Locals("userid", claims.UserID)
		c.Locals("email", claims.Email)
		c.Locals("roleid", claims.RoleID)
		c.Locals("hubid", claims.HubID)

		return c.Next()
	}
}

func RoleCheckMiddleware(allowedRoles ...int) fiber.Handler {
	return func(c *fiber.Ctx) error {
		roleID, ok := c.Locals("roleid").(int)
		if !ok {
			return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
				"success": false,
				"message": "access denied",
			})
		}

		for _, role := range allowedRoles {
			if roleID == role {
				return c.Next()
			}
		}

		return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
			"success": false,
			"message": "insufficient permissions for this resource",
		})
	}
}
