import { NextResponse } from "next/server" import { auth } from "@/lib/auth" import { prisma } from "@/lib/prisma" import { getUserProvider } from "@/lib/ai/provider-factory" import { FEATURE_ROUTING } from "@/lib/ai/routing" import { aiErrorResponse } from "@/lib/ai/errors" import { rateLimit } from "@/lib/rate-limit" import { WHAT_CAN_I_MAKE_PROMPT, buildBarInventoryString } from "@/lib/ai/prompts" import { fuzzyMatchIngredients, recalculateMissingCount } from "@/lib/ingredient-matcher" export async function POST() { const session = await auth() if (!session?.user?.id) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }) } const { success: withinLimit } = rateLimit(`bartender-suggest:${session.user.id}`, 5, 60000) if (!withinLimit) { return NextResponse.json( { error: "Too many requests. Please wait a moment." }, { status: 429 } ) } try { const barItems = await prisma.barItem.findMany({ where: { userId: session.user.id, quantity: { not: "EMPTY" }, }, select: { name: true, category: true, quantity: true }, }) if (barItems.length === 0) { return NextResponse.json( { error: "No items in your bar inventory. Add items to your bar first." }, { status: 400 } ) } const inventoryString = buildBarInventoryString(barItems) const prompt = WHAT_CAN_I_MAKE_PROMPT.replace("{barInventory}", inventoryString) const provider = await getUserProvider(session.user.id) const rawResponse = await provider.sendTextRequest( prompt, "What cocktails can I make with my bar inventory?", FEATURE_ROUTING.bartenderSuggest ) // Parse JSON from response let suggestions try { suggestions = JSON.parse(rawResponse) } catch { const codeBlockMatch = rawResponse.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/) if (codeBlockMatch) { suggestions = JSON.parse(codeBlockMatch[1].trim()) } else { const arrayMatch = rawResponse.match(/\[[\s\S]*\]/) if (arrayMatch) { suggestions = JSON.parse(arrayMatch[0]) } else { throw new Error("Could not parse suggestions from AI response") } } } if (!Array.isArray(suggestions)) { suggestions = [] } // Post-process: fuzzy-match ingredients against bar inventory and re-sort if (barItems.length > 0) { suggestions = suggestions.map((s: { ingredients?: { name: string; amount: string; available: boolean }[]; missingCount?: number }) => { if (s.ingredients && Array.isArray(s.ingredients)) { s.ingredients = fuzzyMatchIngredients(s.ingredients, barItems) s.missingCount = recalculateMissingCount(s.ingredients) } return s }) // Re-sort by missingCount ascending suggestions.sort((a: { missingCount?: number }, b: { missingCount?: number }) => (a.missingCount ?? 99) - (b.missingCount ?? 99) ) } return NextResponse.json({ suggestions }) } catch (error) { return aiErrorResponse(error, "Failed to generate suggestions. Please try again.") } }