import { NextResponse } from 'next/server';
import { withErrorHandler } from '@server/middleware/withErrorHandler';
import { withAuth, AuthedRequest } from '@server/middleware/withAuth';
import { ForbiddenError } from '@server/errors';
import { randomUUID } from 'crypto';
import { uploadFile } from '@server/services/storage.service';

const ALLOWED_TYPES: Record<string, { ext: string; signature: number[] }> = {
  'image/png':  { ext: 'png',  signature: [0x89, 0x50, 0x4E, 0x47] },
  'image/jpeg': { ext: 'jpg',  signature: [0xFF, 0xD8, 0xFF] },
  'image/gif':  { ext: 'gif',  signature: [0x47, 0x49, 0x46, 0x38] },
  'image/webp': { ext: 'webp', signature: [0x52, 0x49, 0x46, 0x46] },
};
const MAX_SIZE = 2 * 1024 * 1024;
const VALID_TYPES = ['logo', 'favicon'] as const;
type UploadType = typeof VALID_TYPES[number];

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

export const POST = withErrorHandler(
  withAuth(async (req: AuthedRequest) => {
    if (req.session.role !== 'superadmin' && req.session.role !== 'support') {
      throw new ForbiddenError();
    }

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

    const typeParam = formData.get('type');
    if (!typeParam || !VALID_TYPES.includes(typeParam as UploadType)) {
      return NextResponse.json({ error: 'type must be "logo" or "favicon"' }, { status: 400 });
    }
    const uploadType = typeParam as UploadType;

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

    const mimeType = file.type;
    if (!ALLOWED_TYPES[mimeType]) {
      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 ext = ALLOWED_TYPES[mimeType].ext;
    const filename = `${uploadType}-${randomUUID()}.${ext}`;
    const url = await uploadFile(buf, filename, 'platform', mimeType);

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