import type Lenis from 'lenis'

// Instance partagée : créée une fois par l'application, lue par les composants.
const lenis = shallowRef<Lenis | null>(null)

/**
 * Défilement vers un élément : adouci si possible, immédiat en mouvement réduit.
 * Dans les deux cas, `scroll-margin-top` (main.css) réserve la hauteur de l'en-tête fixe.
 */
function scrollToElement(target: HTMLElement) {
  if (lenis.value) {
    lenis.value.scrollTo(target, { duration: 1.4 })
  } else {
    const reduce = window.matchMedia(MEDIA.reduce).matches
    target.scrollIntoView({ behavior: reduce ? 'auto' : 'smooth', block: 'start' })
  }

  // Le focus suit le défilement, pour la navigation au clavier.
  if (!target.hasAttribute('tabindex')) target.setAttribute('tabindex', '-1')
  target.focus({ preventScroll: true })
}

export function useSmoothScroll() {
  return { lenis, scrollToElement }
}

/**
 * À appeler une seule fois, dans app.vue.
 *
 * - Défilement adouci (Lenis) réservé aux écrans avec souris : le tactile garde
 *   son défilement natif, et rien n'est chargé en mouvement réduit. Lenis lisse
 *   la molette sans jamais détourner la position : pas de scroll-jacking.
 * - Les liens d'ancre de la page courante défilent en douceur jusqu'à leur cible.
 */
export function useSmoothScrollProvider(root: Ref<HTMLElement | null>, paused: Ref<boolean>) {
  useMotion(root, ({ gsap, ScrollTrigger, conditions }) => {
    if (conditions.reduce || !conditions.hover) return

    let instance: Lenis | null = null
    let cancelled = false
    const tick = (time: number) => instance?.raf(time * 1000)

    import('lenis').then(({ default: LenisClass }) => {
      if (cancelled) return
      instance = new LenisClass({ lerp: 0.12 })
      instance.on('scroll', ScrollTrigger.update)
      gsap.ticker.add(tick)
      gsap.ticker.lagSmoothing(0)
      if (paused.value) instance.stop()
      lenis.value = instance
    })

    return () => {
      cancelled = true
      gsap.ticker.remove(tick)
      instance?.destroy()
      lenis.value = null
    }
  })

  watch(paused, (isPaused) => {
    if (isPaused) lenis.value?.stop()
    else lenis.value?.start()
  })

  function onClick(event: MouseEvent) {
    if (event.defaultPrevented || event.button !== 0) return
    if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return

    const link = (event.target as Element | null)?.closest<HTMLAnchorElement>('a[href*="#"]')
    if (!link || link.target === '_blank') return

    const url = new URL(link.href, window.location.href)
    if (url.origin !== window.location.origin || url.pathname !== window.location.pathname) return

    const target = document.getElementById(decodeURIComponent(url.hash.slice(1)))
    if (!target) return

    // Le routeur n'a rien à faire : même page, et un second clic sur la même ancre doit fonctionner.
    event.preventDefault()
    scrollToElement(target)
  }

  onMounted(() => document.addEventListener('click', onClick, { capture: true }))
  onBeforeUnmount(() => document.removeEventListener('click', onClick, { capture: true }))
}
