import { extname } from 'path';
import { BadRequestException } from '@nestjs/common';

/**
 * Generates a unique filename by appending a timestamp and random number
 * to prevent naming conflicts when storing uploaded files.
 *
 * This function preserves the original file extension while ensuring
 * uniqueness through a combination of timestamp and random number.
 *
 * @param originalName - The original filename (e.g., "document.pdf")
 * @returns {string} A unique filename with format: timestamp-random.extension
 *
 * @example
 * // Generates something like: "1701791712345-123456789.pdf"
 * generateUniqueFileName('document.pdf');
 *
 * @example
 * // With complex filename
 * generateUniqueFileName('my vacation photo (1).jpg');
 * // Returns: "1701791712345-987654321.jpg"
 *
 * @example
 * // With no extension (rare but handled)
 * generateUniqueFileName('README');
 * // Returns: "1701791712345-456789123" (no extension)
 *
 * @note
 * - Uses Date.now() for millisecond precision timestamp
 * - Adds random number (0-1e9) for additional uniqueness
 * - Preserves original file extension using path.extname()
 * - Collision probability: Extremely low for practical purposes
 */
export const generateUniqueFileName = (originalName: string): string => {
  // Create unique suffix combining timestamp and random number
  // Date.now(): Current timestamp in milliseconds
  // Math.random() * 1e9: Random number between 0 and 1 billion
  const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);

  // Extract file extension including the dot (e.g., ".pdf", ".jpg")
  const ext = extname(originalName);

  // Combine unique suffix with original extension
  return `${uniqueSuffix}${ext}`;
};

/**
 * Validates that a file's extension is in the list of allowed types.
 * Throws a BadRequestException if the file type is not allowed.
 *
 * This is a security-critical function to prevent malicious file uploads.
 * It should be used in conjunction with server-side file type verification.
 *
 * @param fileName - The name of the file to validate (e.g., "image.png")
 * @param allowedTypes - Array of allowed file extensions (without dots)
 * @returns {void} Nothing, but throws BadRequestException if validation fails
 * @throws {BadRequestException} When file extension is missing or not allowed
 *
 * @example
 * // Valid file type
 * validateFileType('document.pdf', ['pdf', 'docx', 'txt']);
 * // No exception thrown
 *
 * @example
 * // Invalid file type
 * validateFileType('script.exe', ['pdf', 'docx', 'txt']);
 * // Throws: BadRequestException - Invalid file type. Allowed types: pdf, docx, txt
 *
 * @example
 * // File without extension
 * validateFileType('README', ['txt', 'md']);
 * // Throws: BadRequestException - Invalid file type...
 *
 * @example
 * // Case-insensitive check (this implementation IS case-sensitive)
 * validateFileType('image.JPG', ['jpg', 'png']);
 * // Throws: BadRequestException - JPG != jpg (case-sensitive)
 *
 * @security
 * - This only checks the extension, not the actual file content
 * - Malicious users can rename files (e.g., rename virus.exe to virus.jpg)
 * - Always validate actual file content on the server side
 * - Consider using libraries like 'file-type' for MIME type detection
 */
export const validateFileType = (
  fileName: string,
  allowedTypes: string[],
): void => {
  // Extract file extension (without dot)
  // split('.') splits by dot, pop() gets last element after last dot
  const ext = fileName.split('.').pop();

  // Check if extension exists and is in allowed types list
  if (!ext || !allowedTypes.includes(ext)) {
    throw new BadRequestException(
      `Invalid file type. Allowed types: ${allowedTypes.join(', ')}`,
    );
  }
};

/**
 * Enhanced version with case-insensitive support and MIME type validation:
 *
 * export const validateFileTypeEnhanced = (
 *   fileName: string,
 *   allowedExtensions: string[],
 *   allowedMimeTypes?: string[]
 * ): void => {
 *   const ext = fileName.split('.').pop()?.toLowerCase();
 *
 *   if (!ext || !allowedExtensions.includes(ext)) {
 *     throw new BadRequestException(
 *       `Invalid file extension. Allowed: ${allowedExtensions.join(', ')}`
 *     );
 *   }
 *
 *   // Additional MIME type validation if buffer is available
 *   if (allowedMimeTypes && fileBuffer) {
 *     const mimeType = await fileType.fromBuffer(fileBuffer);
 *     if (!mimeType || !allowedMimeTypes.includes(mimeType.mime)) {
 *       throw new BadRequestException('Invalid file content type');
 *     }
 *   }
 * };
 *
 * Common usage patterns:
 *
 * // For image uploads
 * const ALLOWED_IMAGE_TYPES = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
 * validateFileType(uploadedFile.originalname, ALLOWED_IMAGE_TYPES);
 *
 * // For document uploads
 * const ALLOWED_DOC_TYPES = ['pdf', 'docx', 'txt', 'md'];
 * validateFileType(uploadedFile.originalname, ALLOWED_DOC_TYPES);
 *
 * // Combined with unique filename generation
 * export const processFileUpload = (file: Express.Multer.File) => {
 *   validateFileType(file.originalname, ALLOWED_TYPES);
 *   const uniqueName = generateUniqueFileName(file.originalname);
 *   // Save file with uniqueName
 *   return uniqueName;
 * };
 */
