import { Client } from 'minio';

// Initialize MinIO client
export const getMinioClient = () => {
  const config = useRuntimeConfig().minio;
  
  return new Client({
    endPoint: config.endPoint,
    port: config.port,
    useSSL: config.useSSL,
    accessKey: config.accessKey,
    secretKey: config.secretKey,
  });
};

// Upload file with content type detection
export const uploadFile = async (filePath: string, fileBuffer: Buffer, contentType: string) => {
  const client = getMinioClient();
  const bucketName = useRuntimeConfig().minio.bucketName;
  
  return await client.putObject(bucketName, filePath, fileBuffer, fileBuffer.length, {
    'Content-Type': contentType,
  });
};

// Generate presigned URL for secure downloads
export const getDownloadUrl = async (fileName: string, expiry: number = 60 * 60) => {
  const client = getMinioClient();
  const bucketName = useRuntimeConfig().minio.bucketName;
  
  // Extract just the filename from the full path
  let filename = fileName.split('/').pop() || fileName;
  
  // Remove timestamp prefix if present (e.g., "1234567890-filename.pdf" -> "filename.pdf")
  const timestampMatch = filename.match(/^\d{10,}-(.+)$/);
  if (timestampMatch) {
    filename = timestampMatch[1];
  }
  
  // Force download with Content-Disposition header
  const responseHeaders = {
    'response-content-disposition': `attachment; filename="${filename}"`,
  };
  
  return await client.presignedGetObject(bucketName, fileName, expiry, responseHeaders);
};

// Get presigned URL for file preview (inline display)
export const getPreviewUrl = async (fileName: string, contentType: string) => {
  const client = getMinioClient();
  const bucketName = useRuntimeConfig().minio.bucketName;
  
  // For images and PDFs, generate a presigned URL with appropriate response headers
  const responseHeaders = {
    'response-content-type': contentType,
    'response-content-disposition': 'inline',
  };
  
  return await client.presignedGetObject(bucketName, fileName, 60 * 60, responseHeaders);
};

// Delete file
export const deleteFile = async (fileName: string) => {
  const client = getMinioClient();
  const bucketName = useRuntimeConfig().minio.bucketName;
  
  return await client.removeObject(bucketName, fileName);
};

// Get file statistics
export const getFileStats = async (fileName: string) => {
  const client = getMinioClient();
  const bucketName = useRuntimeConfig().minio.bucketName;
  
  return await client.statObject(bucketName, fileName);
};

// Create bucket if it doesn't exist
export const createBucketIfNotExists = async (bucketName?: string) => {
  const client = getMinioClient();
  const bucket = bucketName || useRuntimeConfig().minio.bucketName;
  
  try {
    const exists = await client.bucketExists(bucket);
    if (!exists) {
      await client.makeBucket(bucket);
      console.log(`Bucket '${bucket}' created successfully`);
    }
    return true;
  } catch (error) {
    console.error('Error creating bucket:', error);
    throw error;
  }
};

// List files with prefix support
export const listFiles = async (prefix: string = '', recursive: boolean = false) => {
  const client = getMinioClient();
  const bucketName = useRuntimeConfig().minio.bucketName;
  
  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) => {
        // Handle folder prefixes returned by MinIO
        if (obj && obj.prefix) {
          folders.add(obj.prefix);
          return;
        }
        
        // Skip objects without a name
        if (!obj || typeof obj.name !== 'string') {
          return;
        }
        
        if (!recursive) {
          if (prefix) {
            // Extract folder structure when inside a folder
            const relativePath = obj.name.substring(prefix.length);
            if (!relativePath) return; // Skip if no relative path
            
            const firstSlash = relativePath.indexOf('/');
            
            if (firstSlash > -1) {
              // This is a folder
              const folderName = relativePath.substring(0, firstSlash);
              folders.add(prefix + folderName + '/');
            } else if (relativePath && !obj.name.endsWith('/')) {
              // This is a file in the current folder
              files.push({
                name: obj.name,
                size: obj.size || 0,
                lastModified: obj.lastModified || new Date(),
                etag: obj.etag || '',
                isFolder: false,
              });
            }
          } else {
            // At root level
            const firstSlash = obj.name.indexOf('/');
            
            if (obj.name.endsWith('/')) {
              // This is a folder placeholder
              folders.add(obj.name);
            } else if (firstSlash > -1) {
              // This is inside a folder, extract the folder
              const folderName = obj.name.substring(0, firstSlash);
              folders.add(folderName + '/');
            } else {
              // This is a file at root
              files.push({
                name: obj.name,
                size: obj.size || 0,
                lastModified: obj.lastModified || new Date(),
                etag: obj.etag || '',
                isFolder: false,
              });
            }
          }
        } else {
          // When recursive, include all files
          if (!obj.name.endsWith('/')) {
            files.push({
              name: obj.name,
              size: obj.size || 0,
              lastModified: obj.lastModified || new Date(),
              etag: obj.etag || '',
              isFolder: false,
            });
          }
        }
      });
      
      stream.on('error', (error) => {
        console.error('Stream error:', error);
        reject(error);
      });
      
      stream.on('end', () => {
        // Add folders to the result
        const folderItems = Array.from(folders).map(folder => ({
          name: folder,
          size: 0,
          lastModified: new Date(),
          etag: '',
          isFolder: true,
        }));
        
        resolve([...folderItems, ...files]);
      });
    } catch (error) {
      console.error('Error in listFiles:', error);
      reject(error);
    }
  });
};
