import { NextResponse } from "next/server"; import { db } from "@/db"; import { quizSessions } from "@/db/schema"; import { eq, and, desc } from "drizzle-orm"; import { getSession } from "@/lib/auth"; import { WARMUP_PARAGRAPHS } from "@/lib/warmup-paragraphs"; /** * Warmup progress is keyed by the auth session's createdAt timestamp. * This means warmup resets every time the user logs in (new session), * while the quiz pass is permanent. */ interface WarmupProgressMap { [sessionKey: string]: number; } function getWarmupCompleted( answersJson: string, sessionKey: string, ): number { try { const parsed = JSON.parse(answersJson); if (parsed && typeof parsed === "object" && "warmupBySession" in parsed) { return (parsed.warmupBySession as WarmupProgressMap)[sessionKey] ?? 0; } // Legacy format: single warmupCompleted if (parsed && typeof parsed === "object" && "warmupCompleted" in parsed) { return 0; // Reset legacy progress — they need to redo warmup } return 0; } catch { return 0; } } async function getPassedQuizSession(annotatorId: string) { const [session] = await db .select() .from(quizSessions) .where( and( eq(quizSessions.annotatorId, annotatorId), eq(quizSessions.passed, true), ), ) .orderBy(desc(quizSessions.startedAt)) .limit(1); return session ?? null; } export async function GET() { const session = await getSession(); if (!session) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const quizSession = await getPassedQuizSession(session.annotatorId); if (!quizSession) { return NextResponse.json( { error: "Quiz not passed" }, { status: 403 }, ); } const sessionKey = String(session.createdAt); const warmupCompleted = getWarmupCompleted(quizSession.answers, sessionKey); if (warmupCompleted >= WARMUP_PARAGRAPHS.length) { return NextResponse.json({ done: true, warmupCompleted }); } const next = WARMUP_PARAGRAPHS[warmupCompleted]; return NextResponse.json({ done: false, warmupCompleted, paragraph: { id: next.id, text: next.text, index: warmupCompleted, total: WARMUP_PARAGRAPHS.length, }, }); } export async function POST(request: Request) { const session = await getSession(); if (!session) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const quizSession = await getPassedQuizSession(session.annotatorId); if (!quizSession) { return NextResponse.json( { error: "Quiz not passed" }, { status: 403 }, ); } const body = await request.json(); const { category, specificity, warmupIndex } = body as { category?: string; specificity?: number; warmupIndex?: number; }; if (!category || !specificity || warmupIndex === undefined) { return NextResponse.json( { error: "Missing required fields: category, specificity, warmupIndex" }, { status: 400 }, ); } const sessionKey = String(session.createdAt); const warmupCompleted = getWarmupCompleted(quizSession.answers, sessionKey); if (warmupIndex !== warmupCompleted) { return NextResponse.json( { error: "Warmup index mismatch" }, { status: 400 }, ); } if (warmupIndex >= WARMUP_PARAGRAPHS.length) { return NextResponse.json( { error: "Warmup already complete" }, { status: 400 }, ); } const gold = WARMUP_PARAGRAPHS[warmupIndex]; const newCompleted = warmupIndex + 1; const categoryCorrect = category === gold.goldCategory; const specificityCorrect = specificity === gold.goldSpecificity; // Store warmup progress keyed by auth session let existingData: Record; try { const parsed = JSON.parse(quizSession.answers); if (Array.isArray(parsed)) { existingData = { quizAnswers: parsed }; } else { existingData = parsed; } } catch { existingData = {}; } const warmupBySession = (existingData.warmupBySession as WarmupProgressMap) ?? {}; warmupBySession[sessionKey] = newCompleted; await db .update(quizSessions) .set({ answers: JSON.stringify({ ...existingData, warmupBySession, }), }) .where(eq(quizSessions.id, quizSession.id)); return NextResponse.json({ categoryCorrect, specificityCorrect, goldCategory: gold.goldCategory, goldSpecificity: gold.goldSpecificity, explanation: gold.explanation, warmupCompleted: newCompleted, done: newCompleted >= WARMUP_PARAGRAPHS.length, }); }