import { NextResponse } from 'next/server';

import { withAuth, withPermission } from '@/lib/api/helpers';
import { errorResponse, ValidationError } from '@/lib/errors';
import { uploadFile } from '@/lib/services/files';
import { uploadFileSchema } from '@/lib/validators/files';

export const POST = withAuth(
  withPermission('files', 'upload', async (req, ctx) => {
    try {
      const formData = await req.formData();
      const file = formData.get('file') as File | null;

      if (!file) {
        throw new ValidationError('No file provided');
      }

      const buffer = Buffer.from(await file.arrayBuffer());

      // A16: FormData.get returns null when the field is absent, not
      // undefined. Zod's .optional() accepts undefined but rejects null,
      // so the previous `as string | undefined` cast lied and uploads at
      // the hub root (no entity selected) 400'd. Coerce absent / empty
      // values to undefined before parse.
      const formStr = (key: string): string | undefined => {
        const v = formData.get(key);
        return typeof v === 'string' && v.length > 0 ? v : undefined;
      };
      const metadata = uploadFileSchema.parse({
        filename: formStr('filename') ?? file.name,
        clientId: formStr('clientId'),
        yachtId: formStr('yachtId'),
        companyId: formStr('companyId'),
        category: formStr('category'),
        entityType: formStr('entityType'),
        entityId: formStr('entityId'),
        folderId: formStr('folderId'),
      });

      const result = await uploadFile(
        ctx.portId,
        ctx.portSlug,
        {
          buffer,
          originalName: file.name,
          mimeType: file.type,
          size: file.size,
        },
        metadata,
        {
          userId: ctx.userId,
          portId: ctx.portId,
          ipAddress: ctx.ipAddress,
          userAgent: ctx.userAgent,
        },
      );

      return NextResponse.json({ data: result }, { status: 201 });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);
