/**
 * Integration test for video-frames against the real ffmpeg/ffprobe binaries.
 * Skipped in CI: only runs when `RUN_FFMPEG_TESTS=true` is set in env. Generates
 * a tiny throwaway fixture via `ffmpeg -f lavfi`, then asserts the extraction
 * produces at least one valid JPEG.
 */
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import {
  buildDefaultVideoFrameOptions,
  extractVideoFrames,
  isFfmpegAvailable,
  resetFfmpegAvailabilityCache,
} from "@/utils/video-frames.js";
import { mockLogger } from "../_helpers/mock-logger.js";

const ENABLED = process.env.RUN_FFMPEG_TESTS === "true";

let workDir: string;
let inputPath: string;
let outDir: string;

beforeAll(async () => {
  if (!ENABLED) return;
  resetFfmpegAvailabilityCache();
  workDir = mkdtempSync(join(tmpdir(), "video-frames-it-"));
  inputPath = join(workDir, "fixture.mp4");
  outDir = join(workDir, "frames");
  // Generate a 3s, 10fps, 320x240 testsrc video via ffmpeg lavfi (no committed binary)
  const proc = Bun.spawn(
    [
      "ffmpeg",
      "-y",
      "-f",
      "lavfi",
      "-i",
      "testsrc=duration=3:size=320x240:rate=10",
      "-pix_fmt",
      "yuv420p",
      inputPath,
    ],
    { stdout: "ignore", stderr: "ignore" },
  );
  const exit = await proc.exited;
  if (exit !== 0) {
    throw new Error(`Failed to generate fixture mp4 (exit ${exit})`);
  }
});

afterAll(() => {
  if (workDir) rmSync(workDir, { recursive: true, force: true });
});

describe.skipIf(!ENABLED)("video-frames integration (real ffmpeg)", () => {
  test("isFfmpegAvailable resolves true with system ffmpeg/ffprobe", async () => {
    const ok = await isFfmpegAvailable("ffmpeg", "ffprobe", mockLogger());
    expect(ok).toBe(true);
  });

  test("extractVideoFrames produces at least one valid JPEG from the fixture", async () => {
    mkdirSync(outDir, { recursive: true });
    const opts = buildDefaultVideoFrameOptions("ffmpeg", "ffprobe", { maxFrames: 5 });
    const result = await extractVideoFrames(inputPath, outDir, opts, mockLogger());

    expect(result.frames.length).toBeGreaterThan(0);
    expect(result.durationSec).toBeGreaterThan(2);
    for (const frame of result.frames) {
      const path = join(outDir, frame.filename);
      expect(existsSync(path)).toBe(true);
      const head = readFileSync(path).subarray(0, 3);
      expect(head[0]).toBe(0xff);
      expect(head[1]).toBe(0xd8);
      expect(head[2]).toBe(0xff);
    }
  });
});
