import { useEffect, useRef, useState } from 'react'
import { Home, Cpu, BarChart3, Flag, Sun, Moon, Navigation } from 'lucide-react'
import { Button } from '../ui/neon-button'
import { LimelightNav, type NavItem } from '../ui/limelight-nav'
import { getScroll } from '../../lib/landing/scroll'
import { useTwinStore } from '../../lib/twin/store'

import { getLenisRef } from '../../lib/landing/lenis-ref'

// Section ids in nav order - index maps 1:1 to the limelight items below.
// MUST stay in the same top-to-bottom order the sections actually render in
// LandingPage (problem → matrix → how → blind-spots → trust). The scroll-spy
// interpolates between consecutive section tops, so a mismatch here makes the
// limelight indicator track the wrong link.
const SECTION_IDS = ['problem', 'matrix', 'how', 'blind-spots', 'trust']

/**
 * Sticky top nav. Condenses with a frosted background after the hero.
 */
export function Nav({ visible }: { visible: boolean }) {
  const [scrolled, setScrolled] = useState(false)
  // Active section index (0=Hero … 3=Findings). Derived from a continuous
  // scroll position but ROUNDED to the nearest section, so the light always
  // sits centered on the highlighted word (the label uses the same rounding).
  const [navActive, setNavActive] = useState(0)
  // When a nav item is clicked we jump the light straight to the target and
  // ignore the scroll-spy until the smooth-scroll actually lands there - so the
  // light glides directly instead of pausing on every section it passes over.
  const jumpTargetRef = useRef(-1)
  const jumpTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
  // Continuous progress state for the limelight
  const [navProgress, setNavProgress] = useState(0)
  const lastProgressRef = useRef(0)

  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > window.innerHeight * 0.6)
    window.addEventListener('scroll', onScroll, { passive: true })
    return () => window.removeEventListener('scroll', onScroll)
  }, [])

  // Scroll-spy driven by a rAF loop reading the SAME Lenis-synced scroll value
  // the 3D scene uses (getScroll). This removes the two lag sources: the
  // IntersectionObserver hysteresis AND the smooth-scroll/CSS-transition delay.
  // We compute a continuous position, then ROUND to the active section so the
  // light stays centered on the highlighted word (it uses the same rounding).
  useEffect(() => {
    let raf = 0
    let last = -1

    const measure = () => {
      // Offset by 100px so sections activate when they sit nicely below the nav.
      const navOffset = 100
      return SECTION_IDS.map((id) => {
        const el = document.getElementById(id)
        return el ? el.getBoundingClientRect().top + window.scrollY - navOffset : null
      })
    }
    const remeasure = () => {}
    // We no longer cache tops on mount, we'll measure continuously to ensure
    // pixel-perfect alignment even if the layout shifts slightly (fonts loading etc).

    const loop = () => {
      raf = requestAnimationFrame(loop)
      const tops = measure()
      const { scrollY } = getScroll()

      // Find the bracketing sections and interpolate between their tops.
      let p = 0
      const maxScroll = document.documentElement.scrollHeight - window.innerHeight
      if (scrollY >= maxScroll - 10) {
        // Force active state to the last section when at the absolute bottom
        p = tops.length - 1
      } else {
        for (let i = 0; i < tops.length; i++) {
          const top = tops[i]
          if (top == null) continue
          if (scrollY >= top) {
            const next = tops[i + 1]
            if (next != null && next > top) {
              const t = Math.min(1, (scrollY - top) / (next - top))
              p = i + t
            } else {
              p = i
            }
          }
        }
      }
      const active = Math.round(p)
      // While a click-jump is in flight, suppress intermediate sections - only
      // release the lock once the scroll has reached the clicked target.
      if (jumpTargetRef.current !== -1) {
        if (active === jumpTargetRef.current) {
          jumpTargetRef.current = -1
          last = active
        }
        return
      }

      // We round p to 3 decimal places to prevent micro-jitter react updates
      const smoothP = Math.round(p * 1000) / 1000
      if (smoothP !== lastProgressRef.current) {
        lastProgressRef.current = smoothP
        setNavProgress(smoothP)
      }

      if (active !== last) {
        last = active
        setNavActive(active)
      }
    }
    raf = requestAnimationFrame(loop)

    return () => {
      cancelAnimationFrame(raf)
    }
  }, [])

  const go = (id: string) => {
    const index = SECTION_IDS.indexOf(id)
    if (index !== -1) {
      // Send the light straight to the target and lock out intermediate spy
      // updates until the scroll arrives.
      jumpTargetRef.current = index
      setNavActive(index)
      // Failsafe: release the lock even if the scroll never lands exactly on the
      // target (e.g. the user scrolls manually mid-jump).
      if (jumpTimerRef.current) clearTimeout(jumpTimerRef.current)
      jumpTimerRef.current = setTimeout(() => (jumpTargetRef.current = -1), 1500)
    }
    const el = document.getElementById(id)
    if (el) {
      const navOffset = 100
      const targetY = el.getBoundingClientRect().top + window.scrollY - navOffset
      const lenis = getLenisRef()
      if (lenis) {
        lenis.scrollTo(targetY)
      } else {
        window.scrollTo({ top: targetY, behavior: 'smooth' })
      }
    }
  }

  // Center limelight nav. Order matches SECTION_IDS so scroll-spy maps 1:1.
  const navItems: NavItem[] = [
    { id: 'problem', icon: <Flag />, label: 'PROBLEM', onClick: () => go('problem') },
    { id: 'matrix', icon: <BarChart3 />, label: 'THE MATRIX', onClick: () => go('matrix') },
    { id: 'how', icon: <Cpu />, label: 'HOW IT WORKS', onClick: () => go('how') },
    { id: 'blind-spots', icon: <Navigation />, label: 'BLIND SPOTS', onClick: () => go('blind-spots') },
    { id: 'trust', icon: <Flag />, label: 'TRUST', onClick: () => go('trust') },
  ]

  return (
    <header
      className="fixed inset-x-0 top-0 z-50 flex items-center justify-between px-8 py-5"
      style={{
        opacity: visible ? 1 : 0,
        transition: 'opacity 0.6s ease, background 0.3s ease, border-color 0.3s ease',
        background: scrolled ? 'var(--lp-nav)' : 'transparent',
        backdropFilter: scrolled ? 'blur(12px)' : 'none',
        WebkitBackdropFilter: scrolled ? 'blur(12px)' : 'none',
        borderBottom: `1px solid ${scrolled ? 'var(--lp-line)' : 'transparent'}`,
      }}
    >
      {/* Wordmark */}
      <button
        onClick={() => go('hero')}
        className="flex items-center gap-2.5"
        style={{ cursor: 'pointer' }}
      >
        <span
          className="police-light inline-block h-2 w-2 rounded-full"
        />
        <span
          className="text-[12px] font-semibold uppercase"
          style={{ fontFamily: 'var(--font-mono)', letterSpacing: '0.2em', color: 'var(--lp-text)' }}
        >
          TrafficOps Twin
        </span>
      </button>

      {/* Center links - limelight text nav, absolutely centered so it never
          clashes with the wordmark or CTA regardless of their widths. */}
      <div className="pointer-events-none absolute left-1/2 top-1/2 hidden -translate-x-1/2 -translate-y-1/2 md:block">
        <div className="pointer-events-auto">
          <LimelightNav
            items={navItems}
            activeIndex={navActive}
            progress={jumpTargetRef.current !== -1 ? undefined : navProgress}
            showLabels
            className="h-12 rounded-xl !border-transparent !bg-transparent text-[var(--lp-text)]"
            limelightClassName="!bg-[var(--lp-text)] !shadow-[0_50px_15px_var(--lp-text)]"
            iconClassName="hidden"
            iconContainerClassName="!gap-0"
          />
        </div>
      </div>

      {/* Right cluster: theme toggle + CTA */}
      <div className="flex items-center gap-3">
        <ThemeToggle />
        <Button
          onClick={() => go('action')}
          size="default"
          className="!mx-0 text-[12px] font-medium uppercase text-[var(--lp-text)]"
          style={{ fontFamily: 'var(--font-mono)', letterSpacing: '0.12em' }}
        >
          Enter the Twin
        </Button>
      </div>
    </header>
  )
}

/**
 * Dark/Light theme toggle. Sets the app-wide theme, which the dashboard map +
 * panels follow (light theme → light basemap, dark → dark basemap).
 */
function ThemeToggle() {
  const theme = useTwinStore((s) => s.theme)
  const toggleTheme = useTwinStore((s) => s.toggleTheme)
  const light = theme === 'light'
  return (
    <button
      onClick={toggleTheme}
      aria-label={light ? 'Switch to dark theme' : 'Switch to light theme'}
      title={light ? 'Switch to dark theme' : 'Switch to light theme'}
      className="flex h-9 w-9 items-center justify-center rounded-lg transition-colors"
      style={{
        border: '1px solid var(--lp-line)',
        background: 'var(--lp-chip)',
        color: 'var(--lp-text)',
        cursor: 'pointer',
      }}
    >
      {light ? <Moon className="h-[18px] w-[18px]" /> : <Sun className="h-[18px] w-[18px]" />}
    </button>
  )
}
