// v-reveal 디렉티브 — 요소가 뷰포트에 들어오면 등장 애니메이션 트리거
//   사용법:
//     v-reveal                       → 기본(아래→위 fade-up)
//     v-reveal:scale                 → 확대 등장
//     v-reveal:fade                  → 투명도만
//     v-reveal="{ delay: 120 }"      → 등장 지연(ms) — 스태거용
//     v-reveal:up="{ delay: i*90 }"  → 타입 + 지연 조합
//
// 디렉티브는 서버/클라이언트 양쪽에 등록(미등록 시 SSR 렌더 크래시)하되,
// IntersectionObserver 등 실제 동작은 클라이언트에서만 수행한다.
// getSSRProps 를 제공해 SSR 단계에서 안전하게 통과시킨다.
type RevealType = 'up' | 'scale' | 'fade'
interface RevealValue {
  type?: RevealType
  delay?: number
}

export default defineNuxtPlugin((nuxtApp) => {
  let observer: IntersectionObserver | null = null
  let reduceMotion = false

  if (import.meta.client) {
    reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
    observer = new IntersectionObserver(
      (entries) => {
        for (const entry of entries) {
          if (entry.isIntersecting) {
            entry.target.classList.add('is-revealed')
            observer?.unobserve(entry.target)
          }
        }
      },
      // 요소가 화면 하단에서 약간 올라온 시점에 트리거
      { threshold: 0.15, rootMargin: '0px 0px -8% 0px' },
    )
  }

  nuxtApp.vueApp.directive<HTMLElement, RevealValue | number | undefined>('reveal', {
    // SSR: 추가 속성 없이 통과 (디렉티브 미등록으로 인한 크래시 방지)
    getSSRProps: () => ({}),
    mounted(el, binding) {
      // 서버에서는 호출되지 않음. 모션 최소화 선호 시 애니메이션 없이 그대로 노출.
      if (reduceMotion || !observer) return

      const value = binding.value
      const type: RevealType =
        (binding.arg as RevealType) ||
        (typeof value === 'object' && value?.type) ||
        'up'
      const delay = typeof value === 'number' ? value : value?.delay ?? 0

      el.classList.add('reveal', `reveal-${type}`)
      if (delay) el.style.setProperty('--reveal-delay', `${delay}ms`)

      observer.observe(el)
    },
    unmounted(el) {
      observer?.unobserve(el)
    },
  })
})
