import { useEffect, useState } from 'react'
import { motion } from 'framer-motion'

export interface SectionTab {
  id: string
  label: string
}

interface Props {
  /** Element ids the user can jump to, in display order. The component
   *  filters out ones that don't actually exist in the DOM at render
   *  time so the tab row mirrors what's on the page. */
  tabs: SectionTab[]
}

/**
 * Compact table-of-contents strip rendered just below the hero. Smooth-
 * scrolls to the targeted section on click and keeps the active tab
 * synced with the viewport via IntersectionObserver - useful on long
 * series pages where the user might want to jump from Overview straight
 * to Cast or More-like-this without scrolling.
 *
 * The tabs are NOT sticky - that role is owned by `DetailStickyBar` so
 * the page doesn't end up with two competing top-anchored chromes.
 */
export default function DetailSectionTabs({ tabs }: Props) {
  const [active, setActive] = useState<string | null>(null)
  const [available, setAvailable] = useState<SectionTab[]>([])

  // Filter to tabs whose target element actually exists in the DOM.
  // Sections are conditionally rendered, so listing them all from the
  // parent would surface dead links for sections that hid themselves.
  useEffect(() => {
    const present = tabs.filter(t => document.getElementById(t.id))
    setAvailable(present)
  }, [tabs])

  // Spy on each section so the active tab matches what's mostly in view.
  useEffect(() => {
    if (available.length === 0) return
    const root = document.querySelector('main.content-scroll') as HTMLElement | null
    const observer = new IntersectionObserver(
      entries => {
        // Pick the highest entry that's in view - the one closest to the
        // top of the viewport from the user's perspective.
        const inView = entries
          .filter(e => e.isIntersecting)
          .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top)
        if (inView.length > 0) {
          setActive(inView[0].target.id)
        }
      },
      {
        root,
        // Activate when a section's top is near the top of the viewport,
        // not when it just barely enters from below. The negative bottom
        // margin makes the active zone the upper third of the viewport.
        rootMargin: '-12% 0px -65% 0px',
        threshold: 0,
      },
    )
    for (const t of available) {
      const el = document.getElementById(t.id)
      if (el) observer.observe(el)
    }
    return () => observer.disconnect()
  }, [available])

  function scrollTo(id: string) {
    const el = document.getElementById(id)
    if (!el) return
    el.scrollIntoView({ behavior: 'smooth', block: 'start' })
    setActive(id)
  }

  if (available.length < 2) return null

  return (
    <nav
      aria-label="Sections"
      className="relative -mx-7 px-7 overflow-x-auto hide-scrollbar"
    >
      <ul className="flex items-center gap-1 min-w-max">
        {available.map(t => {
          const isActive = active === t.id
          return (
            <li key={t.id}>
              <button
                type="button"
                onClick={() => scrollTo(t.id)}
                aria-current={isActive ? 'true' : undefined}
                className={`relative h-10 px-3.5 inline-flex items-center text-[12.5px] font-medium tracking-tight transition-colors focus-ring rounded-md ${
                  isActive ? 'text-text-1' : 'text-text-3 hover:text-text-1'
                }`}
              >
                {t.label}
                {isActive && (
                  <motion.span
                    layoutId="detail-tab-underline"
                    className="absolute -bottom-px left-2 right-2 h-[2px] bg-accent rounded-t"
                    transition={{ type: 'spring', stiffness: 380, damping: 32 }}
                  />
                )}
              </button>
            </li>
          )
        })}
      </ul>
    </nav>
  )
}
