const fs = require('fs').promises;
const path = require('path');
const { v4: uuidv4 } = require('uuid');

/**
 * Upload a file to the server
 * @param {Object} file - The file object from multer
 * @param {String} uploadPath - The directory path where the file should be saved
 * @param {Array} allowedTypes - Array of allowed MIME types (e.g., ['image/jpeg', 'image/png'])
 * @param {Number} maxSize - Maximum file size in bytes
 * @returns {Promise<Object>} - Object containing file information
 */
const uploadFile = async (file, uploadPath, allowedTypes = null, maxSize = 5 * 1024 * 1024) => {
  try {
    // Check if file exists
    if (!file) {
      throw new Error('No file provided');
    }

    // Check file size
    if (file.size > maxSize) {
      throw new Error(`File size exceeds the limit of ${maxSize / (1024 * 1024)}MB`);
    }

    // Check file type if allowedTypes is provided
    if (allowedTypes && !allowedTypes.includes(file.mimetype)) {
      throw new Error(`Invalid file type. Allowed types: ${allowedTypes.join(', ')}`);
    }

    // Create directory if it doesn't exist
    await fs.mkdir(uploadPath, { recursive: true });

    // Generate unique filename
    const fileExt = path.extname(file.originalname).toLowerCase();
    const fileName = `${uuidv4()}${fileExt}`;
    const filePath = path.join(uploadPath, fileName);

    // Move the file to the upload directory
    await fs.rename(file.path, filePath);

    // Return file information
    return {
      originalName: file.originalname,
      fileName,
      filePath,
      mimeType: file.mimetype,
      size: file.size,
      url: `/uploads/${path.basename(uploadPath)}/${fileName}`
    };
  } catch (error) {
    // Clean up the file if there was an error
    if (file && file.path) {
      try {
        await fs.unlink(file.path);
      } catch (unlinkError) {
        console.error('Error cleaning up file:', unlinkError);
      }
    }
    throw error;
  }
};

/**
 * Delete a file from the server
 * @param {String} filePath - Path to the file to be deleted
 * @returns {Promise<Boolean>} - True if file was deleted, false if it didn't exist
 */
const deleteFile = async (filePath) => {
  try {
    await fs.access(filePath);
    await fs.unlink(filePath);
    return true;
  } catch (error) {
    if (error.code === 'ENOENT') {
      // File doesn't exist, which is fine
      return false;
    }
    throw error;
  }
};

/**
 * Delete multiple files
 * @param {Array<String>} filePaths - Array of file paths to delete
 * @returns {Promise<Array>} - Array of results for each file deletion
 */
const deleteFiles = async (filePaths) => {
  if (!Array.isArray(filePaths)) {
    filePaths = [filePaths];
  }
  
  return Promise.all(
    filePaths.map(filePath => 
      deleteFile(filePath).catch(error => ({
        filePath,
        success: false,
        error: error.message
      }))
    )
  );
};

module.exports = {
  uploadFile,
  deleteFile,
  deleteFiles
};
