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

import { withAuth, withPermission, 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);
  }
};

export const GET = withAuth(withPermission('reservations', 'view', getHandler));
// PATCH cannot use `withPermission` wrapper — the required permission depends
// on the `action` field in the body. `requirePermission` is called inside the
// handler after the body is parsed.
export const PATCH = withAuth(patchHandler);
export const DELETE = withAuth(withPermission('reservations', 'cancel', deleteHandler));
