import { fal } from "@fal-ai/client";
import { execFileSync } from "node:child_process";
import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
import path from "node:path";

if (!process.env.FAL_KEY) throw new Error("FAL_KEY is missing. Add it to .env.local.");
const root = process.cwd();
const config = JSON.parse(await readFile(path.join(root, "assets-generation/videos.config.json"), "utf8"));

for (const asset of config) {
  console.log(`Generating ${asset.id} with ${asset.model}...`);
  const source = await readFile(path.join(root, asset.sourceImage));
  const extension = path.extname(asset.sourceImage).slice(1).toLowerCase();
  const mime = extension === "jpg" || extension === "jpeg" ? "image/jpeg" : `image/${extension}`;
  const imageUrl = `data:${mime};base64,${source.toString("base64")}`;
  const result = await fal.subscribe(asset.model, {
    input: {
      prompt: asset.prompt,
      image_url: imageUrl,
      duration: asset.duration,
      negative_prompt: "blur, distort, low quality, morphing, text, logo, watermark",
      cfg_scale: 0.5
    },
    logs: true,
    onQueueUpdate(update) {
      if (update.status === "IN_PROGRESS") process.stdout.write(".");
    }
  });
  const url = result.data?.video?.url;
  if (!url) throw new Error(`No video returned for ${asset.id}`);
  const response = await fetch(url);
  if (!response.ok) throw new Error(`Could not download ${asset.id}: ${response.status}`);
  const destination = path.join(root, asset.destination);
  const rawDestination = destination.replace(/\.mp4$/i, ".raw.mp4");
  await mkdir(path.dirname(destination), { recursive: true });
  await writeFile(rawDestination, Buffer.from(await response.arrayBuffer()));
  console.log(" optimizing to an exact 15-second web MP4...");
  execFileSync("ffmpeg", [
    "-y", "-stream_loop", "2", "-i", rawDestination, "-t", "15", "-an",
    "-vf", "scale='min(1280,iw)':-2:flags=lanczos,fps=24,format=yuv420p",
    "-c:v", "libx264", "-preset", "slow", "-crf", "28",
    "-movflags", "+faststart", destination
  ], { stdio: "ignore" });
  await unlink(rawDestination);
  console.log(`Saved ${asset.destination}`);
}
