import { Children, cloneElement, isValidElement, useEffect, useState } from "react"

interface ScrollSpyProps {
  /** IDs of sections to track */
  ids: string[]
  /** Class to apply to active link */
  activeClass?: string
  /** Offset from the top for determining when a section is active */
  offset?: number
  /** Callback function when active section changes */
  onChange?: (activeId: string | null) => void
  /** Optional component props */
  className?: string
  children?: React.ReactNode
}

function ScrollSpy({
  ids,
  activeClass = "active",
  offset = 0,
  onChange,
  className,
  children,
}: ScrollSpyProps) {
  const [activeId, setActiveId] = useState<string | null>(null)

  // biome-ignore lint/correctness/useExhaustiveDependencies: <false positive >
  useEffect(() => {
    const handleScroll = () => {
      // Find all sections
      const sections = ids.map(id => document.getElementById(id)).filter(Boolean)

      // Find the section that is currently visible
      let currentSectionId: string | null = null

      for (const section of sections) {
        if (!section) continue

        const sectionTop = section.getBoundingClientRect().top

        // Section is considered active if its top is near the viewport top
        if (sectionTop <= offset + 50) {
          currentSectionId = section.id
        } else {
          break
        }
      }

      if (currentSectionId !== activeId) {
        setActiveId(currentSectionId)
        onChange?.(currentSectionId)
      }
    }

    // Initial check
    handleScroll()

    // Add scroll event listener
    window.addEventListener("scroll", handleScroll)

    // Cleanup
    return () => {
      window.removeEventListener("scroll", handleScroll)
    }
  }, [ids, activeClass, offset, onChange, activeId])

  // Clone children and add active class to matching child
  const childrenWithProps = Children.map(children, child => {
    if (isValidElement(child)) {
      const href = (child.props as { href?: string }).href

      if (href?.startsWith("#")) {
        return cloneElement(child)
      }
    }

    return child
  })

  return (
    <div data-slot="scroll-spy" className={className}>
      {childrenWithProps}
    </div>
  )
}

export { ScrollSpy }
