export function getZoomFactor(): number {
  const app = document.getElementById('app')
  if (!app) return 1
  const zoom = (app.style as any).zoom
  return zoom ? parseFloat(zoom) / 100 : 1
}

// Cached probe results for fixed-position coordinate mapping inside #app.
// CSS zoom behavior with position:fixed varies across Chromium versions,
// so we detect the actual behavior at runtime with a probe element.
let _probeCache: { scaleX: number; scaleY: number; offsetX: number; offsetY: number; zoomKey: string } | null = null

export function getFixedPositionMapping(): { scaleX: number; scaleY: number; offsetX: number; offsetY: number } {
  const app = document.getElementById('app')
  if (!app) return { scaleX: 1, scaleY: 1, offsetX: 0, offsetY: 0 }

  const zoomKey = (app.style as any).zoom || ''
  if (_probeCache && _probeCache.zoomKey === zoomKey) {
    return _probeCache
  }

  const probe = document.createElement('div')
  probe.style.cssText = 'position:fixed;top:0;left:0;width:100px;height:100px;visibility:hidden;pointer-events:none'
  app.appendChild(probe)
  const r0 = probe.getBoundingClientRect()
  probe.style.top = '100px'
  probe.style.left = '100px'
  const r1 = probe.getBoundingClientRect()
  app.removeChild(probe)

  const result = {
    scaleX: (r1.left - r0.left) / 100,
    scaleY: (r1.top - r0.top) / 100,
    offsetX: r0.left,
    offsetY: r0.top,
    zoomKey,
  }
  _probeCache = result
  return result
}

export function resetPositionCache() {
  _probeCache = null
}

export function computeDropdownPosition(
  triggerEl: HTMLElement,
  opts?: { minWidth?: number; estimatedHeight?: number; panelEl?: HTMLElement | null }
): Record<string, string> {
  const rect = triggerEl.getBoundingClientRect()
  const { scaleX, scaleY, offsetX, offsetY } = getFixedPositionMapping()
  const gap = 4

  const minW = (opts?.minWidth ?? 0) * scaleX
  const vpH = window.innerHeight
  const vpW = window.innerWidth

  // Default: position below trigger
  let topVP = rect.bottom + gap

  // Use offsetHeight (unaffected by CSS transition transforms like scale(0.95))
  // and multiply by scaleY to get viewport pixels.
  const panelEl = opts?.panelEl
  if (panelEl) {
    const panelH = panelEl.offsetHeight * scaleY
    if (topVP + panelH > vpH && rect.top - gap - panelH >= 0) {
      topVP = rect.top - gap - panelH
    }
  }

  let leftVP = rect.left
  const widthVP = Math.max(rect.width, minW)
  if (leftVP + widthVP > vpW - gap) {
    leftVP = vpW - gap - widthVP
  }
  if (leftVP < gap) leftVP = gap

  // Convert viewport pixels to CSS pixels for position:fixed inside #app
  return {
    position: 'fixed',
    top: `${(topVP - offsetY) / scaleY}px`,
    left: `${(leftVP - offsetX) / scaleX}px`,
    width: `${widthVP / scaleX}px`,
    zIndex: '9999',
  }
}
