// @ts-nocheck
export async function compressPhoto(
  file: File,
  opts: { targetBytes?: number; maxEdge?: number; qualityStart?: number } = {}
): Promise<File> {
  const targetBytes = opts.targetBytes ?? 1_500_000; // 1.5 MB
  const maxEdge = opts.maxEdge ?? 2560;
  const qualityStart = opts.qualityStart ?? 0.85;

  // If already small and jpeg, return as-is
  if (file.size <= targetBytes && file.type === 'image/jpeg') return file;

  const img = await loadImageBitmap(file);
  const { width, height } = fitWithin(img.width, img.height, maxEdge);

  const canvas = createCanvas(width, height);
  const ctx = canvas.getContext('2d');
  if (!ctx) throw new Error('Canvas unsupported');
  ctx.drawImage(img, 0, 0, width, height);

  // Iteratively lower quality to fit target size
  let quality = qualityStart;
  let blob: Blob | null = await toBlob(canvas, 'image/jpeg', quality);
  if (!blob) throw new Error('Failed to encode image');

  while (blob.size > targetBytes && quality > 0.5) {
    quality -= 0.05;
    const attempt = await toBlob(canvas, 'image/jpeg', quality);
    if (attempt) blob = attempt;
    else break;
  }

  // If still too large, downscale further by 0.9 until it fits or edge < 800
  let currentWidth = width;
  let currentHeight = height;
  while (blob.size > targetBytes && Math.max(currentWidth, currentHeight) > 800) {
    currentWidth = Math.round(currentWidth * 0.9);
    currentHeight = Math.round(currentHeight * 0.9);
    const c2 = createCanvas(currentWidth, currentHeight);
    const c2ctx = c2.getContext('2d');
    if (!c2ctx) break;
    c2ctx.drawImage(canvas, 0, 0, currentWidth, currentHeight);
    const attempt = await toBlob(c2, 'image/jpeg', quality);
    if (attempt) blob = attempt;
  }

  const outName = ensureJpegExtension(file.name);
  return new File([blob], outName, { type: 'image/jpeg', lastModified: Date.now() });
}

function fitWithin(w: number, h: number, maxEdge: number) {
  const scale = Math.min(1, maxEdge / Math.max(w, h));
  return { width: Math.round(w * scale), height: Math.round(h * scale) };
}

function createCanvas(w: number, h: number): HTMLCanvasElement {
  const c = document.createElement('canvas');
  c.width = w; c.height = h; return c;
}

function toBlob(canvas: HTMLCanvasElement, type: string, quality: number): Promise<Blob | null> {
  return new Promise(resolve => canvas.toBlob(resolve, type, quality));
}

async function loadImageBitmap(file: File): Promise<CanvasImageSource> {
  const canBitmap = 'createImageBitmap' in window;

  if (canBitmap) {
    try {
      return await createImageBitmap(file);
    } catch (error) {
      console.warn('Falling back to HTML image decode', error);
    }
  }

  return await loadHtmlImage(file);
}

function loadHtmlImage(file: File): Promise<HTMLImageElement> {
  return new Promise((resolve, reject) => {
    const url = URL.createObjectURL(file);
    const img = new Image();
    img.onload = () => { URL.revokeObjectURL(url); resolve(img); };
    img.onerror = (e) => { URL.revokeObjectURL(url); reject(e); };
    img.src = url;
  });
}

function ensureJpegExtension(name: string) {
  return name.replace(/\.(heic|heif|png|webp|jpg|jpeg)$/i, '') + '.jpg';
}

export function formatBytes(bytes: number) {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
}
