import path from "path";
import { bundle } from "@remotion/bundler";
import { renderMedia, selectComposition } from "@remotion/renderer";

export * from "./compositions/index";

let cachedBundlePath: string | null = null;

export async function getBundlePath(): Promise<string> {
  if (cachedBundlePath) {
    return cachedBundlePath;
  }
  const entryPoint = path.resolve(__dirname, "Root.tsx");
  cachedBundlePath = await bundle({ entryPoint });
  return cachedBundlePath;
}

export interface RenderPresentationOptions {
  serveUrl: string;
  input: Record<string, unknown>;
  onProgress: (progress: number) => void;
  browserExecutable?: string;
}

export interface RenderPresentationResult {
  buffer: Buffer;
  durationInFrames: number;
  fps: number;
  inputProps: Record<string, unknown>;
}

export async function renderPresentationComposition(
  opts: RenderPresentationOptions,
): Promise<RenderPresentationResult> {
  const { serveUrl, input, onProgress, browserExecutable } = opts;

  const compositionId = input["videoType"] === "demo" ? "DemoVideo" : "PitchDeck";

  const composition = await selectComposition({
    serveUrl,
    id: compositionId,
    inputProps: input,
    ...(browserExecutable ? { browserExecutable } : {}),
  });

  const result = await renderMedia({
    composition,
    serveUrl,
    codec: "h264",
    concurrency: 1,
    inputProps: input,
    outputLocation: null,
    ...(browserExecutable ? { browserExecutable } : {}),
    onProgress: ({ progress }) => {
      onProgress(Math.round(progress * 100));
    },
  });

  if (!result.buffer) {
    throw new Error("renderMedia returned null buffer");
  }

  return {
    buffer: result.buffer,
    durationInFrames: composition.durationInFrames,
    fps: composition.fps,
    inputProps: input,
  };
}
