"use client";

import { useEffect } from "react";
import { usePathname } from "next/navigation";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import Lenis from "lenis";

/**
 * SmoothScroll
 * ---------------------------------------------------------------------------
 * One global Lenis instance, driven by a SINGLE rAF source (GSAP's ticker) and
 * kept locked to ScrollTrigger via `lenis.on("scroll", ScrollTrigger.update)`.
 *
 * Enabled on every route. /miletruth's three scroll-driven WebGL sections use a
 * self-managed `position: fixed` pin (toggled from ScrollTrigger.onUpdate via
 * `self.progress`) — NOT GSAP's pin-spacer — so Lenis driving real document
 * scroll keeps their progress correct and just smooths the wheel input. (It was
 * previously gated off here when those sections used GSAP pins; that no longer
 * applies, and native scroll there felt noticeably janky next to every Lenis
 * route.)
 *
 * Still gated OFF on:
 *   - touch devices — native momentum is smoother than emulated inertia.
 *   - prefers-reduced-motion.
 *
 * Re-evaluates on every route change: the effect cleanup destroys the previous
 * instance and re-inits on the next route.
 */
// /how-it-works runs its own tuned Lenis inside the embedded 3D experience
// (src/modules/how-it-works-3d); the global instance is gated off there so two
// Lenis instances don't fight over the same document scroll.
const DISABLED_ROUTES: string[] = ["/how-it-works"];

export default function SmoothScroll() {
  const pathname = usePathname();

  useEffect(() => {
    const routeDisabled = DISABLED_ROUTES.some(
      (r) => pathname === r || pathname.startsWith(`${r}/`),
    );
    const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    // Mouse/desktop only — touch devices already have good native momentum.
    const isPointerFine = window.matchMedia("(hover: hover) and (pointer: fine)").matches;

    let hashTimer: ReturnType<typeof setTimeout>;

    if (routeDisabled || prefersReduced || !isPointerFine) {
      if (!window.location.hash) {
        window.scrollTo(0, 0);
      } else {
        const scrollToHash = () => {
          try {
            const target = document.querySelector(window.location.hash) as HTMLElement | null;
            if (target) {
              target.scrollIntoView();
            }
          } catch (err) {
            console.warn(err);
          }
        };
        scrollToHash();
        hashTimer = setTimeout(scrollToHash, 100);
      }
      return () => {
        if (hashTimer) clearTimeout(hashTimer);
      };
    }

    gsap.registerPlugin(ScrollTrigger);

    // /miletruth is one long stack of tall, pinned 3D sections, each with its own
    // ScrollTrigger `scrub`. The default duration-based momentum (1.05s) compounds
    // with that scrub, so the wheel feels heavy, slow and disconnected. On this
    // route we switch to a snappy `lerp`-based follow + a higher wheel multiplier:
    // the page travels fast and stays tightly locked to the wheel, while each
    // section's scrub supplies the visual smoothing. Other routes keep the softer
    // duration-based feel that suits their normal content.
    const isMileTruth =
      pathname === "/miletruth" || pathname.startsWith("/miletruth/");

    const lenis = new Lenis(
      isMileTruth
        ? {
            lerp: 0.13, // snappy follow (higher = less smoothing lag)
            wheelMultiplier: 1.3, // travel further per wheel tick → fast
            touchMultiplier: 1.6,
            orientation: "vertical",
            gestureOrientation: "vertical",
            smoothWheel: true,
          }
        : {
            duration: 1.05,
            easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
            orientation: "vertical",
            gestureOrientation: "vertical",
            smoothWheel: true,
          },
    );

    if (!window.location.hash) {
      lenis.scrollTo(0, { immediate: true });
      window.scrollTo(0, 0);
    } else {
      const scrollToHash = () => {
        try {
          const target = document.querySelector(window.location.hash) as HTMLElement | null;
          if (target) {
            lenis.scrollTo(target, { immediate: true });
          }
        } catch (err) {
          console.warn(err);
        }
      };
      scrollToHash();
      hashTimer = setTimeout(scrollToHash, 100);
    }

    lenis.on("scroll", ScrollTrigger.update);
    const tickerCb = (time: number) => lenis.raf(time * 1000); // ticker is seconds, Lenis wants ms
    gsap.ticker.add(tickerCb);
    gsap.ticker.lagSmoothing(0);
    ScrollTrigger.refresh();

    return () => {
      if (hashTimer) clearTimeout(hashTimer);
      gsap.ticker.remove(tickerCb);
      lenis.destroy();
    };
  }, [pathname]);

  return null;
}
