import { type Ref, ref } from "vue"

export type FocusTarget =
  | { kind: "block"; id: string }
  | { kind: "zone"; index: number }

/** A screen-coordinate-guided focus request for preserving horizontal
 *  column position when navigating between blocks. */
export interface CoordinateFocus {
  left: number
  edge: "top" | "bottom"
}

export type FocusPosition = "start" | "end" | number | CoordinateFocus

export interface FocusRegistryHandle {
  focus: (pos?: FocusPosition) => void
  element?: HTMLElement
}

export interface FocusRegistry {
  focusedId: Ref<string | null>
  notifyFocused: (id: string) => void
  focus: (id: string, pos?: FocusPosition) => boolean
  focusFirst: () => boolean
  focusLast: () => boolean
  focusNext: () => boolean
  focusPrevious: () => boolean
  register: (id: string, handle: FocusRegistryHandle) => void
  unregister: (id: string) => void
}

export function useFocusRegistry(): FocusRegistry {
  const handles = new Map<string, FocusRegistryHandle>()
  const ids: string[] = []
  const focusedId = ref<string | null>(null)

  function register(id: string, handle: FocusRegistryHandle) {
    handles.set(id, handle)
    if (!ids.includes(id)) {
      ids.push(id)
    }
  }

  function unregister(id: string) {
    handles.delete(id)
    const idx = ids.indexOf(id)
    if (idx !== -1) ids.splice(idx, 1)
    if (focusedId.value === id) {
      focusedId.value = null
    }
  }

  function notifyFocused(id: string) {
    focusedId.value = id
  }

  function focus(id: string, pos?: FocusPosition): boolean {
    const handle = handles.get(id)
    if (!handle) return false
    handle.focus(pos)
    focusedId.value = id
    return true
  }

  function focusFirst(): boolean {
    if (ids.length === 0) return false
    const first = ids[0]
    if (!first) return false
    return focus(first)
  }

  function focusLast(): boolean {
    if (ids.length === 0) return false
    const last = ids[ids.length - 1]
    if (!last) return false
    return focus(last)
  }

  function focusPrevious(): boolean {
    const current = focusedId.value
    if (current === null) return focusLast()
    const idx = ids.indexOf(current)
    if (idx <= 0) return focusLast()
    const prev = ids[idx - 1]
    if (!prev) return focusLast()
    return focus(prev)
  }

  function focusNext(): boolean {
    const current = focusedId.value
    if (current === null) return focusFirst()
    const idx = ids.indexOf(current)
    if (idx === -1 || idx >= ids.length - 1) return focusFirst()
    const next = ids[idx + 1]
    if (!next) return focusFirst()
    return focus(next)
  }

  return {
    focusedId,
    notifyFocused,
    focus,
    focusFirst,
    focusLast,
    focusNext,
    focusPrevious,
    register,
    unregister,
  }
}
