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,
  endTenancy,
  getById,
  updateTenancy,
} from '@/lib/services/berth-tenancies.service';
import { assertTenanciesModuleEnabled } from '@/lib/services/tenancies-module.service';
import { TENURE_TYPES } from '@/lib/validators/tenancies';

// ─── 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(),
  }),
  z.object({
    action: z.literal('update'),
    startDate: z.coerce.date().optional(),
    endDate: z.coerce.date().nullable().optional(),
    tenureType: z.enum(TENURE_TYPES).optional(),
    notes: z.string().nullable().optional(),
  }),
]);

// ─── Handlers ────────────────────────────────────────────────────────────────

export const getHandler: RouteHandler = async (_req, ctx, params) => {
  try {
    await assertTenanciesModuleEnabled(ctx.portId);
    const tenancy = await getById(params.id!, ctx.portId);
    return NextResponse.json({ data: tenancy });
  } catch (error) {
    return errorResponse(error);
  }
};

export const patchHandler: RouteHandler = async (req, ctx, params) => {
  try {
    await assertTenanciesModuleEnabled(ctx.portId);
    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, 'tenancies', 'manage');
      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, 'tenancies', 'manage');
      const result = await endTenancy(
        params.id!,
        ctx.portId,
        { endDate: body.endDate, notes: body.notes },
        meta,
      );
      return NextResponse.json({ data: result });
    }

    if (body.action === 'update') {
      requirePermission(ctx, 'tenancies', 'manage');
      const result = await updateTenancy(
        params.id!,
        ctx.portId,
        {
          startDate: body.startDate,
          endDate: body.endDate,
          tenureType: body.tenureType,
          notes: body.notes,
        },
        meta,
      );
      return NextResponse.json({ data: result });
    }

    // action === 'cancel'
    requirePermission(ctx, 'tenancies', '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 assertTenanciesModuleEnabled(ctx.portId);
    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);
  }
};
