import { requireAuth } from '~/server/utils/auth';
import { getMinioClient } from '~/server/utils/minio';

export default defineEventHandler(async (event) => {
  // Check authentication (x-tag header OR Keycloak session)
  await requireAuth(event);
  
  try {
    const query = getQuery(event);
    const fileName = query.fileName as string;
    const bucket = (query.bucket as string) || 'client-portal'; // Support bucket parameter
    
    if (!fileName) {
      throw createError({
        statusCode: 400,
        statusMessage: 'File name is required',
      });
    }
    
    // Retry logic for getting download URL and fetching file
    let response: Response | null = null;
    let lastError: any = null;
    
    for (let attempt = 0; attempt < 3; attempt++) {
      try {
        console.log(`[proxy-download] Attempting to download ${fileName} from bucket ${bucket} (attempt ${attempt + 1}/3)`);
        
        // Get the download URL from MinIO with the correct bucket
        const client = getMinioClient();
        
        // Extract just the filename for the download header
        let filename = fileName.split('/').pop() || fileName;
        
        // Remove timestamp prefix if present
        const timestampMatch = filename.match(/^\d{10,}-(.+)$/);
        if (timestampMatch) {
          filename = timestampMatch[1];
        }
        
        // Generate presigned URL with download headers
        const responseHeaders = {
          'response-content-disposition': `attachment; filename="${filename}"`,
        };
        
        const url = await client.presignedGetObject(bucket, fileName, 60 * 60, responseHeaders);
        
        // Fetch the file from MinIO with timeout
        const controller = new AbortController();
        const timeout = setTimeout(() => controller.abort(), 30000); // 30 second timeout
        
        response = await fetch(url, { signal: controller.signal });
        clearTimeout(timeout);
        
        if (response.ok) {
          break; // Success, exit retry loop
        }
        
        lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);
      } catch (error: any) {
        lastError = error;
        console.error(`[proxy-download] Attempt ${attempt + 1} failed:`, error.message);
        
        // Wait before retry with exponential backoff
        if (attempt < 2) {
          await new Promise(resolve => setTimeout(resolve, (attempt + 1) * 1000));
        }
      }
    }
    
    if (!response || !response.ok) {
      throw createError({
        statusCode: response?.status || 500,
        statusMessage: lastError?.message || 'Failed to fetch file from storage after 3 attempts',
      });
    }
    
    // Get the file data
    const arrayBuffer = await response.arrayBuffer();
    const buffer = Buffer.from(arrayBuffer);
    
    // Extract clean filename (remove timestamp prefix)
    let cleanFileName = fileName.split('/').pop() || fileName;
    const timestampMatch = cleanFileName.match(/^\d{10,}-(.+)$/);
    if (timestampMatch) {
      cleanFileName = timestampMatch[1];
    }
    
    // Get content type
    const contentType = response.headers.get('content-type') || 'application/octet-stream';
    
    // Set headers for download
    setHeader(event, 'Content-Type', contentType);
    // Use both filename and filename* for better compatibility
    setHeader(event, 'Content-Disposition', `attachment; filename="${cleanFileName}"; filename*=UTF-8''${encodeURIComponent(cleanFileName)}`);
    // Content-Length header is set automatically by Nitro when returning a buffer
    
    // Return the file buffer
    return buffer;
  } catch (error: any) {
    console.error('Failed to proxy download:', error);
    throw createError({
      statusCode: 500,
      statusMessage: error.message || 'Failed to download file',
    });
  }
});
