import { NextResponse } from 'next/server';
import { z } from 'zod';

import { withAuth, withPermission } from '@/lib/api/helpers';
import { parseBody } from '@/lib/api/route-helpers';
import { errorResponse } from '@/lib/errors';
import { cancelDocument } from '@/lib/services/documents.service';

const cancelBodySchema = z
  .object({
    reason: z.string().max(2000).optional().nullable(),
    notifyRecipients: z.array(z.string().uuid()).max(20).optional(),
    /**
     * Whether to also DELETE the document from Documenso. `delete` (the
     * default) frees the upstream envelope slot - useful for unclogging
     * the Documenso log when a draft was abandoned. `keep_remote`
     * leaves the envelope intact for audit purposes; only the local
     * row is marked `cancelled`. Audit-trail copy on the cancelled-doc
     * badge changes accordingly.
     */
    cancelMode: z.enum(['delete', 'keep_remote']).optional(),
  })
  .strict()
  .optional();

export const POST = withAuth(
  withPermission('documents', 'edit', async (req, ctx, params) => {
    try {
      // Body is optional - legacy callers POST with `{}`. parseBody returns
      // null when the request has no body; default to empty options.
      let body: z.infer<typeof cancelBodySchema> = undefined;
      try {
        body = await parseBody(req, cancelBodySchema);
      } catch {
        body = undefined;
      }
      const doc = await cancelDocument(
        params.id!,
        ctx.portId,
        {
          userId: ctx.userId,
          portId: ctx.portId,
          ipAddress: ctx.ipAddress,
          userAgent: ctx.userAgent,
        },
        {
          reason: body?.reason ?? null,
          notifyRecipients: body?.notifyRecipients ?? [],
          cancelMode: body?.cancelMode ?? 'delete',
        },
      );
      return NextResponse.json({ data: doc });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);
