import { useEffect, useRef } from 'react'

/**
 * Пишет нормализованные координаты в CSS-переменные --mx/--my на самой
 * секции; слои фона сдвигаются от них в CSS со своим коэффициентом глубины.
 *
 * Источник координат зависит от устройства:
 * - мышь (hover + fine pointer) — позиция курсора внутри секции (-1..1);
 * - тач — прогресс прокрутки секции, орб плавно уплывает при скролле.
 */
export function useParallax<T extends HTMLElement>() {
  const ref = useRef<T>(null)

  useEffect(() => {
    const el = ref.current
    if (!el) return
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return

    if (window.matchMedia('(hover: hover) and (pointer: fine)').matches) {
      const onMove = (e: MouseEvent) => {
        const rect = el.getBoundingClientRect()
        const x = ((e.clientX - rect.left) / rect.width - 0.5) * 2
        const y = ((e.clientY - rect.top) / rect.height - 0.5) * 2
        el.style.setProperty('--mx', x.toFixed(3))
        el.style.setProperty('--my', y.toFixed(3))
      }

      const onLeave = () => {
        el.style.setProperty('--mx', '0')
        el.style.setProperty('--my', '0')
      }

      el.addEventListener('mousemove', onMove)
      el.addEventListener('mouseleave', onLeave)
      return () => {
        el.removeEventListener('mousemove', onMove)
        el.removeEventListener('mouseleave', onLeave)
      }
    }

    let raf = 0
    const onScroll = () => {
      if (raf) return
      raf = requestAnimationFrame(() => {
        raf = 0
        const rect = el.getBoundingClientRect()
        const progress = Math.min(Math.max(-rect.top / rect.height, 0), 1)
        // >1 по модулю — усиливаем дрейф, т.к. скролл-диапазон уже курсорного
        el.style.setProperty('--mx', (progress * 0.6).toFixed(3))
        el.style.setProperty('--my', (progress * -1.4).toFixed(3))
      })
    }

    onScroll()
    window.addEventListener('scroll', onScroll, { passive: true })
    return () => {
      window.removeEventListener('scroll', onScroll)
      cancelAnimationFrame(raf)
    }
  }, [])

  return ref
}
