package middleware

import (
	"strings"

	"git.ma-al.com/goc_daniel/b2b/app/config"
	"git.ma-al.com/goc_daniel/b2b/app/model"
	"git.ma-al.com/goc_daniel/b2b/app/service/authService"
	constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"

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

// AuthMiddleware creates authentication middleware
func AuthMiddleware() fiber.Handler {
	authService := authService.NewAuthService()

	return func(c fiber.Ctx) error {
		// Get token from Authorization header
		authHeader := c.Get("Authorization")
		if authHeader == "" {
			// Try to get from cookie
			authHeader = c.Cookies("access_token")
			if authHeader == "" {
				return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
					"error": "authorization token required",
				})
			}
		} else {
			// Extract token from "Bearer <token>"
			parts := strings.Split(authHeader, " ")
			if len(parts) != 2 || parts[0] != "Bearer" {
				return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
					"error": "invalid authorization header format",
				})
			}
			authHeader = parts[1]
		}

		// Validate token
		claims, err := authService.ValidateToken(authHeader)
		if err != nil {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"error": "invalid or expired token",
			})
		}

		// Get user from database
		user, err := authService.GetUserByID(claims.UserID)
		if err != nil {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"error": "user not found",
			})
		}

		// Check if user is active
		if !user.IsActive {
			return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
				"error": "user account is inactive",
			})
		}

		// Set user in context
		c.Locals(constdata.USER_LOCALES_NAME, user.ToSession())
		c.Locals(constdata.USER_LOCALES_ID, user.ID)

		return c.Next()
	}
}

// RequireAdmin creates admin-only middleware
func RequireAdmin() fiber.Handler {
	return func(c fiber.Ctx) error {
		user := c.Locals("user")
		if user == nil {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"error": "not authenticated",
			})
		}

		userSession, ok := user.(*model.UserSession)
		if !ok {
			return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
				"error": "invalid user session",
			})
		}

		if userSession.Role != model.RoleAdmin {
			return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
				"error": "admin access required",
			})
		}

		return c.Next()
	}
}

// GetUserID extracts user ID from context
func GetUserID(c fiber.Ctx) uint {
	userID, ok := c.Locals("userID").(uint)
	if !ok {
		return 0
	}
	return userID
}

// GetUser extracts user from context
func GetUser(c fiber.Ctx) *model.UserSession {
	user, ok := c.Locals("user").(*model.UserSession)
	if !ok {
		return nil
	}
	return user
}

// GetConfig returns the app config
func GetConfig() *config.Config {
	return config.Get()
}
