const VIDEO_BITRATES = Object.freeze({
  medium: '5M',
  high: '10M',
  ultra: '20M',
});

export function exportTimeRange(range, duration, loop) {
  const fullEnd = Number.isFinite(duration) && duration > 0 ? duration : 60;
  if (range === 'loop' && loop?.enabled) {
    const start = Math.max(0, Number(loop.start) || 0);
    const end = Math.max(start, Number(loop.end) || start);
    return { start, end, duration: end - start };
  }
  return { start: 0, end: fullEnd, duration: fullEnd };
}

export function exportBitrate(quality) {
  return VIDEO_BITRATES[quality] || VIDEO_BITRATES.high;
}

export function exportFrameCount(duration, fps) {
  return Math.max(0, Math.ceil(duration * fps));
}

export function exportChunkFrameCount(width, height, {
  targetPixelFrames = 1920 * 1080 * 120,
  minimum = 24,
  maximum = 180,
} = {}) {
  const pixels = Math.max(1, Number(width) * Number(height));
  const estimate = Math.floor(targetPixelFrames / pixels);
  return Math.max(minimum, Math.min(maximum, estimate));
}

export function exportChunkRanges(totalFrames, framesPerChunk) {
  const total = Math.max(0, Math.floor(Number(totalFrames) || 0));
  const chunkSize = Math.max(1, Math.floor(Number(framesPerChunk) || 1));
  const ranges = [];
  for (let start = 0; start < total; start += chunkSize) {
    ranges.push({
      start,
      end: Math.min(total, start + chunkSize),
      count: Math.min(chunkSize, total - start),
    });
  }
  return ranges;
}

export function buildFfmpegChunkArgs({
  fps,
  bitrate,
  inputPattern,
  frameCount,
  output,
}) {
  return [
    '-framerate', String(fps),
    '-start_number', '0',
    '-i', inputPattern,
    '-frames:v', String(frameCount),
    '-an',
    '-c:v', 'libx264',
    '-preset', 'fast',
    '-b:v', bitrate,
    '-pix_fmt', 'yuv420p',
    '-movflags', '+faststart',
    '-y', output,
  ];
}

export function buildFfmpegConcatArgs({ listFile, output }) {
  return [
    '-f', 'concat',
    '-safe', '0',
    '-i', listFile,
    '-c', 'copy',
    '-movflags', '+faststart',
    '-y', output,
  ];
}

export function buildFfmpegMuxArgs({
  videoFile,
  audioFile,
  duration,
  output = 'output.mp4',
}) {
  return [
    '-i', videoFile,
    '-i', audioFile,
    '-c:v', 'copy',
    '-c:a', 'aac',
    '-b:a', '192k',
    '-t', String(duration),
    '-shortest',
    '-movflags', '+faststart',
    '-y', output,
  ];
}

export function exportErrorMessage(error, fallback = 'Unknown export error') {
  if (error instanceof Error && error.message) return error.message;
  if (typeof error === 'string' && error.trim()) return error;
  if (error && typeof error.message === 'string' && error.message.trim()) {
    return error.message;
  }
  try {
    const serialized = JSON.stringify(error);
    if (serialized && serialized !== '{}') return serialized;
  } catch {}
  return fallback;
}

export function buildFfmpegArgs({ fps, bitrate, audio = null, output = 'output.mp4' }) {
  const args = [
    '-framerate', String(fps),
    '-i', 'frame%06d.jpg',
    '-c:v', 'libx264',
    '-preset', 'fast',
    '-b:v', bitrate,
    '-pix_fmt', 'yuv420p',
  ];
  if (audio) {
    args.push(
      '-i', audio.file,
      '-ss', String(audio.start),
      '-t', String(audio.duration),
      '-c:a', 'aac',
      '-b:a', '192k',
      '-shortest',
    );
  }
  args.push('-y', output);
  return args;
}
