/**
 * Image-loading helpers used by photo upload and slot assignment.
 *
 * Before this module: `useTemplate.assignImageToSlot` and `UploadTab.getImageSize`
 * each had their own inline `new Image() + onload + onerror` Promise wrapper,
 * and `App.handlePhotoEditComplete` had a third variant using callbacks
 * instead of a Promise. The three wrappers had subtly different error
 * handling — one rejected with a generic message, another logged to the
 * console, the third silently swallowed errors and used a fallback path.
 *
 * Centralizing here gives every caller the same behavior: a clean Promise
 * that resolves to dimensions or rejects with a descriptive Error. The
 * App.jsx photo-edit flow still uses the lower-level callback form because
 * its onload handler runs synchronously before its setEditingElement call
 * (timing matters for the Filerobot modal teardown sequence) — but the
 * other two consumers go through `loadImageDimensions`.
 */

/**
 * Load an image and resolve to its natural pixel dimensions.
 *
 * Resolves with `{ width, height }` from `naturalWidth`/`naturalHeight`,
 * falling back to `width`/`height` for the rare case where naturalWidth is 0
 * (some Safari versions report this for SVG sources without intrinsic size).
 *
 * Rejects with a descriptive Error if the image fails to load. Callers
 * should `await` and use try/catch — not `.then(undefined, () => fallback)`,
 * which would silently mask bugs.
 *
 * @param {string} src - data:, blob:, or remote URL
 * @returns {Promise<{ width: number, height: number }>}
 */
export function loadImageDimensions(src) {
  return new Promise((resolve, reject) => {
    const img = new window.Image();
    img.onload = () => resolve({
      width: img.naturalWidth || img.width,
      height: img.naturalHeight || img.height,
    });
    img.onerror = () => reject(new Error(`Failed to load image: ${truncate(src, 80)}`));
    img.src = src;
  });
}

/**
 * Truncate a URL for use in error messages. Long data: URLs in stack traces
 * blow up log readers; the first 80 chars are enough to identify the type.
 */
function truncate(s, n) {
  if (typeof s !== 'string') return String(s);
  return s.length > n ? `${s.slice(0, n)}…` : s;
}
