"use client"

import { cx } from "class-variance-authority"
import NextLink from "next/link"
import { useRouter } from "next/navigation"
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef } from "react"

import { Typography } from "@scandic-hotels/design-system/Typography"

import { StickyElementNameEnum } from "@/stores/sticky-position"

import useHash from "@/hooks/useHash"
import useScrollShadows from "@/hooks/useScrollShadows"
import useScrollSpy from "@/hooks/useScrollSpy"
import useStickyPosition from "@/hooks/useStickyPosition"
import { trackHotelTabClick } from "@/utils/tracking"

import styles from "./tabNavigation.module.css"

import type { HotelPageSections } from "@/types/components/hotelPage/sections"
import { HotelHashValues } from "@/types/enums/hotelPage"

interface TabNavigationProps {
  pageSections: HotelPageSections
}

export default function TabNavigation({ pageSections }: TabNavigationProps) {
  const activeHash = useHash()
  const router = useRouter()
  const tabNavigationRef = useRef<HTMLDivElement>(null)
  const tabRefs = useMemo(() => new Map<string, HTMLAnchorElement>(), [])
  const tabLinks = Object.values(pageSections).map(({ hash }) => hash)

  useStickyPosition({
    ref: tabNavigationRef,
    name: StickyElementNameEnum.HOTEL_TAB_NAVIGATION,
    group: "hotelPage",
  })

  const { containerRef, showLeftShadow, showRightShadow } =
    useScrollShadows<HTMLDivElement>()

  const { activeSectionId, pauseScrollSpy } = useScrollSpy(tabLinks)

  const scrollLinkToCenter = useCallback(
    (hash: string) => {
      requestAnimationFrame(() => {
        const activeTab = tabRefs.get(hash)
        if (!containerRef.current || !activeTab) {
          return
        }

        const container = containerRef.current
        const containerWidth = container.offsetWidth
        const tabWidth = activeTab.offsetWidth
        const tabLeft = activeTab.offsetLeft
        const scrollLeft = tabLeft - containerWidth / 2 + tabWidth / 2
        const maxScrollLeft = container.scrollWidth - containerWidth

        // Ensure scrollLeft is inside the viewport
        const boundedScrollLeft = Math.max(
          0,
          Math.min(scrollLeft, maxScrollLeft)
        )

        container.scrollTo({
          left: boundedScrollLeft,
          behavior: "smooth",
        })
      })
    },
    [containerRef, tabRefs]
  )

  useLayoutEffect(() => {
    const hash = activeHash || HotelHashValues.overview
    scrollLinkToCenter(hash)
  }, [activeHash, scrollLinkToCenter])

  useEffect(() => {
    if (activeSectionId) {
      router.replace(`#${activeSectionId}`, { scroll: false })
    }
  }, [activeSectionId, router])

  return (
    <div
      ref={tabNavigationRef}
      className={cx(styles.containerWrapper, {
        [styles.showLeftShadow]: showLeftShadow,
        [styles.showRightShadow]: showRightShadow,
      })}
    >
      <nav className={styles.tabsContainer} ref={containerRef}>
        {Object.values(pageSections).map(({ hash, heading }) => {
          const isActive =
            activeHash === hash ||
            (!activeHash && hash === HotelHashValues.overview)
          return (
            <Typography
              key={hash}
              variant={
                isActive ? "Body/Paragraph/mdBold" : "Body/Paragraph/mdRegular"
              }
            >
              <NextLink
                href={`#${hash}`}
                className={cx(styles.link, {
                  [styles.active]: isActive,
                })}
                aria-current={isActive}
                scroll={true}
                ref={(element) => {
                  if (element) {
                    tabRefs.set(hash, element)
                  }
                }}
                onClick={() => {
                  pauseScrollSpy()
                  trackHotelTabClick(heading)
                }}
              >
                {heading}
              </NextLink>
            </Typography>
          )
        })}
      </nav>
    </div>
  )
}
