import { NextResponse } from "next/server" import { z } from "zod" import { getSessionUser } from "@/lib/session" import { aiConfigured, AI_UNCONFIGURED_ERROR } from "@/lib/ai/client" import { aiComplete } from "@/lib/ai/provider" 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 }) // Before the quota check so an unconfigured server never burns a call. if (!aiConfigured()) return NextResponse.json({ error: AI_UNCONFIGURED_ERROR }, { status: 503 }) 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 text = await aiComplete({ messages: [ { role: "system", content: RENT_RECEIPT_PROMPT }, { role: "user", content: dataBlock("PAYMENT DETAILS", JSON.stringify(receiptFields, null, 2)), }, ], maxTokens: 1024, json: true, }) let receipt try { receipt = JSON.parse(text) } catch { return NextResponse.json({ error: "Failed to parse AI response" }, { status: 500 }) } return NextResponse.json(receipt) }