import { Screen } from 'electrobun/bun'

const FRAME_TOLERANCE_PX = 4
// Win32 DWM invisible borders sit outside the client work area; Electrobun's
// maximized frame includes those overhangs, so we treat this adjusted rect as
// the canonical "maximized to work area" geometry.
const WIN32_FRAME_OVERHANG_NATIVE = {
  x: -8,
  y: 0,
  width: 16,
  height: 8
}
const WIN32_FRAME_OVERHANG_CEF = {
  x: -12,
  y: 0,
  width: 24,
  height: 12
}

function getWin32FrameOverhang(window) {
  return window?.renderer === 'cef'
    ? WIN32_FRAME_OVERHANG_CEF
    : WIN32_FRAME_OVERHANG_NATIVE
}

function framesMatch(a, b, tolerance = FRAME_TOLERANCE_PX) {
  return (
    Math.abs(a.x - b.x) <= tolerance &&
    Math.abs(a.y - b.y) <= tolerance &&
    Math.abs(a.width - b.width) <= tolerance &&
    Math.abs(a.height - b.height) <= tolerance
  )
}

function getMaximizedWorkAreaFrame(workArea, window) {
  const overhang = getWin32FrameOverhang(window)
  return {
    x: workArea.x + overhang.x,
    y: workArea.y + overhang.y,
    width: workArea.width + overhang.width,
    height: workArea.height + overhang.height
  }
}

function getFrameCenter(frame) {
  return {
    x: frame.x + frame.width / 2,
    y: frame.y + frame.height / 2
  }
}

function getDisplayForFrame(frame) {
  const { x, y } = getFrameCenter(frame)
  const displays = Screen.getAllDisplays()

  const match = displays.find(({ bounds }) => {
    return (
      x >= bounds.x &&
      x < bounds.x + bounds.width &&
      y >= bounds.y &&
      y < bounds.y + bounds.height
    )
  })

  return match ?? Screen.getPrimaryDisplay()
}

function frameCoversMonitor(frame, bounds) {
  return (
    frame.x <= bounds.x + FRAME_TOLERANCE_PX &&
    frame.y <= bounds.y + FRAME_TOLERANCE_PX &&
    frame.x + frame.width >= bounds.x + bounds.width - FRAME_TOLERANCE_PX &&
    frame.y + frame.height >= bounds.y + bounds.height - FRAME_TOLERANCE_PX
  )
}

export function isWindowWorkAreaMaximized(window) {
  if (!window?.getFrame) {
    return false
  }

  const frame = window.getFrame()
  const { workArea } = getDisplayForFrame(frame)
  return (
    framesMatch(frame, workArea) ||
    framesMatch(frame, getMaximizedWorkAreaFrame(workArea, window))
  )
}

export function clampWindowToWorkArea(window) {
  if (!window?.getFrame || !window?.setFrame) {
    return false
  }

  if (window.isFullScreen?.()) {
    return false
  }

  const frame = window.getFrame()
  if (!frame.width || !frame.height) {
    return false
  }

  const display = getDisplayForFrame(frame)
  const { bounds, workArea } = display
  const maximizedFrame = getMaximizedWorkAreaFrame(workArea, window)

  if (framesMatch(frame, workArea) || framesMatch(frame, maximizedFrame)) {
    return false
  }

  if (!frameCoversMonitor(frame, bounds)) {
    return false
  }

  window.setFrame(
    maximizedFrame.x,
    maximizedFrame.y,
    maximizedFrame.width,
    maximizedFrame.height
  )
  return true
}
