const fs = require('node:fs');
const path = require('node:path');
const ffmpeg = require('fluent-ffmpeg');
const { emitEvent, writeJson } = require('./workspace.cjs');

try {
  ffmpeg.setFfmpegPath(require('@ffmpeg-installer/ffmpeg').path);
  ffmpeg.setFfprobePath(require('@ffprobe-installer/ffprobe').path);
} catch {
  // Use PATH ffmpeg/ffprobe.
}

function probeVideo(videoPath) {
  return new Promise((resolve, reject) => {
    ffmpeg.ffprobe(videoPath, (error, data) => {
      if (error) reject(error);
      else resolve(data);
    });
  });
}

function runExtract(videoPath, pattern, fps, quality) {
  return new Promise((resolve, reject) => {
    ffmpeg(videoPath)
      .outputOptions(['-vf', `fps=${fps}`, '-q:v', String(Math.max(2, Math.round((100 - quality) / 5) || 2))])
      .output(pattern)
      .on('end', resolve)
      .on('error', reject)
      .run();
  });
}

async function extractFrames({ workspace, videoPath, fps = 5, quality = 90 }) {
  emitEvent('frames', 'extracting frames', { fps, quality });
  const framesDir = path.join(workspace.workspacePath, 'frames');
  fs.mkdirSync(framesDir, { recursive: true });
  for (const file of fs.readdirSync(framesDir)) fs.rmSync(path.join(framesDir, file), { force: true });

  const meta = await probeVideo(videoPath);
  const stream = (meta.streams || []).find(item => item.codec_type === 'video') || {};
  const duration = Number(meta.format?.duration || stream.duration || 0);
  const resolution = `${stream.width || 0}x${stream.height || 0}`;
  const pattern = path.join(framesDir, 'frame_%06d.jpg');
  await runExtract(videoPath, pattern, fps, quality);

  const files = fs.readdirSync(framesDir).filter(file => /\.jpe?g$/i.test(file)).sort();
  const frames = files.map((file, index) => ({
    index: index + 1,
    timestamp: Number((index / fps).toFixed(2)),
    path: path.join(framesDir, file),
    relativePath: `frames/${file}`,
  }));
  const videoInfo = {
    videoPath,
    duration,
    resolution,
    extractFps: fps,
    extractedFrames: frames.length,
  };
  writeJson(workspace, 'video_info.json', { videoInfo, frames });
  emitEvent('frames', 'frames extracted', { frameCount: frames.length, duration, resolution });
  if (frames.length === 0) throw new Error('视频无法抽帧');
  return { videoInfo, frames };
}

module.exports = { extractFrames, probeVideo };
