import type { ReadOnlyRect } from '@/lib/litegraph/src/interfaces'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'

interface FitToViewOptions {
  selectionOnly?: boolean
  zoom?: number
  padding?: number
}

/**
 * Instantly fits the canvas view to graph content without waiting for UI animation.
 *
 * Lives outside the shared fixture to keep the default ComfyPage interactions user-oriented.
 */
export async function fitToViewInstant(
  comfyPage: ComfyPage,
  options: FitToViewOptions = {}
) {
  const { selectionOnly = false, zoom = 0.75, padding = 10 } = options

  const rectangles = await comfyPage.page.evaluate<
    ReadOnlyRect[] | null,
    { selectionOnly: boolean }
  >(
    ({ selectionOnly }) => {
      const app = window.app
      if (!app?.canvas) return null

      const canvas = app.canvas
      const items = (() => {
        if (selectionOnly && canvas.selectedItems?.size) {
          return Array.from(canvas.selectedItems)
        }
        try {
          return Array.from(canvas.positionableItems ?? [])
        } catch {
          return []
        }
      })()

      if (!items.length) return null

      const rects: ReadOnlyRect[] = []

      for (const item of items) {
        const rect = item?.boundingRect
        if (!rect) continue

        const x = Number(rect[0])
        const y = Number(rect[1])
        const width = Number(rect[2])
        const height = Number(rect[3])

        rects.push([x, y, width, height] as const)
      }

      return rects.length ? rects : null
    },
    { selectionOnly }
  )

  if (!rectangles || rectangles.length === 0) return

  let minX = Infinity
  let minY = Infinity
  let maxX = -Infinity
  let maxY = -Infinity

  for (const [x, y, width, height] of rectangles) {
    minX = Math.min(minX, Number(x))
    minY = Math.min(minY, Number(y))
    maxX = Math.max(maxX, Number(x) + Number(width))
    maxY = Math.max(maxY, Number(y) + Number(height))
  }

  const hasFiniteBounds =
    Number.isFinite(minX) &&
    Number.isFinite(minY) &&
    Number.isFinite(maxX) &&
    Number.isFinite(maxY)

  if (!hasFiniteBounds) return

  const bounds: ReadOnlyRect = [
    minX - padding,
    minY - padding,
    maxX - minX + 2 * padding,
    maxY - minY + 2 * padding
  ]

  await comfyPage.page.evaluate(
    ({ bounds, zoom }) => {
      const app = window.app
      if (!app?.canvas) return

      const canvas = app.canvas
      canvas.ds.fitToBounds(bounds, { zoom })
      canvas.setDirty(true, true)
    },
    { bounds, zoom }
  )

  await comfyPage.nextFrame()
}
