import { useCallback, useEffect, useMemo, useState } from "react";
import clsx from "clsx";
import { useRouter } from "next/router";

import NavTabs from "@/components/nav-tabs";
import Pagination from "@/components/pagination";
import { entriesToArray } from "@/helpers/map";
import { useTabs, useWindowSize } from "@/hooks";
import { useStore } from "@/store";
import type { NavigationItem } from "@/types";

import CallToAction from "../call-to-action";
import Login from "../login";

import styles from "./styles.module.scss";

const toHashHref = (id: string) =>
  typeof id === "string" ? "#" + id.split("_")[0] : "";

interface HeaderProps {
  navItems: NavigationItem[];
}

// TODO: Refactor

const Header = ({ navItems = [] }: HeaderProps) => {
  const lenis = useStore.use.lenis();
  const currentSectionId = useStore.use.currentSectionId();
  const setCurrentSectionId = useStore.use.setCurrentSectionId();
  const sectionRefs = useStore.use.sectionRefs();
  const router = useRouter();
  const [location, setLocation] = useState("");
  const { height } = useWindowSize({ triggerOnce: true });

  const isSecondaryPage = router.pathname !== "/";

  const sectionHrefs = useMemo(() => {
    const navHrefs = new Set(navItems.map((item) => item.href));
    return new Map(
      entriesToArray(sectionRefs)
        .filter(([key]) => navHrefs.has(toHashHref(key)))
        .map(([key]) => [toHashHref(key), key]),
    );
  }, [sectionRefs, navItems]);

  const navigateToPage = useCallback(
    (href: string) => {
      if (isSecondaryPage) {
        router.push(href);
      } else {
        lenis?.scrollTo("top", {
          duration: 0.5,
          onComplete: () => {
            setLocation(href);
          },
        });
      }
    },
    [lenis, router, isSecondaryPage],
  );

  const navigateToSection = useCallback(
    (hashHref: string) => {
      const sectionId = sectionHrefs.get(hashHref);
      if (sectionId) {
        setCurrentSectionId(sectionId);
        const sectionElement = sectionRefs.get(sectionId);
        if (sectionElement) {
          lenis?.scrollTo(sectionElement, {
            offset: -height * 0.1,
            onComplete: () => {
              setCurrentSectionId(sectionId);
              setLocation(hashHref);
            },
          });
        }
      }
    },
    [lenis, height, sectionHrefs, sectionRefs, setCurrentSectionId],
  );

  const initialHash = useMemo(
    () => router.asPath.split("#")[1] || "",
    [router.asPath],
  );
  const currentSectionHash = currentSectionId
    ? toHashHref(currentSectionId)
    : "";

  const { tabProps, setActiveTab } = useTabs({
    tabs: isSecondaryPage ? navItems.slice(0, 1) : navItems,
    initialTabId: navItems[0]?.id,
    onTabClick: (index) => {
      const href = navItems[index]?.href;

      if (href === "/") {
        window.location.href = "/";
        return;
      }

      if (href.startsWith("#")) {
        navigateToSection(href);
      } else {
        navigateToPage(href);
      }
    },
  });

  useEffect(() => {
    const activeIndex = navItems.findIndex((item) => item.href === location);
    if (activeIndex !== -1) {
      setActiveTab(activeIndex);
    } else {
      setActiveTab(0);
    }
  }, [location, navItems, setActiveTab]);

  useEffect(() => {
    if (initialHash) {
      navigateToSection(initialHash);
      router
        .replace(
          {
            pathname: window.location.pathname,
            query: window.location.search,
          },
          undefined,
          { shallow: true },
        )
        .catch((error) => {
          // https://github.com/vercel/next.js/issues/37362
          if (!error.cancelled) {
            throw error;
          }
        });
    }
  }, [initialHash, navigateToSection, router]);

  useEffect(() => {
    if (currentSectionHash) {
      if (sectionHrefs.has(currentSectionHash)) {
        setLocation(currentSectionHash);
      } else {
        setLocation("");
      }
    }
  }, [currentSectionHash, sectionHrefs]);

  return (
    <>
      <header
        className={clsx(styles.header, { [styles.secondary]: isSecondaryPage })}
      >
        <div className={styles.inner}>
          {/* Left-aligned items */}
          <NavTabs
            className={clsx(styles.navList, styles.left)}
            {...tabProps}
          />

          <Pagination />

          <Login />
        </div>
      </header>
      {isSecondaryPage && <hr className={styles.divider} />}
    </>
  );
};

export default Header;
