// src/utils/imageProcessor.ts
import sharp from 'sharp';
import path from 'path';
import fs from 'node:fs/promises';
import type { Logger } from 'pino';
import { sanitizeFilename } from './stringUtils';

/**
 * Processes an uploaded image file by stripping all metadata (like EXIF)
 * and optimizing it for web use.
 *
 * @param sourcePath The path to the temporary uploaded file.
 * @param destinationDir The directory where the final image should be saved.
 * @param originalFileName The original name of the file, used to determine the output name.
 * @param logger A pino logger instance for logging.
 * @returns The file name of the newly processed image.
 */
export async function processAndSaveImage(
  sourcePath: string,
  destinationDir: string,
  originalFileName: string,
  logger: Logger,
): Promise<string> {
  // Create a unique-ish filename to avoid collisions, but keep the original extension.
  const fileExt = path.extname(originalFileName);
  const fileBase = path.basename(originalFileName, fileExt);
  const outputFileName = `${fileBase}-${Date.now()}${fileExt}`;
  const outputPath = path.join(destinationDir, outputFileName);

  try {
    // Ensure the destination directory exists.
    await fs.mkdir(destinationDir, { recursive: true });

    logger.debug({ sourcePath, outputPath }, 'Starting image processing: stripping metadata and optimizing.');

    // Use sharp to process the image.
    // .withMetadata({}) strips all EXIF and other metadata.
    // .jpeg() and .png() apply format-specific optimizations.
    await sharp(sourcePath, { failOn: 'none' })
      .withMetadata({}) // This is the key to stripping metadata
      .jpeg({ quality: 85, mozjpeg: true }) // Optimize JPEGs
      .png({ compressionLevel: 8, quality: 85 }) // Optimize PNGs
      .toFile(outputPath);

    logger.info(`Successfully processed image and saved to ${outputPath}`);
    console.log('[DEBUG] processAndSaveImage returning:', outputFileName);
    return outputFileName;
  } catch (error) {
    logger.error(
      { err: error, sourcePath, outputPath },
      'An error occurred during image processing and saving.',
    );
    // Re-throw the error to be handled by the calling service (e.g., the worker).
    throw new Error(`Failed to process image ${originalFileName}.`);
  }
}

/**
 * Generates a small WebP icon from a source image.
 *
 * @param sourcePath The path to the source image (can be the original upload or the processed image).
 * @param outputDir The directory to save the icon in (e.g., 'flyer-images/icons').
 * @param logger A pino logger instance for logging.
 * @returns The file name of the generated icon.
 */
export async function generateFlyerIcon(
  sourcePath: string,
  outputDir: string,
  logger: Logger,
): Promise<string> {
  // Sanitize the base name of the source file to create a clean icon name.
  const sourceBaseName = path.parse(sourcePath).name;
  const iconFileName = `icon-${sanitizeFilename(sourceBaseName)}.webp`;
  const outputPath = path.join(outputDir, iconFileName);

  try {
    // Ensure the output directory exists.
    await fs.mkdir(outputDir, { recursive: true });

    logger.debug({ sourcePath, outputPath }, 'Starting icon generation.');

    await sharp(sourcePath, { failOn: 'none' })
      .resize({ width: 128, height: 128, fit: 'inside' })
      .webp({ quality: 75 }) // Slightly lower quality for icons is acceptable.
      .toFile(outputPath);

    logger.info(`Successfully generated icon: ${outputPath}`);
    console.log('[DEBUG] generateFlyerIcon returning:', iconFileName);
    return iconFileName;
  } catch (error) {
    logger.error(
      { err: error, sourcePath, outputPath },
      'An error occurred during icon generation.',
    );
    // Re-throw the error to be handled by the calling service.
    throw new Error(`Failed to generate icon for ${sourcePath}.`);
  }
}