import { NextRequest, NextResponse } from 'next/server' import { getServerSession } from 'next-auth' import { authOptions } from '@/lib/auth' import { prisma } from '@/lib/prisma' import OpenAI from 'openai' const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }) interface ExtractedTerms { keywords: string[] tribunal?: string area?: string relator?: string dateRange?: { from?: string; to?: string } } export async function POST(req: NextRequest) { const session = await getServerSession(authOptions) if (!session?.user?.id) { return NextResponse.json({ error: 'Não autorizado' }, { status: 401 }) } const body = await req.json() const { query } = body if (!query || typeof query !== 'string') { return NextResponse.json({ error: 'Query é obrigatória' }, { status: 400 }) } // Use OpenAI to extract structured legal search terms const completion = await openai.chat.completions.create({ model: 'gpt-4o-mini', temperature: 0, messages: [ { role: 'system', content: `Você é um assistente jurídico brasileiro especializado em pesquisa de jurisprudência. Dado uma consulta em linguagem natural, extraia termos de busca estruturados. Responda APENAS com JSON válido no formato: { "keywords": ["termo1", "termo2"], "tribunal": "STF" | "STJ" | "TST" | "TRF1" | ... | null, "area": "CIVIL" | "TRABALHISTA" | "PENAL" | "TRIBUTARIO" | "FAMILIA" | "EMPRESARIAL" | "CONSUMIDOR" | "ADMINISTRATIVO" | null, "relator": "nome do relator" | null, "dateRange": { "from": "YYYY-MM-DD", "to": "YYYY-MM-DD" } | null } Extraia o máximo de termos jurídicos relevantes. Inclua sinônimos e termos técnicos. Se o usuário mencionar um tribunal específico, inclua-o. Se mencionar uma área do direito, identifique-a.`, }, { role: 'user', content: query, }, ], }) let extracted: ExtractedTerms try { const raw = completion.choices[0].message.content || '{}' // Strip markdown code fences if present const cleaned = raw.replace(/```json?\n?/g, '').replace(/```/g, '').trim() extracted = JSON.parse(cleaned) } catch { extracted = { keywords: query.split(/\s+/).filter((w) => w.length > 2) } } // Build search queries from extracted keywords // eslint-disable-next-line @typescript-eslint/no-explicit-any const where: any = {} if (extracted.keywords.length > 0) { // Search ementa for any of the keywords where.OR = extracted.keywords.map((kw) => ({ ementa: { contains: kw, mode: 'insensitive' }, })) } if (extracted.tribunal) { where.tribunal = extracted.tribunal } if (extracted.area) { where.area = extracted.area } if (extracted.relator) { where.relator = { contains: extracted.relator, mode: 'insensitive' } } if (extracted.dateRange) { if (extracted.dateRange.from) { where.data = { ...(where.data || {}), gte: extracted.dateRange.from } } if (extracted.dateRange.to) { where.data = { ...(where.data || {}), lte: extracted.dateRange.to } } } const [total, results] = await Promise.all([ prisma.jurisprudencia.count({ where }), prisma.jurisprudencia.findMany({ where, orderBy: { data: 'desc' }, take: 20, }), ]) return NextResponse.json({ results, total, extractedTerms: extracted, aiQuery: query, }) }