import type { Ref } from 'vue'

/**
 * Scroll-spy des pages empilées : la page active suit en temps réel la page au
 * centre du conteneur défilable, et permet de défiler vers une page donnée.
 * Partagé par le composeur (pages/portfolios/[id].vue) et la vue publique
 * (pages/view/[id].vue) — chacun câble sa propre ref `active` et son `idPrefix`.
 *
 * - `container` : élément défilable (l'aperçu).
 * - `pages`     : liste courante des pages (on lit `.id` et l'ordre).
 * - `active`    : ref d'id écrite à chaque défilement (jamais de re-scroll).
 * - `idPrefix`  : préfixe des id DOM des pages (`preview-page` / `view-page`),
 *                 suffixés par la position 1-based.
 */
export function usePageScrollSpy(options: {
  container: Ref<HTMLElement | undefined>
  pages: Ref<{ id: string }[]>
  active: Ref<string | undefined>
  idPrefix: string
}) {
  const { container, pages, active, idPrefix } = options

  function elementFor(index: number): HTMLElement | null {
    return document.getElementById(`${idPrefix}-${index + 1}`)
  }

  function scrollToIndex(i: number) {
    nextTick(() => {
      elementFor(i)?.scrollIntoView({ behavior: 'smooth', block: 'start' })
    })
  }

  function scrollToId(id: string) {
    const i = pages.value.findIndex(p => p.id === id)
    if (i !== -1) scrollToIndex(i)
  }

  // Une mise à jour par frame (rAF) pour rester fluide sans recalcul redondant.
  let rafPending = false
  function onScroll() {
    if (rafPending) return
    rafPending = true
    requestAnimationFrame(() => {
      rafPending = false
      updateActiveFromScroll()
    })
  }

  function updateActiveFromScroll() {
    const cont = container.value
    if (!cont) return
    const mid = cont.getBoundingClientRect().top + cont.clientHeight / 2
    let bestId: string | undefined
    let bestDist = Infinity
    pages.value.forEach((page, i) => {
      const el = elementFor(i)
      if (!el) return
      const r = el.getBoundingClientRect()
      const dist = Math.abs(r.top + r.height / 2 - mid)
      if (dist < bestDist) {
        bestDist = dist
        bestId = page.id
      }
    })
    if (bestId && bestId !== active.value) active.value = bestId
  }

  return { onScroll, scrollToIndex, scrollToId }
}
