import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { isMobile } from "react-device-detect";
import clsx from "clsx";
import { m, useMotionValueEvent, useScroll } from "framer-motion";
import { useRouter } from "next/router";

import { AppCalloutCTA } from "@/components/call-to-action";
import List from "@/components/list";
import NavTabs from "@/components/nav-tabs";
import { mediaQueries } from "@/helpers/layout";
import { entriesToArray } from "@/helpers/map";
import { useMatchMedia, useTabs, useWindowSize } from "@/hooks";
import { useStore } from "@/store";
import type { NavigationItem } from "@/types";

import Banner from "../banners";

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

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

interface HeaderProps {
  navItems: NavigationItem[];
}

// TODO: Refactor

export default function Header({ navItems = [] }: HeaderProps) {
  const currentSectionId = useStore.use.currentSectionId();
  const setCurrentSectionId = useStore.use.setCurrentSectionId();
  const sectionRefs = useStore.use.sectionRefs();
  const bannerData = useStore.use.banner();

  const router = useRouter();
  const [location, setLocation] = useState("");
  const [showBanner, setShowBanner] = useState<boolean>(true);
  const [yHeader, setYHeader] = useState<number>(0);
  const { height } = useWindowSize({ triggerOnce: true });
  const matchesSmall = useMatchMedia(mediaQueries.minWidth.small);

  const { scrollY } = useScroll();
  const refBanner = useRef(null);

  const isHomePage = router.pathname === "/";
  const isLegalPage =
    router.pathname === "/terms" || router.pathname === "/privacy";

  const anchorNavItems = navItems.filter(
    (item) => item.href === "/" || item.href.startsWith("#"),
  );
  const secondaryNavItems = navItems.filter(
    (item) => item.href.startsWith("/") && item.href !== "/",
  );

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

  const navigateToPage = useCallback(
    (href: string) => {
      if (isHomePage && href === "/") {
        window.scrollTo({ top: 0, behavior: "smooth" });
        setLocation(href);
      } else {
        router.push(href);
      }
    },
    [router, isHomePage],
  );

  const navigateToSection = useCallback(
    (hashHref: string) => {
      const sectionId = sectionHrefs.get(hashHref);
      if (sectionId) {
        setCurrentSectionId(sectionId);
        const sectionElement = sectionRefs.get(sectionId);
        if (sectionElement) {
          const offset = height * 0.1;
          const elementPosition = sectionElement.getBoundingClientRect().top;
          const offsetPosition = elementPosition + window.pageYOffset - offset;

          window.scrollTo({
            top: offsetPosition,
            behavior: "smooth",
          });
          setCurrentSectionId(sectionId);
          setLocation(hashHref);
        }
      }
    },
    [height, sectionHrefs, sectionRefs, setCurrentSectionId],
  );

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

  const { tabProps: primaryTabProps, setActiveTab: setActivePrimaryTab } =
    useTabs({
      tabs:
        isHomePage && matchesSmall
          ? anchorNavItems
          : anchorNavItems.slice(0, 1),
      initialTabId: anchorNavItems[0]?.id,
      onTabClick: (index) => {
        const href = anchorNavItems[index]?.href;
        if (href.startsWith("#")) {
          navigateToSection(href);
        } else {
          navigateToPage(href);
        }
      },
    });

  const { tabProps: secondaryTabProps, setActiveTab: setActiveSecondaryTab } =
    useTabs({
      tabs: secondaryNavItems,
      initialTabId:
        secondaryNavItems.find((item) => router.pathname === item.href)?.id ??
        "",
      onTabClick: (index) => {
        const href = secondaryNavItems[index]?.href;
        navigateToPage(href);
      },
    });

  useEffect(() => {
    if (isHomePage) {
      setActiveSecondaryTab(-1);

      const activeIndex = anchorNavItems.findIndex(
        (item) => item.href === location,
      );

      if (activeIndex !== -1) {
        setActivePrimaryTab(activeIndex);
      } else {
        setActivePrimaryTab(0);
      }
    } else {
      setActivePrimaryTab(-1);

      const activeIndex = secondaryNavItems.findIndex(
        (item) =>
          item.href === router.pathname ||
          router.pathname.startsWith(item.href),
      );

      if (activeIndex !== -1) {
        setActiveSecondaryTab(activeIndex);
      } else {
        setActiveSecondaryTab(-1);
      }
    }

    return () => {
      setActivePrimaryTab(0);
      setActiveSecondaryTab(-1);
    };
  }, [
    router,
    location,
    isHomePage,
    anchorNavItems,
    setActivePrimaryTab,
    secondaryNavItems,
    setActiveSecondaryTab,
  ]);

  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]);

  const hBanner = 123; // refBanner?.current?.offsetHeight + 15 || 0;

  useMotionValueEvent(scrollY, "change", (y) => {
    if (isMobile && isHomePage) {
      if (y < hBanner) {
        setYHeader(y * -1);
      } else {
        setYHeader(hBanner * -1);
      }
    } else {
      setYHeader(0);
    }
  });

  return (
    <>
      <m.header
        className={styles.header}
        style={{
          y: showBanner ? yHeader : 0,
        }}
      >
        <div className={styles.inner}>
          <div className={styles.left}>
            <NavTabs
              className={clsx(styles.navList, styles.primary)}
              {...primaryTabProps}
            />
            <NavTabs
              className={clsx(styles.navList, styles.secondary)}
              {...secondaryTabProps}
            />
          </div>
          <div className={styles.right}>
            <List
              as="nav"
              className={clsx(styles.navList, styles.callout)}
              items={[<AppCalloutCTA key="app-callout-cta" context="header" />]}
            />
          </div>
        </div>

        {bannerData && isHomePage && (
          <Banner
            data={bannerData}
            show={showBanner}
            onClose={() => setShowBanner(false)}
            ref={refBanner}
          />
        )}
      </m.header>
      {isLegalPage && <hr className={styles.divider} />}
    </>
  );
}

// <List
//   as="nav"
//   className={clsx(styles.navList, styles.secondary)}
//   items={secondaryNavItems.map((item) => (
//     <CallToAction
//       key={item.id}
//       href={item.href}
//       onClick={() => navigateToPage(item.href)}
//       variant="buttonSecondary"
//     >
//       {item.label}
//     </CallToAction>
//   ))}
// />
