import { and, eq } from 'drizzle-orm';
import { NextResponse } from 'next/server';

import { type RouteHandler } from '@/lib/api/helpers';
import { parseBody, parseQuery } from '@/lib/api/route-helpers';
import { db } from '@/lib/db';
import { berths } from '@/lib/db/schema/berths';
import { NotFoundError, errorResponse } from '@/lib/errors';
import { createPending, listTenancies } from '@/lib/services/berth-tenancies.service';
import { assertTenanciesModuleEnabled } from '@/lib/services/tenancies-module.service';
import { createPendingSchema, listTenanciesSchema } from '@/lib/validators/tenancies';

// URL berthId is authoritative; make body berthId optional (ignored anyway).
const createPendingBodySchema = createPendingSchema
  .omit({ berthId: true })
  .extend({ berthId: createPendingSchema.shape.berthId.optional() });

async function assertBerthInPort(berthId: string, portId: string): Promise<void> {
  const berth = await db.query.berths.findFirst({
    where: and(eq(berths.id, berthId), eq(berths.portId, portId)),
  });
  if (!berth) throw new NotFoundError('Berth');
}

export const listHandler: RouteHandler = async (req, ctx, params) => {
  try {
    await assertTenanciesModuleEnabled(ctx.portId);
    await assertBerthInPort(params.id!, ctx.portId);
    const query = parseQuery(req, listTenanciesSchema);
    const result = await listTenancies(ctx.portId, { ...query, berthId: params.id! });
    const { page, limit } = query;
    const totalPages = Math.ceil(result.total / limit);
    return NextResponse.json({
      data: result.data,
      pagination: {
        page,
        pageSize: limit,
        total: result.total,
        totalPages,
        hasNextPage: page < totalPages,
        hasPreviousPage: page > 1,
      },
    });
  } catch (error) {
    return errorResponse(error);
  }
};

export const createHandler: RouteHandler = async (req, ctx, params) => {
  try {
    await assertTenanciesModuleEnabled(ctx.portId);
    await assertBerthInPort(params.id!, ctx.portId);
    const body = await parseBody(req, createPendingBodySchema);
    const tenancy = await createPending(
      ctx.portId,
      { ...body, berthId: params.id! },
      {
        userId: ctx.userId,
        portId: ctx.portId,
        ipAddress: ctx.ipAddress,
        userAgent: ctx.userAgent,
      },
    );
    return NextResponse.json({ data: tenancy }, { status: 201 });
  } catch (error) {
    return errorResponse(error);
  }
};
