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 { db } from '@/lib/db';
import { documents, documentFolders } from '@/lib/db/schema/documents';
import { errorResponse, NotFoundError, ValidationError } from '@/lib/errors';
import { moveDocumentToFolderSchema } from '@/lib/validators/document-folders';
import { createAuditLog } from '@/lib/audit';

/**
 * Per-document move endpoint. Moving a single document is a deliberate
 * user action so we DO bump `updated_at` here - different semantics from
 * the bulk soft-rescue in `deleteFolderSoftRescue` where the timestamp
 * stays put because reps did not act on the individual documents.
 *
 * Validates the destination folder belongs to the same port (cross-port
 * leakage guard) and emits a folder-tagged audit log so the documents
 * inspector can filter on `metadata.type='folder_move'`.
 */
export const PATCH = withAuth(
  withPermission('documents', 'manage_folders', async (req, ctx, params) => {
    try {
      const docId = params.id;
      if (!docId) throw new NotFoundError('Document');
      const body = await parseBody(req, moveDocumentToFolderSchema);

      const existing = await db.query.documents.findFirst({
        where: and(eq(documents.id, docId), eq(documents.portId, ctx.portId)),
      });
      if (!existing) throw new NotFoundError('Document');

      if (body.folderId !== null) {
        const folder = await db.query.documentFolders.findFirst({
          where: and(eq(documentFolders.id, body.folderId), eq(documentFolders.portId, ctx.portId)),
        });
        if (!folder) throw new ValidationError('Invalid folder');
      }

      const [updated] = await db
        .update(documents)
        .set({ folderId: body.folderId, updatedAt: new Date() })
        .where(and(eq(documents.id, docId), eq(documents.portId, ctx.portId)))
        .returning();

      void createAuditLog({
        userId: ctx.userId,
        portId: ctx.portId,
        action: 'update',
        entityType: 'document',
        entityId: docId,
        oldValue: { folderId: existing.folderId },
        newValue: { folderId: body.folderId },
        metadata: { type: 'folder_move' },
        ipAddress: ctx.ipAddress,
        userAgent: ctx.userAgent,
      });

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