import type { NextApiRequest, NextApiResponse } from 'next' import { prisma } from '@/lib/prisma' import { requireAuth, logAction } from '@/lib/auth' import { serializeOptions, withParsedFields } from '@/lib/forms' import { FormStatus } from '@/types' export default async function handler(req: NextApiRequest, res: NextApiResponse) { const user = await requireAuth(req, res) if (!user) return const { id } = req.query as { id: string } if (req.method === 'GET') { const form = await prisma.buildForm.findUnique({ where: { id }, include: { fields: { orderBy: { order: 'asc' } }, _count: { select: { submissions: true, fields: true } } }, }) if (!form) return res.status(404).json({ error: 'Not found' }) return res.json({ data: withParsedFields(form) }) } if (req.method === 'PATCH') { if (user.role !== 'ADMIN') return res.status(403).json({ error: 'Admin only' }) const before = await prisma.buildForm.findUnique({ where: { id }, include: { fields: true } }) if (!before) return res.status(404).json({ error: 'Not found' }) const { fields, status, ...rest } = req.body as { fields?: Array<{ id?: string; label: string; type: string; hint?: string; options?: string[]; required?: boolean; trackStd?: boolean }> status?: FormStatus name?: string; product?: string; description?: string; minSubmissions?: number; publishedAt?: string } // ── Full field-level edit (name/product/description/minSubmissions + fields array) ── if (fields !== undefined) { const existingIds = new Set(before.fields.map(f => f.id)) const keepIds = new Set(fields.filter(f => f.id && existingIds.has(f.id)).map(f => f.id as string)) const toDeleteIds = before.fields.filter(f => !keepIds.has(f.id)).map(f => f.id) const ops: any[] = [] if (toDeleteIds.length > 0) { ops.push(prisma.formField.deleteMany({ where: { id: { in: toDeleteIds } } })) } fields.forEach((f, i) => { const data = { label: f.label, type: f.type as any, hint: f.hint || null, options: serializeOptions(f.options), required: !!f.required, trackStd: f.trackStd !== false, order: i, } if (f.id && existingIds.has(f.id)) { ops.push(prisma.formField.update({ where: { id: f.id }, data })) } else { ops.push(prisma.formField.create({ data: { ...data, formId: id } })) } }) const formUpdate: any = {} if (rest.name !== undefined) formUpdate.name = rest.name if (rest.product !== undefined) formUpdate.product = rest.product if (rest.description !== undefined) formUpdate.description = rest.description if (rest.minSubmissions !== undefined) formUpdate.minSubmissions = rest.minSubmissions if (Object.keys(formUpdate).length > 0) { ops.push(prisma.buildForm.update({ where: { id }, data: formUpdate })) } await prisma.$transaction(ops) const updated = await prisma.buildForm.findUnique({ where: { id }, include: { fields: { orderBy: { order: 'asc' } }, _count: { select: { submissions: true, fields: true } } }, }) await logAction(user.id, 'UPDATE', 'BuildForm', id, before, updated) return res.json({ data: withParsedFields(updated) }) } // ── Status transitions (publish / suspend / reactivate / archive / restore) ── const updateData: any = { ...rest } if (status !== undefined) { updateData.status = status if (status === 'ACTIVE' && before.status === 'DRAFT') updateData.publishedAt = new Date() if (status === 'ACTIVE' && before.status === 'SUSPENDED') updateData.suspendedAt = null if (status === 'SUSPENDED') updateData.suspendedAt = new Date() if (status === 'ARCHIVED') updateData.archivedAt = new Date() if (status === 'DRAFT' && before.status === 'ARCHIVED') updateData.archivedAt = null } const updated = await prisma.buildForm.update({ where: { id }, data: updateData, include: { fields: { orderBy: { order: 'asc' } }, _count: { select: { submissions: true, fields: true } } }, }) await logAction(user.id, 'UPDATE', 'BuildForm', id, { status: before.status }, { status: updated.status }) return res.json({ data: withParsedFields(updated) }) } if (req.method === 'DELETE') { if (user.role !== 'ADMIN') return res.status(403).json({ error: 'Admin only' }) await prisma.buildForm.delete({ where: { id } }) await logAction(user.id, 'DELETE', 'BuildForm', id, null, null) return res.json({ ok: true }) } res.status(405).end() }