package httpserver

import (
	"errors"
	"net/http"

	authservice "update_server/internal/auth"
	"update_server/internal/db"
)

func (h *handler) requireAuthenticatedSession(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		cookie, err := r.Cookie(h.auth.SessionCookieName())
		if err != nil {
			http.Redirect(w, r, loginRedirectPath(r.URL.RequestURI()), http.StatusSeeOther)
			return
		}

		sessionState, err := h.auth.LoadSession(r.Context(), cookie.Value)
		if err != nil {
			if errors.Is(err, authservice.ErrUnauthenticated) {
				http.SetCookie(w, h.auth.ClearSessionCookie())
				http.Redirect(w, r, loginRedirectPath(r.URL.RequestURI()), http.StatusSeeOther)
				return
			}

			http.Error(w, "session lookup failed", http.StatusInternalServerError)
			return
		}

		next.ServeHTTP(w, r.WithContext(authservice.NewContext(r.Context(), sessionState)))
	})
}

func (h *handler) requireRole(requiredRole db.UserRole) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			sessionState, ok := authservice.FromContext(r.Context())
			if !ok {
				http.Error(w, "authentication required", http.StatusUnauthorized)
				return
			}

			if !authservice.RoleAllowed(sessionState.User.Role, requiredRole) {
				http.Error(w, "forbidden", http.StatusForbidden)
				return
			}

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