import { DOCS_GRAPHIC_DEFAULTS } from "./docs-graphic-types.ts"
import { GRAPHIC_KEYBOARD_MIN_SIZE } from "./docs-graphic-keyboard.ts"

/** Max frame width when inserting large photos into the page body. */
export const DOCS_IMAGE_INSERT_MAX_WIDTH_PX = 560

/** Max frame height when inserting very tall images. */
export const DOCS_IMAGE_INSERT_MAX_HEIGHT_PX = 720

export type ImageNaturalSize = {
  width: number
  height: number
}

/** Frame size that preserves the source aspect ratio, scaled down when needed. */
export function computeImageInsertFrameSize(
  naturalWidth: number,
  naturalHeight: number,
  options: {
    maxWidth?: number
    maxHeight?: number
    minSize?: number
  } = {}
): ImageNaturalSize {
  const maxWidth = options.maxWidth ?? DOCS_IMAGE_INSERT_MAX_WIDTH_PX
  const maxHeight = options.maxHeight ?? DOCS_IMAGE_INSERT_MAX_HEIGHT_PX
  const minSize = options.minSize ?? GRAPHIC_KEYBOARD_MIN_SIZE

  if (naturalWidth <= 0 || naturalHeight <= 0) {
    return {
      width: DOCS_GRAPHIC_DEFAULTS.width,
      height: DOCS_GRAPHIC_DEFAULTS.height,
    }
  }

  const scale = Math.min(1, maxWidth / naturalWidth, maxHeight / naturalHeight)
  let width = Math.max(minSize, Math.round(naturalWidth * scale))
  let height = Math.max(minSize, Math.round(naturalHeight * scale))

  // Keep ratio after integer rounding (derive height from width).
  height = Math.max(minSize, Math.round(width * (naturalHeight / naturalWidth)))
  if (height > maxHeight) {
    height = maxHeight
    width = Math.max(minSize, Math.round(height * (naturalWidth / naturalHeight)))
  }

  return { width, height }
}

/** Load intrinsic pixel dimensions for a data URL or remote image src. */
export function readImageNaturalSize(src: string): Promise<ImageNaturalSize> {
  if (typeof Image === "undefined") {
    return Promise.resolve({
      width: DOCS_GRAPHIC_DEFAULTS.width,
      height: DOCS_GRAPHIC_DEFAULTS.height,
    })
  }

  return new Promise((resolve, reject) => {
    const img = new Image()
    img.onload = () => {
      resolve({
        width: img.naturalWidth,
        height: img.naturalHeight,
      })
    }
    img.onerror = () => reject(new Error("Failed to read image dimensions"))
    img.src = src
  })
}
