import "server-only";

import { runFfmpegAndExpectFile } from "@/lib/ffmpeg/ffmpeg";
import { createTempOutputPath } from "@/lib/uploads/temp-files";
import { MediaProcessingError } from "@/lib/server/media-errors";
import type { FrameExtractionResult, FrameOutputFormat } from "@/types/media-processing";

interface ExtractFrameOptions {
  inputPath: string;
  timestampSeconds: number;
  outputFormat: FrameOutputFormat;
  outputPath?: string;
  filters?: string[];
}

export async function extractFrame({
  inputPath,
  timestampSeconds,
  outputFormat,
  outputPath,
  filters = []
}: ExtractFrameOptions): Promise<FrameExtractionResult> {
  if (!Number.isFinite(timestampSeconds) || timestampSeconds < 0) {
    throw new MediaProcessingError({
      message: "Frame extraction timestamp must be a positive number.",
      code: "invalid_input",
      statusCode: 400
    });
  }

  const finalOutputPath =
    outputPath ||
    (await createTempOutputPath({
      extension: outputFormat,
      prefix: "frame"
    }));

  const args = [
    "-hide_banner",
    "-loglevel",
    "error",
    "-y",
    "-i",
    inputPath,
    "-ss",
    timestampSeconds.toFixed(3)
  ];

  if (filters.length > 0) {
    args.push("-vf", filters.join(","));
  }

  args.push("-frames:v", "1");

  if (outputFormat === "jpg") {
    args.push("-q:v", "2");
  }

  args.push(finalOutputPath);

  await runFfmpegAndExpectFile(args, finalOutputPath);

  return {
    outputPath: finalOutputPath,
    format: outputFormat,
    timestampSeconds
  };
}
