import { NextRequest, NextResponse } from 'next/server' import { auth } from '@/auth' import prisma from '@/lib/prisma' import { getAISettings } from '@/app/actions/ai-settings' import { reserveUsageOrThrow, QuotaExceededError } from '@/lib/entitlements' import { hasUserAiConsent } from '@/lib/consent/server-consent' import { generateFlashcardsFromNote, type FlashcardStyle } from '@/lib/flashcards/generate-flashcards' import { stripHtmlToText } from '@/lib/flashcards/deck-utils' export async function POST(request: NextRequest) { try { const session = await auth() if (!session?.user?.id) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } if (!(await hasUserAiConsent())) { return NextResponse.json({ error: 'ai_consent_required' }, { status: 403 }) } const userSettings = await getAISettings(session.user.id) if (userSettings.paragraphRefactor === false) { return NextResponse.json({ error: 'Feature disabled' }, { status: 403 }) } const body = await request.json() const noteId = typeof body.noteId === 'string' ? body.noteId : '' const count = typeof body.count === 'number' ? body.count : 10 const styleRaw = typeof body.style === 'string' ? body.style : 'qa' const style: FlashcardStyle = ['qa', 'cloze', 'concept'].includes(styleRaw) ? (styleRaw as FlashcardStyle) : 'qa' if (!noteId) { return NextResponse.json({ error: 'noteId required' }, { status: 400 }) } const note = await prisma.note.findFirst({ where: { id: noteId, userId: session.user.id, trashedAt: null }, select: { id: true, title: true, content: true, language: true }, }) if (!note) { return NextResponse.json({ error: 'Note not found' }, { status: 404 }) } const textContent = stripHtmlToText(note.content) if (textContent.length < 80) { return NextResponse.json({ error: 'Not enough content to generate flashcards' }, { status: 400 }) } try { await reserveUsageOrThrow(session.user.id, 'ai_flashcard') } catch (err) { if (err instanceof QuotaExceededError) { const isTierLocked = err.currentQuota === 0 return NextResponse.json({ error: isTierLocked ? 'feature_locked' : 'quota_exceeded', errorKey: isTierLocked ? 'ai.featureLocked' : 'ai.quotaExceeded', quotaExceeded: true, }, { status: 402 }) } throw err } const cards = await generateFlashcardsFromNote({ title: note.title || 'Untitled', textContent, count, style, language: note.language || undefined, }) return NextResponse.json({ cards, noteId: note.id, style }) } catch (error) { console.error('[flashcards/generate]', error) const message = error instanceof Error ? error.message : 'Generation failed' return NextResponse.json({ error: message }, { status: 500 }) } }