import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; import { db, mealPlans, mealPlanEntries, eq, and } from "@epicure/db"; import { requireSession } from "@/lib/api-auth"; import { dispatchWebhook } from "@/lib/webhooks"; type Params = { params: Promise<{ weekStart: string }> }; const Schema = z.object({ day: z.enum(["mon", "tue", "wed", "thu", "fri", "sat", "sun"]), mealType: z.enum(["breakfast", "lunch", "dinner", "snack"]), recipeId: z.string().optional(), servings: z.number().int().min(1).max(100).default(2), note: z.string().max(500).optional(), }); async function getOrCreatePlan(userId: string, weekStart: string) { const existing = await db.query.mealPlans.findFirst({ where: and(eq(mealPlans.userId, userId), eq(mealPlans.weekStart, weekStart)), }); if (existing) return existing; const id = crypto.randomUUID(); await db.insert(mealPlans).values({ id, userId, weekStart }); return { id, userId, weekStart }; } export async function POST(req: NextRequest, { params }: Params) { const { session, response } = await requireSession(); if (response) return response; const { weekStart } = await params; const body = await req.json() as unknown; const parsed = Schema.safeParse(body); if (!parsed.success) return NextResponse.json({ error: "Validation error" }, { status: 400 }); const plan = await getOrCreatePlan(session!.user.id, weekStart); // Remove existing entry for same day+mealType before inserting await db.delete(mealPlanEntries).where( and( eq(mealPlanEntries.mealPlanId, plan.id), eq(mealPlanEntries.day, parsed.data.day), eq(mealPlanEntries.mealType, parsed.data.mealType) ) ); const entryId = crypto.randomUUID(); await db.insert(mealPlanEntries).values({ id: entryId, mealPlanId: plan.id, day: parsed.data.day, mealType: parsed.data.mealType, recipeId: parsed.data.recipeId, servings: parsed.data.servings, note: parsed.data.note, }); void dispatchWebhook(session!.user.id, "meal_plan.updated", { weekStart, day: parsed.data.day, mealType: parsed.data.mealType }); return NextResponse.json({ id: entryId }, { status: 201 }); }