const sharp = require('sharp');
const path = require('path');
const fs = require('fs').promises;
const { uploadDir } = require('../middleware/upload');
const logger = require('../config/logger');

/**
 * Upload and process image
 * POST /api/v1/upload/image
 */
const uploadImage = async (req, res, next) => {
  try {
    if (!req.file) {
      return res.status(400).json({
        code: 400,
        message: 'No file uploaded',
        data: null,
      });
    }

    const originalPath = req.file.path;
    
    // Generate unique filename with .jpg extension (since we're converting to JPEG)
    const timestamp = Date.now();
    const randomString = Math.random().toString(36).substring(2, 15);
    const processedFilename = `${timestamp}_${randomString}.jpg`;
    const processedPath = path.join(uploadDir, processedFilename);
    
    // Ensure output path is different from input path
    if (processedPath === originalPath) {
      throw new Error('Output path cannot be the same as input path');
    }

    try {
      // Process image with Sharp
      const sharpInstance = sharp(originalPath);
      await sharpInstance
        .resize(1200, 1200, {
          fit: 'inside',
          withoutEnlargement: true,
        })
        .jpeg({
          quality: 85,
          progressive: true,
        })
        .toFile(processedPath);

      // Destroy sharp instance to release file handles
      sharpInstance.destroy();

      // Delete original file if it's different from processed
      // On Windows, file deletion can fail due to file locks, so we schedule it for later
      if (originalPath !== processedPath) {
        // Schedule deletion after a delay to avoid file lock issues on Windows
        setTimeout(async () => {
          try {
            await fs.unlink(originalPath);
            logger.info('Original file deleted successfully', { path: originalPath });
          } catch (unlinkError) {
            // If deletion still fails, just log it
            // The file will need to be cleaned up manually or by a cleanup job
            logger.warn('Could not delete original file', { 
              path: originalPath,
              error: unlinkError.message 
            });
          }
        }, 500); // Wait 500ms before attempting deletion
      }

      // Return relative path for the image (more portable)
      // Frontend will prepend the base URL as needed
      const imageUrl = `/uploads/${processedFilename}`;

      logger.info('Image uploaded and processed successfully', {
        originalName: req.file.originalname,
        processedFilename,
        size: req.file.size,
      });

      res.status(200).json({
        code: 0,
        message: 'Image uploaded successfully',
        data: {
          url: imageUrl,
          filename: processedFilename,
          originalName: req.file.originalname,
          size: req.file.size,
        },
      });
    } catch (processingError) {
      // Clean up file if processing fails
      try {
        await fs.unlink(originalPath);
      } catch (unlinkError) {
        logger.error('Failed to delete file after processing error', { error: unlinkError });
      }
      throw processingError;
    }
  } catch (error) {
    logger.error('Image upload error', { error: error.message });
    next(error);
  }
};

module.exports = {
  uploadImage,
};
