/**
 * Center-crop an image source to a square and downscale it to a JPEG suitable
 * for an avatar. Avatars never render larger than ~80px, so 512px is generous
 * headroom while keeping the upload to a few tens of KB regardless of input.
 *
 * Pass `mirror` when capturing from a (mirrored) webcam preview so the saved
 * image matches what the user saw.
 */
export async function toAvatarBlob(
  source: ImageBitmap,
  { size = 512, mirror = false }: { size?: number; mirror?: boolean } = {},
): Promise<Blob> {
  if (!Number.isInteger(size) || size <= 0) {
    throw new Error('Avatar size must be a positive integer');
  }
  const side = Math.min(source.width, source.height);
  if (side === 0) {
    // A not-yet-decoded <video> or a corrupt image yields a zero-size source;
    // cropping it would silently produce a blank avatar, so fail instead.
    throw new Error('Image source has zero dimensions');
  }
  const sx = (source.width - side) / 2;
  const sy = (source.height - side) / 2;

  const canvas = new OffscreenCanvas(size, size);
  const ctx = canvas.getContext('2d');
  if (!ctx) throw new Error('Failed to acquire 2D canvas context');

  if (mirror) {
    ctx.translate(size, 0);
    ctx.scale(-1, 1);
  }
  ctx.drawImage(source, sx, sy, side, side, 0, 0, size, size);

  return canvas.convertToBlob({ type: 'image/jpeg', quality: 0.82 });
}
