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

// ---------------------------------------------------------------------------
// Configuration
// ---------------------------------------------------------------------------

const MAX_IMAGE_SIZE = 5 * 1024 * 1024; // 5 MB
const MAX_VIDEO_SIZE = 20 * 1024 * 1024; // 20 MB

const IMAGE_TYPES = [
  'image/png',
  'image/jpeg',
  'image/jpg',
  'image/gif',
  'image/webp',
];

const VIDEO_TYPES = [
  'video/mp4',
  'video/webm',
  'video/quicktime',
  'video/x-msvideo',
];

const ALL_TYPES = [...IMAGE_TYPES, ...VIDEO_TYPES];

const VALID_CATEGORIES = ['message', 'house', 'shop', 'product', 'general'] as const;
type Category = (typeof VALID_CATEGORIES)[number];

const UPLOAD_DIR = path.join(process.cwd(), 'public', 'uploads');

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function getExtension(contentType: string): string {
  const map: Record<string, string> = {
    'image/png': '.png',
    'image/jpeg': '.jpg',
    'image/jpg': '.jpg',
    'image/gif': '.gif',
    'image/webp': '.webp',
    'video/mp4': '.mp4',
    'video/webm': '.webm',
    'video/quicktime': '.mov',
    'video/x-msvideo': '.avi',
  };
  return map[contentType] || '.bin';
}

function isImageType(type: string): boolean {
  return IMAGE_TYPES.includes(type);
}

function isVideoType(type: string): boolean {
  return VIDEO_TYPES.includes(type);
}

function validateCategory(raw: string | null): Category {
  if (raw && VALID_CATEGORIES.includes(raw as Category)) {
    return raw as Category;
  }
  return 'general';
}

// ---------------------------------------------------------------------------
// POST  /api/upload
// ---------------------------------------------------------------------------

export async function POST(req: NextRequest) {
  try {
    // Ensure upload directory exists
    if (!existsSync(UPLOAD_DIR)) {
      await mkdir(UPLOAD_DIR, { recursive: true });
    }

    const formData = await req.formData();
    const file = formData.get('file') as File | null;

    if (!file) {
      return NextResponse.json(
        { success: false, error: 'No file provided' },
        { status: 400 },
      );
    }

    const category = validateCategory(formData.get('category') as string | null);

    // ----- Validate file type -----
    if (!ALL_TYPES.includes(file.type)) {
      return NextResponse.json(
        {
          success: false,
          error: `Invalid file type: ${file.type}. Allowed types: ${ALL_TYPES.join(', ')}`,
        },
        { status: 400 },
      );
    }

    // ----- Validate file size -----
    const isImage = isImageType(file.type);
    const isVideo = isVideoType(file.type);
    const maxSize = isVideo ? MAX_VIDEO_SIZE : MAX_IMAGE_SIZE;
    const maxLabel = isVideo ? '20MB' : '5MB';

    if (file.size > maxSize) {
      return NextResponse.json(
        {
          success: false,
          error: `File too large (${(file.size / (1024 * 1024)).toFixed(2)}MB). Maximum for ${isImage ? 'images' : 'videos'}: ${maxLabel}`,
        },
        { status: 400 },
      );
    }

    // ----- Generate unique filename -----
    const ext = getExtension(file.type);
    const timestamp = Date.now();
    const randomStr = Math.random().toString(36).substring(2, 8);
    const filename = `${category}-${timestamp}-${randomStr}${ext}`;

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

    // ----- Build response -----
    const url = `/uploads/${filename}`;

    return NextResponse.json({
      success: true,
      url,
      filename,
      size: file.size,
      type: file.type,
      category,
    });
  } catch (error) {
    console.error('Upload error:', error);
    return NextResponse.json(
      { success: false, error: 'Failed to upload file' },
      { status: 500 },
    );
  }
}

// ---------------------------------------------------------------------------
// DELETE  /api/upload
// ---------------------------------------------------------------------------

export async function DELETE(req: NextRequest) {
  try {
    const { filename } = await req.json();

    if (!filename) {
      return NextResponse.json(
        { success: false, error: 'Filename is required' },
        { status: 400 },
      );
    }

    // Prevent directory traversal – only operate inside UPLOAD_DIR
    const safeName = path.basename(filename);
    const filePath = path.join(UPLOAD_DIR, safeName);

    if (!existsSync(filePath)) {
      return NextResponse.json(
        { success: false, error: 'File not found' },
        { status: 404 },
      );
    }

    const { unlink } = await import('fs/promises');
    await unlink(filePath);

    return NextResponse.json({ success: true });
  } catch (error) {
    console.error('Delete file error:', error);
    return NextResponse.json(
      { success: false, error: 'Failed to delete file' },
      { status: 500 },
    );
  }
}
