import { NextResponse } from "next/server" import { auth } from "@/lib/auth" import { prisma } from "@/lib/prisma" import { decrypt } from "@/lib/encryption" import { createProvider } from "@/lib/ai/provider-factory" import { rateLimit } from "@/lib/rate-limit" import { z } from "zod" import type { Prisma } from "@prisma/client" const searchSchema = z.object({ query: z.string().min(1).max(200), }) export async function POST(request: Request) { const session = await auth() if (!session?.user?.id) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }) } // Rate limit: 20 searches per minute const { success: withinLimit } = rateLimit(`ai-search:${session.user.id}`, 20, 60 * 1000) if (!withinLimit) { return NextResponse.json( { error: "Too many requests. Please wait a moment." }, { status: 429 } ) } try { const body = await request.json() const parsed = searchSchema.safeParse(body) if (!parsed.success) { return NextResponse.json({ error: "Invalid query" }, { status: 400 }) } // Get user's AI provider const apiKeyRecord = await prisma.userApiKey.findFirst({ where: { userId: session.user.id, isActive: true }, }) if (!apiKeyRecord) { return NextResponse.json( { error: "No AI provider configured. Add an API key in Settings." }, { status: 400 } ) } // Check cache first (24hr TTL) const queryHash = parsed.data.query.toLowerCase().trim() const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000) const cached = await prisma.searchCache.findUnique({ where: { userId_queryHash_provider: { userId: session.user.id, queryHash, provider: apiKeyRecord.provider, }, }, }) if (cached && cached.createdAt > twentyFourHoursAgo) { return NextResponse.json(cached.results) } const apiKey = decrypt(apiKeyRecord.encryptedKey, apiKeyRecord.iv) const provider = createProvider(apiKeyRecord.provider, apiKey) const result = await provider.searchDrinks(parsed.data.query) // Cache the result await prisma.searchCache.upsert({ where: { userId_queryHash_provider: { userId: session.user.id, queryHash, provider: apiKeyRecord.provider, }, }, update: { query: parsed.data.query, results: { drinks: result.drinks } as unknown as Prisma.InputJsonValue, createdAt: new Date(), }, create: { userId: session.user.id, queryHash, query: parsed.data.query, results: { drinks: result.drinks } as unknown as Prisma.InputJsonValue, provider: apiKeyRecord.provider, }, }) return NextResponse.json({ drinks: result.drinks }) } catch (error) { console.error("AI search error:", error) return NextResponse.json( { error: "Search failed. Please try again." }, { status: 500 } ) } }