import { NextRequest, NextResponse } from 'next/server';
import path from 'path';
import fs from 'fs';
import { stat } from 'fs/promises';

// Handle OPTIONS preflight for CORS
export async function OPTIONS() {
  return new NextResponse(null, {
    status: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, OPTIONS',
      'Access-Control-Allow-Headers': 'Range, Content-Type, Authorization',
    },
  });
}

// GET /uploads/[...path] - Dynamic static file server with range request support for video streaming
export async function GET(req: NextRequest, { params }: { params: { path: string[] } }) {
  try {
    const rawPath = params.path ? params.path.join('/') : '';
    const filename = params.path && params.path.length > 0 ? params.path[params.path.length - 1] : '';

    if (!filename) {
      return new NextResponse('File not specified', { status: 400 });
    }

    // Try locating file across possible uploads locations
    const possiblePaths = [
      path.join(process.cwd(), 'public', 'uploads', rawPath),
      path.join(process.cwd(), 'public', 'uploads', filename),
      path.join(process.cwd(), 'public', 'uploads', 'videos', filename),
      path.join(process.cwd(), 'public', 'uploads', 'pdfs', filename),
      path.join(process.cwd(), 'public', 'uploads', 'images', filename),
      path.join(process.cwd(), 'public', 'uploads', 'documents', filename),
      path.join(process.cwd(), 'uploads', rawPath),
      path.join(process.cwd(), 'uploads', filename),
    ];

    let foundPath: string | null = null;
    for (const p of possiblePaths) {
      if (fs.existsSync(p) && fs.statSync(p).isFile()) {
        foundPath = p;
        break;
      }
    }

    // Fallback: Scan directories for files ending with target filename (e.g. 16by9_1789980758752.mp4 matching 1789980758752.mp4)
    if (!foundPath) {
      const searchDirs = [
        path.join(process.cwd(), 'public', 'uploads', 'videos'),
        path.join(process.cwd(), 'public', 'uploads', 'pdfs'),
        path.join(process.cwd(), 'public', 'uploads', 'images'),
        path.join(process.cwd(), 'public', 'uploads', 'documents'),
        path.join(process.cwd(), 'public', 'uploads'),
        path.join(process.cwd(), 'uploads'),
      ];

      for (const dir of searchDirs) {
        if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {
          const files = fs.readdirSync(dir);
          const match = files.find((f) => f === filename || f.endsWith(`_${filename}`) || f.endsWith(filename));
          if (match) {
            foundPath = path.join(dir, match);
            break;
          }
        }
      }
    }

    if (!foundPath) {
      return new NextResponse('File not found', { status: 404 });
    }

    const fileStat = await stat(foundPath);
    const fileSize = fileStat.size;
    const ext = path.extname(foundPath).toLowerCase();

    let mimeType = 'application/octet-stream';
    if (ext === '.mp4') mimeType = 'video/mp4';
    else if (ext === '.webm') mimeType = 'video/webm';
    else if (ext === '.mkv') mimeType = 'video/x-matroska';
    else if (ext === '.mov') mimeType = 'video/quicktime';
    else if (ext === '.avi') mimeType = 'video/x-msvideo';
    else if (ext === '.pdf') mimeType = 'application/pdf';
    else if (['.jpg', '.jpeg'].includes(ext)) mimeType = 'image/jpeg';
    else if (ext === '.png') mimeType = 'image/png';
    else if (ext === '.webp') mimeType = 'image/webp';
    else if (ext === '.svg') mimeType = 'image/svg+xml';

    const range = req.headers.get('range');
    if (range) {
      const parts = range.replace(/bytes=/, '').split('-');
      const start = parseInt(parts[0], 10);
      const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
      const chunkSize = end - start + 1;

      const nodeStream = fs.createReadStream(foundPath, { start, end });
      const webStream = new ReadableStream({
        start(controller) {
          nodeStream.on('data', (chunk) => controller.enqueue(chunk));
          nodeStream.on('end', () => controller.close());
          nodeStream.on('error', (err) => controller.error(err));
        },
      });

      return new NextResponse(webStream as any, {
        status: 206,
        headers: {
          'Content-Range': `bytes ${start}-${end}/${fileSize}`,
          'Accept-Ranges': 'bytes',
          'Content-Length': String(chunkSize),
          'Content-Type': mimeType,
          'Access-Control-Allow-Origin': '*',
        },
      });
    }

    const nodeStream = fs.createReadStream(foundPath);
    const webStream = new ReadableStream({
      start(controller) {
        nodeStream.on('data', (chunk) => controller.enqueue(chunk));
        nodeStream.on('end', () => controller.close());
        nodeStream.on('error', (err) => controller.error(err));
      },
    });

    return new NextResponse(webStream as any, {
      status: 200,
      headers: {
        'Content-Length': String(fileSize),
        'Content-Type': mimeType,
        'Accept-Ranges': 'bytes',
        'Access-Control-Allow-Origin': '*',
      },
    });
  } catch (error: any) {
    return new NextResponse('Error serving static file', { status: 500 });
  }
}
