import { NextRequest, NextResponse } from "next/server"; import { db } from "@/lib/db"; async function validateToken(token: string) { const session = await db.reviewSession.findUnique({ where: { token } }); if (!session || !session.isActive) return null; if (session.expiresAt && session.expiresAt < new Date()) return null; return session; } /** GET /api/client/[token]/versions/[versionId] — returns version + comments for client portal */ export async function GET( req: NextRequest, { params }: { params: Promise<{ token: string; versionId: string }> } ) { const { token, versionId } = await params; const session = await validateToken(token); if (!session) { return NextResponse.json({ error: "Invalid or expired review link" }, { status: 403 }); } const version = await db.version.findUnique({ where: { id: versionId }, include: { shot: { include: { project: { select: { id: true, name: true, code: true } }, versions: { orderBy: { versionNumber: "desc" }, select: { id: true, versionNumber: true, approvalStatus: true, isLatest: true, fps: true, duration: true, createdAt: true, }, }, }, }, task: { include: { project: { select: { id: true, name: true, code: true } }, shot: { select: { shotCode: true } }, asset: { select: { assetCode: true, name: true } }, }, }, artist: { select: { id: true, name: true, image: true, email: true } }, approvals: { orderBy: { createdAt: "desc" }, include: { user: { select: { id: true, name: true } } }, }, }, }); // Resolve project: from shot or from task const projectId = version?.shot?.projectId ?? version?.task?.projectId; if (!version || projectId !== session.projectId) { return NextResponse.json({ error: "Version not found" }, { status: 404 }); } // For task-only versions (no shot), require explicit client sharing if (!version.shot && !version.isClientVisible) { return NextResponse.json({ error: "Version not found" }, { status: 404 }); } const comments = await db.comment.findMany({ where: { versionId }, orderBy: { frameNumber: "asc" }, include: { author: { select: { id: true, name: true, image: true, email: true } }, replies: { orderBy: { createdAt: "asc" }, include: { author: { select: { id: true, name: true, image: true, email: true } }, }, }, }, }); const serializedVersion = { ...version, fileSize: version.fileSize?.toString() ?? null, }; return NextResponse.json({ version: serializedVersion, comments }); }