'use client';

import * as React from 'react';
import { usePathname } from 'next/navigation';
import { AppLoader } from '@/components/core/app-loader';

interface DashboardNavigationContextValue {
  pendingHref: string | null;
  startNavigation: (href: string) => void;
}

const DashboardNavigationContext = React.createContext<DashboardNavigationContextValue | null>(null);

export function DashboardNavigationProvider({
  children,
}: {
  children: React.ReactNode;
}): React.JSX.Element {
  const pathname = usePathname();
  const [pendingHref, setPendingHref] = React.useState<string | null>(null);

  React.useEffect(() => {
    setPendingHref(null);
  }, [pathname]);

  const startNavigation = React.useCallback((href: string) => {
    setPendingHref(href);
  }, []);

  const value = React.useMemo(
    () => ({ pendingHref, startNavigation }),
    [pendingHref, startNavigation]
  );

  return (
    <DashboardNavigationContext.Provider value={value}>
      <NavigationProgressBar />
      {children}
    </DashboardNavigationContext.Provider>
  );
}

export function useDashboardNavigation(): DashboardNavigationContextValue {
  const context = React.useContext(DashboardNavigationContext);
  if (!context) {
    throw new Error('useDashboardNavigation must be used within DashboardNavigationProvider');
  }
  return context;
}

function NavigationProgressBar(): React.JSX.Element | null {
  const { pendingHref } = useDashboardNavigation();

  if (!pendingHref) {
    return null;
  }

  return <AppLoader size="lg" viewport="content" />;
}

export function isNavHrefActive(
  href: string | undefined,
  pathname: string,
  pendingHref: string | null
): boolean {
  if (!href) {
    return false;
  }

  if (pendingHref) {
    return pendingHref === href;
  }

  return pathname === href;
}

export function isNavGroupHrefActive(
  item: { matcher?: { type: 'startsWith' | 'equals'; href: string }; items?: { href?: string }[] },
  pathname: string,
  pendingHref: string | null
): boolean {
  if (pendingHref) {
    if (item.items?.some((child) => child.href === pendingHref)) {
      return true;
    }

    if (item.matcher?.type === 'startsWith' && pendingHref.startsWith(item.matcher.href)) {
      return true;
    }

    return false;
  }

  if (item.matcher?.type === 'startsWith') {
    return pathname.startsWith(item.matcher.href);
  }

  return item.items?.some((child) => child.href === pathname) ?? false;
}
