import { diskStorage } from 'multer';
import { extname } from 'path';
import { BadRequestException } from '@nestjs/common';
import { UPLOAD_CONFIGS } from 'src/constants/upload.constants';

/**
 * getMulterConfig
 * ----------------
 * Generates a Multer configuration object based on a predefined upload config.
 *
 * This helper centralizes:
 * - Upload destination paths
 * - File size limits
 * - File count limits
 * - Allowed file extensions
 *
 * @param configKey Key referencing a configuration in UPLOAD_CONFIGS
 * @returns Multer configuration object
 * @throws BadRequestException when an invalid config key or file type is used
 */
export function getMulterConfig(configKey: keyof typeof UPLOAD_CONFIGS) {
  // Retrieve upload configuration by key
  const cfg = UPLOAD_CONFIGS[configKey];

  // Reject request if upload type is not configured
  if (!cfg) {
    throw new BadRequestException(`Invalid upload type: ${configKey}`);
  }

  return {
    /**
     * Storage configuration
     * Files are stored on disk using a custom filename strategy
     */
    storage: diskStorage({
      /**
       * Destination directory for uploaded files
       * Defined per upload type in UPLOAD_CONFIGS
       */
      destination: cfg.path,

      /**
       * Filename generator
       * Uses a timestamp + random suffix to avoid collisions
       */
      filename: (_req, file, callback) => {
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);

        callback(
          null,
          `${file.fieldname}-${uniqueSuffix}${extname(file.originalname)}`,
        );
      },
    }),

    /**
     * Upload limits
     * - fileSize: maximum file size (converted from MB to bytes)
     * - files: maximum number of files allowed per request
     */
    limits: {
      fileSize: cfg.maxSizeMB * 1024 * 1024, // MB → bytes
      files: cfg.maxFiles,
    },

    /**
     * File filter
     * Validates file extensions before accepting the upload
     */
    fileFilter: (_req: any, file: Express.Multer.File, callback: Function) => {
      // Extract and normalize file extension
      const ext = extname(file.originalname).replace('.', '').toLowerCase();

      // Check if file extension is allowed for this upload type
      if (!cfg.fileTypes.map((t) => t.toLowerCase()).includes(ext)) {
        return callback(
          new BadRequestException(`Invalid file type. ${cfg.fileLabel}`),
          false,
        );
      }

      // Accept file
      callback(null, true);
    },
  };
}
