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

export default defineEventHandler(async (event) => {
  // Check authentication (x-tag header OR Keycloak session)
  await requireAuth(event);
  
  try {
    const query = getQuery(event);
    const prefix = (query.prefix as string) || '';
    const recursive = query.recursive === 'true';
    const includeEmailAttachments = query.includeEmailAttachments === 'true';
    const currentUserEmail = query.userEmail as string;
    
    // Get files from main bucket (client-portal)
    const mainFiles = await listFilesFromBucket('client-portal', prefix, recursive);
    
    let allFiles = [...mainFiles];
    
    // If requested, also include email attachments from client-emails bucket
    if (includeEmailAttachments && currentUserEmail) {
      try {
        // Create the folder name from the user's email
        const username = currentUserEmail.split('@')[0]
          .toLowerCase()
          .replace(/[^a-z0-9-]/g, '');
        
        const attachmentFolder = `${username}-attachments`;
        
        // List files from the user's attachment folder
        const attachmentFiles = await listFilesFromBucket('client-emails', attachmentFolder + '/', true);
        
        // Add these files with a special flag to identify them as email attachments
        const formattedAttachmentFiles = attachmentFiles.map((file: any) => ({
          ...file,
          isEmailAttachment: true,
          displayPath: `Email Attachments/${file.name.replace(attachmentFolder + '/', '')}`,
          bucket: 'client-emails'
        }));
        
        // Create a virtual folder for email attachments
        if (formattedAttachmentFiles.length > 0 && !prefix) {
          allFiles.push({
            name: 'Email Attachments/',
            size: 0,
            lastModified: new Date(),
            etag: '',
            isFolder: true,
            isVirtualFolder: true,
            icon: 'mdi-email-multiple'
          });
        }
        
        // If we're inside the Email Attachments folder, show the files
        if (prefix === 'Email Attachments/') {
          allFiles = formattedAttachmentFiles.map((file: any) => ({
            ...file,
            displayName: file.name.replace(attachmentFolder + '/', ''),
            // Keep the full path in 'name' for operations like delete
            name: file.name
          }));
        }
      } catch (error) {
        console.error('Error fetching email attachments:', error);
        // Continue without email attachments if there's an error
      }
    }
    
    // Format file list with additional metadata
    const formattedFiles = allFiles.map(file => ({
      ...file,
      sizeFormatted: file.isFolder ? '-' : formatFileSize(file.size),
      extension: file.isFolder ? 'folder' : getFileExtension(file.name),
      icon: file.icon || (file.isFolder ? 'mdi-folder' : getFileIcon(file.name)),
      displayName: file.displayPath || getDisplayName(file.name),
    }));
    
    // Sort folders first, then files
    formattedFiles.sort((a, b) => {
      if (a.isFolder && !b.isFolder) return -1;
      if (!a.isFolder && b.isFolder) return 1;
      return a.displayName.localeCompare(b.displayName);
    });
    
    return {
      success: true,
      files: formattedFiles,
      count: formattedFiles.length,
      currentPath: prefix,
    };
  } catch (error: any) {
    console.error('Failed to list files:', error);
    throw createError({
      statusCode: 500,
      statusMessage: error.message || 'Failed to list files',
    });
  }
});

// List files from a specific bucket
async function listFilesFromBucket(bucketName: string, prefix: string = '', recursive: boolean = false): Promise<any[]> {
  const config = useRuntimeConfig().minio;
  
  const client = new Client({
    endPoint: config.endPoint,
    port: config.port,
    useSSL: config.useSSL,
    accessKey: config.accessKey,
    secretKey: config.secretKey,
  });
  
  const files: any[] = [];
  const folders = new Set<string>();
  
  return new Promise(async (resolve, reject) => {
    try {
      const stream = client.listObjectsV2(bucketName, prefix, recursive);
      
      stream.on('data', (obj) => {
        if (obj && obj.prefix) {
          folders.add(obj.prefix);
          return;
        }
        
        if (!obj || typeof obj.name !== 'string') {
          return;
        }
        
        if (!recursive) {
          if (prefix) {
            const relativePath = obj.name.substring(prefix.length);
            if (!relativePath) return;
            
            const firstSlash = relativePath.indexOf('/');
            
            if (firstSlash > -1) {
              const folderName = relativePath.substring(0, firstSlash);
              folders.add(prefix + folderName + '/');
            } else if (relativePath && !obj.name.endsWith('/')) {
              files.push({
                name: obj.name,
                size: obj.size || 0,
                lastModified: obj.lastModified || new Date(),
                etag: obj.etag || '',
                isFolder: false,
                bucket: bucketName
              });
            }
          } else {
            const firstSlash = obj.name.indexOf('/');
            
            if (obj.name.endsWith('/')) {
              folders.add(obj.name);
            } else if (firstSlash > -1) {
              const folderName = obj.name.substring(0, firstSlash);
              folders.add(folderName + '/');
            } else {
              files.push({
                name: obj.name,
                size: obj.size || 0,
                lastModified: obj.lastModified || new Date(),
                etag: obj.etag || '',
                isFolder: false,
                bucket: bucketName
              });
            }
          }
        } else {
          if (!obj.name.endsWith('/')) {
            files.push({
              name: obj.name,
              size: obj.size || 0,
              lastModified: obj.lastModified || new Date(),
              etag: obj.etag || '',
              isFolder: false,
              bucket: bucketName
            });
          }
        }
      });
      
      stream.on('error', (error) => {
        console.error('Stream error:', error);
        reject(error);
      });
      
      stream.on('end', () => {
        const folderItems = Array.from(folders).map(folder => ({
          name: folder,
          size: 0,
          lastModified: new Date(),
          etag: '',
          isFolder: true,
          bucket: bucketName
        }));
        
        resolve([...folderItems, ...files]);
      });
    } catch (error) {
      console.error('Error in listFilesFromBucket:', error);
      reject(error);
    }
  });
}

// Helper functions
function formatFileSize(bytes: number): string {
  const sizes = ['Bytes', 'KB', 'MB', 'GB'];
  if (bytes === 0) return '0 Bytes';
  const i = Math.floor(Math.log(bytes) / Math.log(1024));
  return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
}

function getFileExtension(filename: string): string {
  const parts = filename.split('.');
  return parts.length > 1 ? parts.pop()?.toLowerCase() || '' : '';
}

function getFileIcon(filename: string): string {
  const ext = getFileExtension(filename);
  const iconMap: Record<string, string> = {
    pdf: 'mdi-file-pdf-box',
    doc: 'mdi-file-document',
    docx: 'mdi-file-document',
    xls: 'mdi-file-excel',
    xlsx: 'mdi-file-excel',
    jpg: 'mdi-file-image',
    jpeg: 'mdi-file-image',
    png: 'mdi-file-image',
    gif: 'mdi-file-image',
    svg: 'mdi-file-image',
    zip: 'mdi-folder-zip',
    rar: 'mdi-folder-zip',
    txt: 'mdi-file-document-outline',
    csv: 'mdi-file-delimited',
    mp4: 'mdi-file-video',
    mp3: 'mdi-file-music',
  };
  return iconMap[ext] || 'mdi-file';
}

function getDisplayName(filepath: string): string {
  if (filepath.endsWith('/')) {
    const parts = filepath.slice(0, -1).split('/');
    return parts[parts.length - 1];
  }
  
  const parts = filepath.split('/');
  const filename = parts[parts.length - 1];
  
  const match = filename.match(/^\d{10,}-(.+)$/);
  return match ? match[1] : filename;
}
