/**
 * Utilitários de captura de canvas 3D — M9.3
 *
 * Funções determinísticas (sem dependência de React) para:
 *  - Extrair data URL de um canvas 2D/WebGL
 *  - Redimensionar a imagem para uma largura máxima (preservando aspect ratio)
 *  - Validar formato/qualidade
 *
 * Funciona com qualquer HTMLCanvasElement (incluindo R3F, Konva, D3).
 * Para canvas WebGL, o browser exige que `preserveDrawingBuffer: true`
 * seja passado ao `getContext('webgl2')` OU que a captura seja feita
 * imediatamente após o frame renderizado. Como R3F usa o loop de
 * animação do `useFrame`, a captura dentro do mesmo frame funciona.
 *
 * Dica: para WebGL, chamar `gl.flush()` ou renderizar um frame extra
 * antes de `toDataURL` evita canvas em branco.
 */

export interface CaptureOptions {
  /** Formato de saída. Padrão: 'png' */
  format?: 'png' | 'jpeg' | 'webp';
  /** Qualidade JPEG/WebP (0–1). Ignorado para PNG. Padrão: 0.92 */
  quality?: number;
  /** Largura máxima do PNG final (px). 0 = sem redimensionamento */
  maxWidth?: number;
  /** Altura máxima do PNG final (px). 0 = sem limite */
  maxHeight?: number;
}

/**
 * Converte um HTMLCanvasElement em data URL.
 *
 * Para PNG, o segundo argumento é ignorado. Para JPEG/WebP, `quality`
 * controla a compressão (1 = sem perda, 0 = máxima compressão).
 */
export function canvasToDataURL(
  canvas: HTMLCanvasElement,
  format: 'png' | 'jpeg' | 'webp' = 'png',
  quality = 0.92,
): string {
  if (!canvas) throw new Error('canvas é null');
  const mime = `image/${format}`;
  return canvas.toDataURL(mime, quality);
}

/**
 * Captura e opcionalmente redimensiona a imagem do canvas.
 *
 * Usa um canvas 2D temporário para escalar, preservando a proporção.
 * Retorna a data URL final pronta para嵌入 em `<Image src=...>` ou PDF.
 */
export async function captureCanvasImage(
  canvas: HTMLCanvasElement,
  options: CaptureOptions = {},
): Promise<string> {
  const { format = 'png', quality = 0.92, maxWidth = 0, maxHeight = 0 } = options;

  const srcW = canvas.width;
  const srcH = canvas.height;

  let outW = srcW;
  let outH = srcH;

  if (maxWidth > 0 && maxHeight > 0) {
    const ratio = Math.min(maxWidth / srcW, maxHeight / srcH);
    outW = Math.round(srcW * ratio);
    outH = Math.round(srcH * ratio);
  } else if (maxWidth > 0) {
    outW = Math.min(maxWidth, srcW);
    outH = Math.round((outW / srcW) * srcH);
  } else if (maxHeight > 0) {
    outH = Math.min(maxHeight, srcH);
    outW = Math.round((outH / srcH) * srcW);
  }

  if (outW === srcW && outH === srcH) {
    return canvasToDataURL(canvas, format, quality);
  }

  const off = document.createElement('canvas');
  off.width = outW;
  off.height = outH;
  const ctx = off.getContext('2d');
  if (!ctx) throw new Error('Não foi possível criar contexto 2D');

  ctx.imageSmoothingEnabled = true;
  ctx.imageSmoothingQuality = 'high';
  ctx.drawImage(canvas, 0, 0, outW, outH);

  return off.toDataURL(`image/${format}`, quality);
}

/**
 * Faz o download da imagem capturada.
 */
export function downloadImage(dataUrl: string, filename: string): void {
  const link = document.createElement('a');
  link.setAttribute('href', dataUrl);
  link.setAttribute('download', filename);
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

/**
 * Estima o tamanho da data URL em KB (útil para preview).
 */
export function estimateDataUrlSizeKB(dataUrl: string): number {
  const commaIdx = dataUrl.indexOf(',');
  if (commaIdx < 0) return 0;
  const base64 = dataUrl.slice(commaIdx + 1);
  return Math.round((base64.length * 3) / 4 / 1024);
}

/**
 * Converte data URL em Blob (útil para upload ou PDF embed).
 */
export async function dataURLtoBlob(dataUrl: string): Promise<Blob> {
  const res = await fetch(dataUrl);
  return res.blob();
}