import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; import { db, recipes, cookingHistory, pantryItems, recipeIngredients, eq, and } from "@epicure/db"; import { requireSession } from "@/lib/api-auth"; type Params = { params: Promise<{ id: string }> }; const Schema = z.object({ servings: z.number().int().min(1).max(1000).optional(), notes: z.string().max(2000).optional(), deductFromPantry: z.boolean().default(true), }); export async function POST(req: NextRequest, { params }: Params) { const { session, response } = await requireSession(); if (response) return response; const { id } = await params; const userId = session!.user.id; const recipe = await db.query.recipes.findFirst({ where: eq(recipes.id, id) }); if (!recipe || (recipe.visibility === "private" && recipe.authorId !== userId)) { return NextResponse.json({ error: "Not found" }, { status: 404 }); } const body = await req.json().catch(() => ({})) as unknown; const parsed = Schema.safeParse(body); const data = parsed.success ? parsed.data : { deductFromPantry: true }; await db.insert(cookingHistory).values({ id: crypto.randomUUID(), userId, recipeId: id, servings: data.servings, notes: data.notes, cookedAt: new Date(), }); if (data.deductFromPantry) { const ings = await db.query.recipeIngredients.findMany({ where: eq(recipeIngredients.recipeId, id), }); const scale = data.servings ? data.servings / recipe.baseServings : 1; const userPantry = await db.query.pantryItems.findMany({ where: eq(pantryItems.userId, userId), }); for (const ing of ings) { const key = ing.rawName.toLowerCase(); const pantryItem = userPantry.find( (p) => p.rawName.toLowerCase() === key && (p.unit ?? "") === (ing.unit ?? "") ); if (!pantryItem) continue; const pantryQty = pantryItem.quantity ? parseFloat(pantryItem.quantity) : null; const ingQty = ing.quantity ? parseFloat(ing.quantity) * scale : null; if (pantryQty !== null && ingQty !== null && !isNaN(pantryQty) && !isNaN(ingQty)) { const remaining = pantryQty - ingQty; if (remaining <= 0) { await db.delete(pantryItems).where(eq(pantryItems.id, pantryItem.id)); } else { await db.update(pantryItems) .set({ quantity: String(Math.round(remaining * 10000) / 10000) }) .where(eq(pantryItems.id, pantryItem.id)); } } else { // no numeric quantity to deduct — remove the item entirely await db.delete(pantryItems).where(eq(pantryItems.id, pantryItem.id)); } } } return NextResponse.json({ logged: true }, { status: 201 }); }