import { NextResponse } from "next/server" import { z } from "zod" import { getSessionUser } from "@/lib/session" import { openai } from "@/lib/ai/client" import { RENT_RECEIPT_PROMPT, dataBlock } from "@/lib/ai/prompts" import { enforceAiQuota } from "@/lib/ai/usage" // Whitelist only the fields the receipt needs. Never pass the raw request body // into the prompt — tenant-controlled strings must not become instructions. const ReceiptInput = z.object({ payment_id: z.string().optional(), amount: z.number().optional(), tenant_name: z.string().max(200).optional(), property_name: z.string().max(200).optional(), property_address: z.string().max(300).optional(), unit_number: z.string().max(50).optional(), landlord_name: z.string().max(200).optional(), payment_method: z.string().max(100).optional(), due_date: z.string().max(50).optional(), paid_date: z.string().max(50).optional(), period: z.string().max(100).optional(), }) export async function POST(request: Request) { const user = await getSessionUser() if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 }) const quota = await enforceAiQuota(user.id, "ai_rent_receipt") if (!quota.ok) return NextResponse.json({ error: quota.error }, { status: quota.status }) const parsed = ReceiptInput.safeParse(await request.json()) if (!parsed.success) { return NextResponse.json({ error: "Invalid payment details" }, { status: 400 }) } // Pass only the whitelisted, validated fields to the model. const { payment_id, ...receiptFields } = parsed.data const completion = await openai.chat.completions.create({ model: "gpt-4o-mini", max_tokens: 1024, messages: [ { role: "system", content: RENT_RECEIPT_PROMPT }, { role: "user", content: dataBlock("PAYMENT DETAILS", JSON.stringify(receiptFields, null, 2)), }, ], }) const text = completion.choices[0].message.content ?? "" let receipt try { receipt = JSON.parse(text.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim()) } catch { return NextResponse.json({ error: "Failed to parse AI response" }, { status: 500 }) } return NextResponse.json(receipt) }