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

import { withAuth, withPermission } from '@/lib/api/helpers';
import { parseBody } from '@/lib/api/route-helpers';
import { updateWaitingListSchema } from '@/lib/validators/berths';
import { reorderWaitingListSchema } from '@/lib/validators/interests';
import { getWaitingList, updateWaitingList } from '@/lib/services/berths.service';
import { errorResponse, NotFoundError } from '@/lib/errors';
import { db } from '@/lib/db';
import { berths, berthWaitingList } from '@/lib/db/schema/berths';

// GET /api/v1/berths/[id]/waiting-list
export const GET = withAuth(
  withPermission('berths', 'view', async (req, ctx, params) => {
    try {
      const entries = await getWaitingList(params.id!, ctx.portId);
      return NextResponse.json({ data: entries });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);

// PUT /api/v1/berths/[id]/waiting-list
export const PUT = withAuth(
  withPermission('berths', 'manage_waiting_list', async (req, ctx, params) => {
    try {
      const body = await parseBody(req, updateWaitingListSchema);
      const entries = await updateWaitingList(params.id!, ctx.portId, body, {
        userId: ctx.userId,
        portId: ctx.portId,
        ipAddress: ctx.ipAddress,
        userAgent: ctx.userAgent,
      });
      return NextResponse.json({ data: entries });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);

// PATCH /api/v1/berths/[id]/waiting-list - reorder a single entry
export const PATCH = withAuth(
  withPermission('berths', 'manage_waiting_list', async (req, ctx, params) => {
    try {
      const body = await parseBody(req, reorderWaitingListSchema);
      const berthId = params.id!;

      // Tenant scope: refuse to reorder a foreign-port berth's waiting
      // list. The route's URL id and the entry id are otherwise enough
      // for any user with manage_waiting_list to mutate any tenant's
      // queue ordering.
      const berthRow = await db.query.berths.findFirst({
        where: and(eq(berths.id, berthId), eq(berths.portId, ctx.portId)),
      });
      if (!berthRow) throw new NotFoundError('Berth');

      const entry = await db.query.berthWaitingList.findFirst({
        where: and(eq(berthWaitingList.id, body.entryId), eq(berthWaitingList.berthId, berthId)),
      });
      if (!entry) throw new NotFoundError('Waiting list entry');

      if (entry.position !== body.newPosition) {
        // Fetch all entries sorted by position
        const allEntries = await db
          .select()
          .from(berthWaitingList)
          .where(eq(berthWaitingList.berthId, berthId))
          .orderBy(berthWaitingList.position);

        // Remove the moved entry then insert at newPosition (1-indexed)
        const others = allEntries.filter((e) => e.id !== body.entryId);
        others.splice(body.newPosition - 1, 0, entry);

        // Update all positions in sequence
        for (let i = 0; i < others.length; i++) {
          await db
            .update(berthWaitingList)
            .set({ position: i + 1 })
            .where(eq(berthWaitingList.id, others[i]!.id));
        }
      }

      const entries = await db
        .select()
        .from(berthWaitingList)
        .where(eq(berthWaitingList.berthId, berthId))
        .orderBy(berthWaitingList.position);

      return NextResponse.json({ data: entries });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);
