import { v2 as cloudinary } from "cloudinary";
import { unlink, access, constants } from "fs/promises";
import { join } from "path";
import logger from "./logger.js";

// Configure Cloudinary - Trim whitespace to avoid issues
const cloudName = process.env.CLOUDINARY_CLOUD_NAME?.trim();
const apiKey = process.env.CLOUDINARY_API_KEY?.trim();
const apiSecret = process.env.CLOUDINARY_API_SECRET?.trim();

if (cloudName && apiKey && apiSecret) {
  cloudinary.config({
    cloud_name: cloudName,
    api_key: apiKey,
    api_secret: apiSecret,
  });
  logger.info("Cloudinary configured successfully");
} else {
  logger.warn("Cloudinary credentials are missing. Please check your .env file.");
}

/**
 * Upload file to Cloudinary
 * @param {string} filePath - Path to the file to upload
 * @param {string} folder - Cloudinary folder name (optional)
 * @returns {Promise<string>} - Public URL of the uploaded file
 */
export async function uploadToCloudinary(filePath, folder = "user-resumes") {
  try {
    // Verify credentials are set
    if (!cloudName || !apiKey || !apiSecret) {
      throw new Error("Cloudinary credentials are not configured. Please check your .env file.");
    }

    // Verify Cloudinary is properly configured
    if (!cloudinary.config().cloud_name) {
      throw new Error("Cloudinary is not properly configured. Please check your credentials.");
    }

    // Check if file exists
    try {
      await access(filePath, constants.F_OK);
      logger.info(`File exists: ${filePath}`);
    } catch (accessError) {
      logger.error(`File does not exist: ${filePath}`);
      throw new Error(`File not found: ${filePath}`);
    }

    logger.info(`Uploading file to Cloudinary: ${filePath}`);

    // Log configuration (without exposing secret)
    logger.info(`Cloudinary config - Cloud Name: ${cloudName}, API Key: ${apiKey?.substring(0, 5)}...`);

    const result = await cloudinary.uploader.upload(filePath, {
      folder: folder,
      resource_type: "auto", // Automatically detect file type
      use_filename: true,
      unique_filename: true,
    });

    logger.info(`File uploaded successfully to Cloudinary: ${result.secure_url}`);

    // Delete the local file after successful upload
    try {
      await unlink(filePath);
      logger.info(`Local file deleted: ${filePath}`);
    } catch (deleteError) {
      logger.warn(`Failed to delete local file: ${filePath}`, deleteError);
      // Don't throw error if file deletion fails
    }

    return result.secure_url;
  } catch (error) {
    logger.error("Error uploading to Cloudinary:", error);
    logger.error("Error message:", error?.message);
    logger.error("Error http_code:", error?.http_code);
    
    // Provide more helpful error messages
    let errorMessage = error?.message || "Failed to upload to Cloudinary";
    
    if (error?.message?.includes("Invalid Signature") || error?.http_code === 401) {
      errorMessage = "Cloudinary authentication failed. Please verify your API credentials (CLOUDINARY_API_KEY and CLOUDINARY_API_SECRET) in the .env file. Make sure there are no extra spaces or characters.";
    } else if (error?.http_code === 400) {
      errorMessage = "Invalid request to Cloudinary. Please check your Cloudinary configuration.";
    }
    
    // Try to delete the local file even if upload fails
    try {
      await unlink(filePath);
    } catch (deleteError) {
      logger.warn(`Failed to delete local file after error: ${filePath}`);
    }
    
    // Create a new error with the helpful message
    const customError = new Error(errorMessage);
    customError.originalError = error;
    throw customError;
  }
}

/**
 * Delete file from Cloudinary
 * @param {string} publicId - Public ID of the file in Cloudinary
 * @returns {Promise<void>}
 */
export async function deleteFromCloudinary(publicId) {
  try {
    await cloudinary.uploader.destroy(publicId);
    logger.info(`File deleted from Cloudinary: ${publicId}`);
  } catch (error) {
    logger.error("Error deleting from Cloudinary:", error);
    throw error;
  }
}

