// Desktop HID-wedge scanner capture for the /integrations terminal pages.
//
// Encapsulates the returns-desktop.vue pattern (global keydown → focus a hidden
// off-screen input so a USB scanner works without manual focus) and fixes its
// keepalive flaw: app.vue renders <NuxtPage :keepalive="{ max: 10 }"> which
// OVERRIDES page-level `keepalive: false`, so terminal pages stay mounted after
// navigating away. Binding only in onMounted/onBeforeUnmount leaves up to 10
// cached pages fighting over every keystroke. This composable binds in
// onMounted+onActivated and unbinds in onDeactivated+onBeforeUnmount, and the
// handler additionally checks that this page's route is still the active one.
//
// The page still owns: the hidden <input> element (position it off-screen),
// its v-model scan buffer, and all Enter/step dispatching via `onEnter`.

import type { Ref } from 'vue'

export interface UseDesktopScannerOptions {
  /** Template ref of the hidden off-screen input the scanner types into. */
  input: Ref<HTMLInputElement | null>
  /** Master switch; when false the handler ignores everything. Default true. */
  enabled?: Ref<boolean> | (() => boolean)
  /** Return true while any modal/overlay is open or a form-heavy step is active. */
  isBlocked?: () => boolean
  /** Enter pressed outside a real input — dispatch by step; call e.preventDefault() yourself. */
  onEnter?: (e: KeyboardEvent) => void
}

export function useDesktopScanner (opts: UseDesktopScannerOptions) {
  const router = useRouter()
  // Captured once at setup: the path this page instance owns.
  const ownPath = router.currentRoute.value.path

  const isActive = ref(false)
  let bound = false

  const isEnabled = () => {
    const e = opts.enabled
    if (e === undefined) return true
    return typeof e === 'function' ? e() : e.value !== false
  }

  const focusInput = () => {
    if (!isActive.value) return
    try { opts.input.value?.focus() } catch { /* detached ref */ }
  }

  const onWindowKeydown = (e: KeyboardEvent) => {
    if (!isActive.value) return
    if (router.currentRoute.value.path !== ownPath) return
    if (!isEnabled()) return
    if (e.ctrlKey || e.metaKey || e.altKey) return
    const target = e.target as HTMLElement | null
    if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.tagName === 'SELECT' || target.isContentEditable)) return
    if (opts.isBlocked?.()) return
    if (e.key && e.key.length === 1) {
      // Printable char: focus the hidden input; the char lands there (no preventDefault).
      focusInput()
    } else if (e.key === 'Enter') {
      opts.onEnter?.(e)
    }
  }

  const bind = () => {
    if (!import.meta.client || bound) return
    window.addEventListener('keydown', onWindowKeydown)
    bound = true
    isActive.value = true
  }

  const unbind = () => {
    if (!import.meta.client || !bound) return
    window.removeEventListener('keydown', onWindowKeydown)
    bound = false
    isActive.value = false
  }

  onMounted(bind)
  onActivated(bind)
  onDeactivated(unbind)
  onBeforeUnmount(unbind)

  return { focusInput, isActive }
}
