import { execFileSync } from "node:child_process";
import { extname } from "node:path";

const IMAGE_EXT = new Set([".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".ico"]);

export function probe(filePath) {
  const ext = extname(filePath).toLowerCase();
  if (ext === ".svg") return { width: null, height: null, duration: null, codec: "svg" };

  try {
    // execFileSync (no shell) so a hostile filename like `"; rm -rf ~; ".png`
    // can't break out of the quoting — filePath is passed as a literal argv entry.
    const raw = execFileSync(
      "ffprobe",
      ["-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", "--", filePath],
      { encoding: "utf8", timeout: 5000 },
    );
    const info = JSON.parse(raw);
    const stream = info.streams?.[0];
    const format = info.format;

    const isImage = IMAGE_EXT.has(ext);
    const duration = isImage
      ? null
      : parseFloat(format?.duration) || parseFloat(stream?.duration) || null;
    const width = parseInt(stream?.width, 10) || null;
    const height = parseInt(stream?.height, 10) || null;
    const codec = stream?.codec_name || null;

    return {
      duration: duration != null ? Math.round(duration * 10) / 10 : null,
      width,
      height,
      codec,
    };
  } catch {
    return { duration: null, width: null, height: null, codec: null };
  }
}
