const path = require("path");
const childProcess = require("child_process");
const util = require("util");

const execFile = util.promisify(childProcess.execFile);

const directAudioUploadLimitBytes = 24 * 1024 * 1024;
const allowedAudioMimeTypes = new Set(["audio/mpeg", "audio/mp4", "audio/wav", "audio/x-wav", "audio/webm"]);
const allowedAudioExtensions = new Set([".mp3", ".m4a", ".mp4", ".wav", ".webm"]);

function validateAudioUpload(audioFile) {
  const fileName = audioFile.originalFilename || audioFile.name || "";
  const mimeType = String(audioFile.mimetype || audioFile.type || "").toLowerCase();
  const extension = path.extname(fileName).toLowerCase();
  const size = Number(audioFile.size || 0);

  if (!allowedAudioMimeTypes.has(mimeType) || !allowedAudioExtensions.has(extension)) {
    const error = new Error("Unsupported audio file type");
    error.code = 415;
    throw error;
  }

  if (size <= 0 || size > directAudioUploadLimitBytes) {
    const error = new Error("Audio file must be between 1 byte and 24 MB");
    error.code = 413;
    throw error;
  }
}

async function validateAudioContent(filePath, probe = execFile) {
  try {
    const { stdout } = await probe("ffprobe", [
      "-v", "error", "-select_streams", "a:0", "-show_entries", "stream=codec_type",
      "-of", "default=noprint_wrappers=1:nokey=1", filePath,
    ]);

    if (!String(stdout).trim().includes("audio")) {
      const error = new Error("Uploaded file does not contain a readable audio stream");
      error.code = 415;
      throw error;
    }
  } catch (error) {
    if (error.code === 415) {
      throw error;
    }

    const invalidAudio = new Error("Uploaded file is not valid audio");
    invalidAudio.code = 415;
    throw invalidAudio;
  }
}

module.exports = { directAudioUploadLimitBytes, validateAudioUpload, validateAudioContent };
