import type { NavigateFunction, NavigateOptions } from 'react-router-dom';

import { getNavbarElement } from './get-navbar-element';
import { withLoadProgress } from './with-load-progress';

export type HistoryOrigin = 'pm' | 'browser';

let lastNavigatedPath;
// this is copy from portal/src/client/app/utils/loadAndNavigate.ts, for case when we need to run Redoc without Realm
export async function loadAndNavigate({
  navigate,
  to,
  origin = 'browser',
  options,
}: {
  navigate: NavigateFunction;
  to: string;
  origin?: HistoryOrigin;
  options?: NavigateOptions;
}) {
  lastNavigatedPath = to;
  const { pathname, hash, search } = new URL(to, window.location.origin + window.location.pathname);

  // use window-shared loader instead of importing to prevent circular import issue
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
  const loader = (window as any)['__LOADER'];
  const result = await withLoadProgress(loader.tryLoad(pathname));
  // @ts-ignore
  if (result?.redirectTo) {
    // @ts-ignore
    return loadAndNavigate({ navigate, to: result.redirectTo, origin, options });
  }

  if (result && lastNavigatedPath === to) {
    if (pathname !== window.location.pathname || search !== window.location.search) {
      // origin is used to prevent infinite loop when navigating from post message (from wysiwyg)
      navigate({ pathname, search, hash }, {
        ...options,
        state: { origin },
        unstable_flushSync: true,
      } as NavigateOptions & { unstable_flushSync: boolean });
    }
    // @ts-ignore
    if (result.props?.disableAutoScroll) return;

    if (hash) {
      const el = document.getElementById(hash.slice(1));
      if (el) {
        const navbar = getNavbarElement();
        const navbarHeight = navbar?.offsetHeight ?? 0;
        const elementTop = el.getBoundingClientRect().top + window.scrollY;
        const scrollPosition = elementTop - navbarHeight;
        window.scrollTo({ top: scrollPosition, behavior: 'smooth' });
      }
    } else {
      window.scrollTo(0, 0);
    }
  }
}
