"use client";

import { createContext, useContext, useEffect, useState } from "react";

import { usePathname } from "next/navigation";

import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import Lenis from "lenis";

gsap.registerPlugin(ScrollTrigger);

type LenisContextValue = { lenis: Lenis | null };

const LenisContext = createContext<LenisContextValue>({ lenis: null });

export const useLenis = (): LenisContextValue => useContext(LenisContext);

/** Creates the Lenis instance lazily on first render (browser only). */
function createLenis(): Lenis | null {
  if (typeof window === "undefined") return null;
  if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
    return null;
  }
  const instance = new Lenis({
    duration: 1.1,
    easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
    smoothWheel: true,
  });
  instance.on("scroll", ScrollTrigger.update);
  gsap.ticker.add((time) => instance.raf(time * 1000));
  gsap.ticker.lagSmoothing(0);
  return instance;
}

export default function LenisProvider({
  children,
}: {
  children: React.ReactNode;
}) {
  const pathname = usePathname();
  // Lazy init avoids a setState-in-effect; cleanup happens on unmount.
  const [lenis] = useState(createLenis);

  useEffect(() => {
    const onLoad = () => ScrollTrigger.refresh();
    window.addEventListener("load", onLoad);
    return () => window.removeEventListener("load", onLoad);
  }, []);

  // Anchor links: scroll-to-target through lenis, falling back to native.
  // Re-runs on hashchange (same-page anchor clicks) as well as route changes.
  const hash = typeof window !== "undefined" ? window.location.hash : "";
  useEffect(() => {
    if (!lenis) return;
    if (!hash) return;
    const el = document.querySelector(hash);
    if (!el) return;
    const t = window.setTimeout(() => {
      lenis.scrollTo(el as HTMLElement, { offset: -192 });
    }, 120);
    return () => window.clearTimeout(t);
  }, [pathname, lenis, hash]);

  return (
    <LenisContext.Provider value={{ lenis }}>
      {children}
    </LenisContext.Provider>
  );
}
