import { NextRequest, NextResponse } from "next/server"; import { requireAdmin } from "@/lib/api-auth"; import { db, tierDefinitions, auditLogs, eq } from "@epicure/db"; import { randomUUID } from "crypto"; import { UNLIMITED } from "@/lib/tiers"; interface RouteContext { params: Promise<{ tier: string }>; } const NUMERIC_FIELDS = ["maxRecipes", "aiCallsPerMonth", "storageMb", "maxPublicRecipes"] as const; type NumericField = (typeof NUMERIC_FIELDS)[number]; export async function PATCH(req: NextRequest, { params }: RouteContext) { const { session, response } = await requireAdmin(); if (response) return response; const { tier } = await params; if (tier !== "free" && tier !== "pro") { return NextResponse.json({ error: "Invalid tier" }, { status: 400 }); } const body = (await req.json()) as Partial>; const updateData: Partial> = {}; for (const field of NUMERIC_FIELDS) { const value = body[field]; if (value === undefined) continue; if (!Number.isInteger(value) || (value < 0 && value !== UNLIMITED)) { return NextResponse.json({ error: `Invalid value for ${field}` }, { status: 400 }); } updateData[field] = value; } const [updated] = await db .update(tierDefinitions) .set(updateData) .where(eq(tierDefinitions.tier, tier)) .returning(); if (!updated) { return NextResponse.json({ error: "Tier not found" }, { status: 404 }); } await db.insert(auditLogs).values({ id: randomUUID(), userId: session!.user.id, action: "admin.tier.update", targetType: "tier_definition", targetId: tier, metadata: JSON.stringify(updateData), createdAt: new Date(), }); return NextResponse.json({ tierDefinition: updated }); }