package auth

import (
	"encoding/json"
	"net/http"
)

// RequireAdmin is a middleware that MUST run after RequireUser. It reads the
// authenticated user from request context and rejects non-admin callers with
// 403. If no user is in context (RequireUser was bypassed), it returns 500 —
// that is a programmer error in the routing setup, not a client error.
//
// Mount this on /api/admin/* after auth.RequireUser:
//
//	r.Route("/api/admin", func(admin chi.Router) {
//	    admin.Use(auth.RequireUser(pool))
//	    admin.Use(auth.RequireAdmin())
//	    ...
//	})
func RequireAdmin() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			user, ok := UserFromContext(r.Context())
			if !ok {
				// Programmer error: RequireUser was not mounted before RequireAdmin.
				writeAdminErr(w, http.StatusInternalServerError, "internal_error")
				return
			}
			if !user.IsAdmin {
				writeAdminErr(w, http.StatusForbidden, "not_authorized")
				return
			}
			next.ServeHTTP(w, r)
		})
	}
}

// writeAdminErr writes a flat JSON error envelope {"error":"<code>"} and sets
// Content-Type. Uses a flat envelope (not the nested api.errorBody shape)
// because the spec for /api/admin/* errors defines {"error":"<code>"} directly.
func writeAdminErr(w http.ResponseWriter, status int, code string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	_ = json.NewEncoder(w).Encode(map[string]string{"error": code})
}
