package middleware

import (
	"net/http"

	"git.kirlllll.ru/volontery/backend/internal/service"
)

// RequirePermission создает middleware для проверки разрешения
func RequirePermission(userService *service.UserService, permission string) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			userID, ok := GetUserIDFromContext(r.Context())
			if !ok {
				http.Error(w, "unauthorized", http.StatusUnauthorized)
				return
			}

			hasPermission, err := userService.HasPermission(r.Context(), userID, permission)
			if err != nil {
				http.Error(w, "failed to check permissions", http.StatusInternalServerError)
				return
			}

			if !hasPermission {
				http.Error(w, "forbidden: insufficient permissions", http.StatusForbidden)
				return
			}

			next.ServeHTTP(w, r)
		})
	}
}

// RequireRole создает middleware для проверки роли
func RequireRole(userService *service.UserService, roleName string) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			userID, ok := GetUserIDFromContext(r.Context())
			if !ok {
				http.Error(w, "unauthorized", http.StatusUnauthorized)
				return
			}

			roles, err := userService.GetUserRoles(r.Context(), userID)
			if err != nil {
				http.Error(w, "failed to check roles", http.StatusInternalServerError)
				return
			}

			hasRole := false
			for _, role := range roles {
				if role.Name == roleName {
					hasRole = true
					break
				}
			}

			if !hasRole {
				http.Error(w, "forbidden: required role not assigned", http.StatusForbidden)
				return
			}

			next.ServeHTTP(w, r)
		})
	}
}

// RequireAnyRole создает middleware для проверки наличия хотя бы одной из ролей
func RequireAnyRole(userService *service.UserService, roleNames ...string) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			userID, ok := GetUserIDFromContext(r.Context())
			if !ok {
				http.Error(w, "unauthorized", http.StatusUnauthorized)
				return
			}

			roles, err := userService.GetUserRoles(r.Context(), userID)
			if err != nil {
				http.Error(w, "failed to check roles", http.StatusInternalServerError)
				return
			}

			hasAnyRole := false
			for _, role := range roles {
				for _, requiredRole := range roleNames {
					if role.Name == requiredRole {
						hasAnyRole = true
						break
					}
				}
				if hasAnyRole {
					break
				}
			}

			if !hasAnyRole {
				http.Error(w, "forbidden: none of the required roles assigned", http.StatusForbidden)
				return
			}

			next.ServeHTTP(w, r)
		})
	}
}
