import { NextRequest, NextResponse } from 'next/server'; import { getStoredAssembledQuotationPdf } from '@/features/foundation/document-assembly/server/service'; import { auditCrmSecurityEvent, buildCrmSecurityContext, canViewQuotationPricing, } from '@/features/crm/security/server/service'; import { PERMISSIONS } from '@/lib/auth/rbac'; import { AuthError, requireOrganizationAccess } from '@/lib/auth/session'; type Params = { params: Promise<{ id: string }> }; export async function GET(_request: NextRequest, { params }: Params) { try { const { id } = await params; const { organization, session, membership } = await requireOrganizationAccess( { permission: PERMISSIONS.crmQuotationPdfPreview }, ); const securityContext = buildCrmSecurityContext({ organizationId: organization.id, userId: session.user.id, membership, }); if (!canViewQuotationPricing(securityContext)) { await auditCrmSecurityEvent({ organizationId: organization.id, userId: session.user.id, action: 'pricing_hidden', entityType: 'crm_quotation', entityId: id, reason: 'Assembled quotation PDF preview requires pricing visibility', }); return NextResponse.json({ message: 'Forbidden' }, { status: 403 }); } const pdf = await getStoredAssembledQuotationPdf(id, organization.id, { userId: session.user.id, }); return new NextResponse(pdf.buffer, { headers: { 'Content-Type': 'application/pdf', 'Content-Disposition': `inline; filename="${pdf.fileName}"`, }, }); } catch (error) { if (error instanceof AuthError) { return NextResponse.json({ message: error.message }, { status: error.status }); } return NextResponse.json( { message: 'Unable to load assembled quotation PDF' }, { status: 500 }, ); } }