import { NextResponse } from 'next/server'; import { z } from 'zod'; import { type RouteHandler } from '@/lib/api/helpers'; import { parseBody } from '@/lib/api/route-helpers'; import { requirePermission } from '@/lib/auth/permissions'; import { errorResponse } from '@/lib/errors'; import { activate, cancel, endReservation, getById, } from '@/lib/services/berth-reservations.service'; // ─── PATCH body schema (action-based discriminated union) ──────────────────── const patchBodySchema = z.discriminatedUnion('action', [ z.object({ action: z.literal('activate'), contractFileId: z.string().optional(), effectiveDate: z.coerce.date().optional(), }), z.object({ action: z.literal('end'), endDate: z.coerce.date(), notes: z.string().optional(), }), z.object({ action: z.literal('cancel'), reason: z.string().optional(), }), ]); // ─── Handlers ──────────────────────────────────────────────────────────────── export const getHandler: RouteHandler = async (_req, ctx, params) => { try { const reservation = await getById(params.id!, ctx.portId); return NextResponse.json({ data: reservation }); } catch (error) { return errorResponse(error); } }; export const patchHandler: RouteHandler = async (req, ctx, params) => { try { const body = await parseBody(req, patchBodySchema); const meta = { userId: ctx.userId, portId: ctx.portId, ipAddress: ctx.ipAddress, userAgent: ctx.userAgent, }; if (body.action === 'activate') { requirePermission(ctx, 'reservations', 'activate'); const result = await activate( params.id!, ctx.portId, { contractFileId: body.contractFileId, effectiveDate: body.effectiveDate, }, meta, ); return NextResponse.json({ data: result }); } if (body.action === 'end') { // `end` is lifecycle progression; same privilege as activate. requirePermission(ctx, 'reservations', 'activate'); const result = await endReservation( params.id!, ctx.portId, { endDate: body.endDate, notes: body.notes }, meta, ); return NextResponse.json({ data: result }); } // action === 'cancel' requirePermission(ctx, 'reservations', 'cancel'); const result = await cancel(params.id!, ctx.portId, { reason: body.reason }, meta); return NextResponse.json({ data: result }); } catch (error) { return errorResponse(error); } }; export const deleteHandler: RouteHandler = async (_req, ctx, params) => { try { await cancel( params.id!, ctx.portId, {}, { userId: ctx.userId, portId: ctx.portId, ipAddress: ctx.ipAddress, userAgent: ctx.userAgent, }, ); return new NextResponse(null, { status: 204 }); } catch (error) { return errorResponse(error); } };