import { NextResponse } from 'next/server';
import { withErrorHandler } from '@server/middleware/withErrorHandler';
import { withAuth, AuthedRequest } from '@server/middleware/withAuth';
import { db, restaurants } from '@server/db/drizzle';
import { eq, sql } from 'drizzle-orm';
import { randomUUID } from 'crypto';
import { uploadFile } from '@server/services/storage.service';

const MAGIC_BYTES: Record<string, { ext: string; signatures: number[][] }> = {
  'image/png': { ext: 'png', signatures: [[0x89, 0x50, 0x4E, 0x47]] },
  'image/jpeg': { ext: 'jpg', signatures: [[0xFF, 0xD8, 0xFF]] },
  'image/gif': { ext: 'gif', signatures: [[0x47, 0x49, 0x46, 0x38]] },
  'image/webp': { ext: 'webp', signatures: [[0x52, 0x49, 0x46, 0x46]] },
};
const MAX_SIZE = 2 * 1024 * 1024;

function validateMagicBytes(buffer: Buffer, mime: string): boolean {
  const entry = MAGIC_BYTES[mime];
  if (!entry) return false;
  return entry.signatures.some(sig =>
    sig.every((byte, i) => buffer[i] === byte)
  );
}

export const POST = withErrorHandler(
  withAuth(async (req: AuthedRequest) => {
    const { restaurantId } = req.session;
    if (!restaurantId) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    const formData = await req.formData().catch(() => null);
    if (!formData) {
      return NextResponse.json({ error: 'Invalid form data' }, { status: 400 });
    }

    const file = formData.get('file');
    if (!file || typeof file === 'string') {
      return NextResponse.json({ error: 'No file uploaded' }, { status: 400 });
    }

    const mimeType = file.type;
    const entry = MAGIC_BYTES[mimeType];
    if (!entry) {
      return NextResponse.json(
        { error: 'Unsupported file type. Allowed: PNG, JPEG, GIF, WEBP' },
        { status: 400 }
      );
    }

    const arrayBuffer = await file.arrayBuffer();
    if (arrayBuffer.byteLength > MAX_SIZE) {
      return NextResponse.json({ error: 'File too large. Maximum size is 2 MB' }, { status: 400 });
    }

    const buf = Buffer.from(arrayBuffer);
    if (!validateMagicBytes(buf, mimeType)) {
      return NextResponse.json({ error: 'File content does not match declared type' }, { status: 400 });
    }

    const filename = `${randomUUID()}.${entry.ext}`;
    const url = await uploadFile(buf, filename, 'restaurant-logos', mimeType);

    await db.update(restaurants)
      .set({ logoUrl: url, updatedAt: sql`NOW()` })
      .where(eq(restaurants.id, restaurantId));

    return NextResponse.json({ url });
  })
);
