import { useEffect, useRef, useState, useCallback } from 'react'

/**
 * D4: 基于视口的活跃标题追踪 hook
 * 在 preview 模式下监听目标容器的滚动事件，
 * 根据文档中标题元素的 offsetTop 判断当前可见的标题索引。
 *
 * 仅在目标容器 ref 存在时生效（preview 面板挂载后）。
 *
 * @param containerRef - 包含 Markdown 渲染结果的 DOM 元素 ref
 * @param headings    - 解析出的标题列表
 * @returns           - 当前活跃标题的索引（null 表示无法判定或不在范围内）
 */
export function useActiveHeading(
  containerRef: React.RefObject<HTMLElement | null>,
  headings: { level: number; text: string }[]
): number | null {
  const [activeIndex, setActiveIndex] = useState<number | null>(null)
  const observerRef = useRef<IntersectionObserver | null>(null)

  const handleScroll = useCallback(() => {
    const container = containerRef.current
    if (!container || headings.length === 0) {
      setActiveIndex(null)
      return
    }

    // 收集容器内所有 h1-h6 元素的 offsetTop
    const headingElements = Array.from(
      container.querySelectorAll('h1, h2, h3, h4, h5, h6')
    ) as HTMLElement[]

    if (headingElements.length === 0) {
      setActiveIndex(null)
      return
    }

    const scrollTop = container.scrollTop
    const containerHeight = container.clientHeight
    const threshold = scrollTop + containerHeight * 0.3 // 上方 30% 位置视为"到达"

    let bestIndex: number | null = null

    for (let i = 0; i < headingElements.length; i++) {
      const el = headingElements[i]
      // 使用容器顶部的相对偏移而非 getBoundingClientRect（滚动容器不是 window）
      const top = el.offsetTop - (container.offsetTop || 0)
      if (top <= threshold) {
        // 找到 headings 中匹配的索引
        const text = el.textContent?.trim() ?? ''
        const matchIdx = headings.findIndex(
          h => h.text.trim() === text && el.tagName.slice(-1) === String(h.level)
        )
        if (matchIdx >= 0) bestIndex = matchIdx
      }
    }

    setActiveIndex(bestIndex)
  }, [containerRef, headings])

  useEffect(() => {
    const container = containerRef.current
    if (!container || headings.length === 0) {
      setActiveIndex(null)
      return
    }

    // 监听滚动事件
    container.addEventListener('scroll', handleScroll, { passive: true })

    // 初始计算
    handleScroll()

    const observer = observerRef.current
    return () => {
      container.removeEventListener('scroll', handleScroll)
      observer?.disconnect()
    }
  }, [containerRef, headings, handleScroll])

  return activeIndex
}
