import { and, eq } from "drizzle-orm";
import { canDownload, canSocial, hasRole, idSchema, } from "@familyalbum/shared";
import { ApiError, forbidden, notFound } from "../../../core/errors.js";
import { db } from "../../../core/db/client.js";
import { albums, families, familyMembers, media } from "../db/schema.js";
/**
 * Hooks du module PrivateFamily. `requireFamilyMember` est la barrière
 * d'appartenance (rôle + statut) — sans RLS ici : une famille par serveur,
 * la vérification applicative suffit.
 */
export function buildFamilyAuthHooks(app) {
    return {
        requireFamilyMember(opts = { familyParam: "familyId" }) {
            return async (request, _reply) => {
                const user = request.user;
                const userId = user?.sub;
                if (!userId)
                    throw new ApiError(401, "unauthorized", "Non authentifié");
                const params = request.params;
                // Résolution de la famille (directe ou via mediaId/albumId).
                let familyId = null;
                if (opts.familyParam) {
                    const raw = params[opts.familyParam];
                    if (!raw)
                        throw new ApiError(400, "invalid_param", "familyId manquant");
                    if (!idSchema.safeParse(raw).success)
                        throw notFound();
                    familyId =
                        db
                            .select({ id: families.id })
                            .from(families)
                            .where(eq(families.id, raw))
                            .limit(1)
                            .get()?.id ?? null;
                }
                else if (opts.mediaParam) {
                    const raw = params[opts.mediaParam];
                    if (!raw)
                        throw new ApiError(400, "invalid_param", "mediaId manquant");
                    if (!idSchema.safeParse(raw).success)
                        throw notFound();
                    familyId =
                        db
                            .select({ familyId: media.familyId })
                            .from(media)
                            .where(eq(media.id, raw))
                            .limit(1)
                            .get()?.familyId ?? null;
                }
                else if (opts.albumParam) {
                    const raw = params[opts.albumParam];
                    if (!raw)
                        throw new ApiError(400, "invalid_param", "albumId manquant");
                    if (!idSchema.safeParse(raw).success)
                        throw notFound();
                    familyId =
                        db
                            .select({ familyId: albums.familyId })
                            .from(albums)
                            .where(eq(albums.id, raw))
                            .limit(1)
                            .get()?.familyId ?? null;
                }
                if (!familyId)
                    throw notFound();
                const [membership] = db
                    .select()
                    .from(familyMembers)
                    .where(and(eq(familyMembers.familyId, familyId), eq(familyMembers.userId, userId)))
                    .limit(1)
                    .all();
                if (!membership)
                    throw forbidden();
                const minRole = opts.minRole ?? "viewer";
                if (!hasRole(membership.role, minRole)) {
                    throw new ApiError(403, "admin_required", "Rôle insuffisant");
                }
                if (opts.minPermission) {
                    const ok = opts.minPermission === "full"
                        ? canSocial(membership.role, membership.permission)
                        : opts.minPermission === "download"
                            ? canDownload(membership.role, membership.permission)
                            : true; // "view" : tout membre
                    if (!ok) {
                        throw new ApiError(403, "permission_required", "Statut insuffisant");
                    }
                }
                request.familyContext = {
                    familyId,
                    userId,
                    role: membership.role,
                    permission: membership.permission,
                };
            };
        },
    };
}
//# sourceMappingURL=auth.js.map