"use client";

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useRef,
  useState,
  ReactNode,
} from "react";
import { usePathname } from "next/navigation";
import { NavEntry } from "@/src/lib/utils/navLabels";
import { captureTitle, recordNavigation } from "@/src/lib/utils/navHistory";

/**
 * Tracks the page the visitor came *from*, so the back button can say
 * "Go back to Programs" rather than guessing from the URL hierarchy.
 * The state machine itself lives in lib/utils/navHistory.ts.
 */

interface NavHistoryValue {
  previous: NavEntry | null;
  /** Used by <NavLabel> so a page can name itself. */
  setPageLabel: (label: string) => void;
  clearPageLabel: () => void;
}

const NavHistoryContext = createContext<NavHistoryValue>({
  previous: null,
  setPageLabel: () => {},
  clearPageLabel: () => {},
});

export function useNavHistory() {
  return useContext(NavHistoryContext);
}

export function NavHistoryProvider({ children }: { children: ReactNode }) {
  const [previous, setPrevious] = useState<NavEntry | null>(null);
  const pathname = usePathname();

  // React flushes child effects before parent ones, so a <NavLabel> deeper in
  // the tree has always deposited this page's name here before the navigation
  // effect below reads it. Leaving a page clears it via NavLabel's cleanup.
  const pageLabelRef = useRef<string | null>(null);
  const setPageLabel = useCallback((label: string) => {
    pageLabelRef.current = label;
  }, []);
  const clearPageLabel = useCallback(() => {
    pageLabelRef.current = null;
  }, []);

  // Guards the title capture against writing onto an entry that a newer
  // navigation has already replaced.
  const currentPathRef = useRef<string | null>(null);

  useEffect(() => {
    if (!pathname) return;
    setPrevious(
      recordNavigation(sessionStorage, pathname, window.location.search, pageLabelRef.current),
    );
    currentPathRef.current = pathname;
  }, [pathname]);

  // Fallback for pages that do not name themselves. Sampled twice: once for
  // fast client transitions, once for slower renders where the title lands
  // later. captureTitle refuses to overwrite a page-supplied label.
  useEffect(() => {
    if (!pathname) return;

    const sample = () => {
      if (currentPathRef.current !== pathname) return;
      captureTitle(sessionStorage, pathname, document.title);
    };

    const timers = [setTimeout(sample, 120), setTimeout(sample, 700)];
    return () => timers.forEach(clearTimeout);
  }, [pathname]);

  return (
    <NavHistoryContext.Provider value={{ previous, setPageLabel, clearPageLabel }}>
      {children}
    </NavHistoryContext.Provider>
  );
}
