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

import { withAuth, withPermission } from '@/lib/api/helpers';
import { parseBody } from '@/lib/api/route-helpers';
import { errorResponse, ValidationError } from '@/lib/errors';
import { getStorageBackend } from '@/lib/storage';

const renameFolderSchema = z.object({
  newPath: z.string().min(1).max(500),
});

function sanitizeFolderPath(raw: string): string {
  return raw
    .replace(/\x00/g, '')
    .replace(/\.\.\//g, '')
    .replace(/^\/+/, '')
    .replace(/\/+/g, '/');
}

// Catch-all route: Next.js 15.5+ infers `params: { path: string[] }` and
// enforces the handler signature matches. Pass the explicit type param
// so withAuth/withPermission narrow correctly.
type FolderPathParams = { path: string[] };

export const PATCH = withAuth<FolderPathParams>(
  withPermission<FolderPathParams>('files', 'manage_folders', async (req, ctx, params) => {
    try {
      const currentPath = params.path.join('/');

      const body = await parseBody(req, renameFolderSchema);
      const safeCurrent = sanitizeFolderPath(currentPath);
      const safeNew = sanitizeFolderPath(body.newPath);

      if (!safeCurrent || !safeNew) {
        throw new ValidationError('Invalid folder path');
      }

      const oldKey = `${ctx.portSlug}/${safeCurrent}${safeCurrent.endsWith('/') ? '' : '/'}`;
      const newKey = `${ctx.portSlug}/${safeNew}${safeNew.endsWith('/') ? '' : '/'}`;

      // Create new marker, remove old. Routed through the active backend
      // so filesystem mode doesn't crash.
      const backend = await getStorageBackend();
      await backend.put(newKey, Buffer.alloc(0), {
        contentType: 'application/x-directory',
        sizeBytes: 0,
      });
      await backend.delete(oldKey);

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

export const DELETE = withAuth<FolderPathParams>(
  withPermission<FolderPathParams>('files', 'delete', async (req, ctx, params) => {
    try {
      const currentPath = params.path.join('/');

      const safePath = sanitizeFolderPath(currentPath);
      if (!safePath) {
        throw new ValidationError('Invalid folder path');
      }

      const folderKey = `${ctx.portSlug}/${safePath}${safePath.endsWith('/') ? '' : '/'}`;
      await (await getStorageBackend()).delete(folderKey);

      return new NextResponse(null, { status: 204 });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);
