import { NextRequest, NextResponse } from 'next/server';
import { writeFile, mkdir } from 'fs/promises';
import { join, extname } from 'path';

// Allowed MIME types per category
const ALLOWED_TYPES: Record<string, string[]> = {
  image: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
  video: ['video/mp4', 'video/webm'],
  audio: ['audio/mpeg', 'audio/webm', 'audio/ogg'],
  document: [
    'application/pdf',
    'application/msword',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  ],
};

// Max file sizes in bytes
const MAX_SIZES: Record<string, number> = {
  image: 10 * 1024 * 1024,   // 10MB
  video: 10 * 1024 * 1024,   // 10MB
  audio: 10 * 1024 * 1024,   // 10MB
  document: 5 * 1024 * 1024, // 5MB
};

// Map upload `type` parameter to a file category
function getCategory(type: string): string | null {
  if (type === 'avatar' || type === 'message') return 'image';
  if (type === 'voice') return 'audio';
  if (type === 'document') return 'document';
  // Allow direct category names too
  if (['image', 'video', 'audio', 'document'].includes(type)) return type;
  return null;
}

// Generate a random alphanumeric string
function randomString(length = 6): string {
  const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
  let result = '';
  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return result;
}

export async function POST(request: NextRequest) {
  try {
    const formData = await request.formData();
    const file = formData.get('file') as File | null;
    const type = formData.get('type') as string | null;

    // Validate required fields
    if (!file) {
      return NextResponse.json({ error: 'No file provided' }, { status: 400 });
    }
    if (!type) {
      return NextResponse.json({ error: 'No type provided' }, { status: 400 });
    }

    // Determine category from type
    const category = getCategory(type);
    if (!category) {
      return NextResponse.json(
        { error: `Invalid upload type: ${type}. Allowed: avatar, message, voice, document` },
        { status: 400 }
      );
    }

    // Validate MIME type
    const allowedMimes = ALLOWED_TYPES[category];
    if (!allowedMimes.includes(file.type)) {
      return NextResponse.json(
        { error: `Invalid file type: ${file.type}. Allowed: ${allowedMimes.join(', ')}` },
        { status: 400 }
      );
    }

    // Validate file size
    const maxSize = MAX_SIZES[category];
    if (file.size > maxSize) {
      const maxMB = Math.round(maxSize / (1024 * 1024));
      return NextResponse.json(
        { error: `File too large. Maximum size for ${category}: ${maxMB}MB` },
        { status: 400 }
      );
    }

    // Generate unique filename
    const ext = extname(file.name) || getDefaultExtension(category, file.type);
    const timestamp = Date.now();
    const random = randomString(6);
    const filename = `${type}-${timestamp}-${random}${ext}`;

    // Ensure upload directory exists
    const uploadDir = join(process.cwd(), 'public', 'uploads', type);
    await mkdir(uploadDir, { recursive: true });

    // Write file to disk
    const filePath = join(uploadDir, filename);
    const buffer = Buffer.from(await file.arrayBuffer());
    await writeFile(filePath, buffer);

    // Return the public URL
    const url = `/uploads/${type}/${filename}`;
    return NextResponse.json({ url }, { status: 200 });
  } catch (error) {
    console.error('Upload error:', error);
    return NextResponse.json({ error: 'Upload failed' }, { status: 500 });
  }
}

// Provide default extension when original filename lacks one
function getDefaultExtension(category: string, mime: string): string {
  const map: Record<string, string> = {
    'image/jpeg': '.jpg',
    'image/png': '.png',
    'image/gif': '.gif',
    'image/webp': '.webp',
    'video/mp4': '.mp4',
    'video/webm': '.webm',
    'audio/mpeg': '.mp3',
    'audio/webm': '.webm',
    'audio/ogg': '.ogg',
    'application/pdf': '.pdf',
    'application/msword': '.doc',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
  };
  return map[mime] || '';
}
