import { useEffect, useRef } from 'react';
import { useLocation, useNavigate, useNavigationType } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { App } from '@capacitor/app';
import { Toast } from '@capacitor/toast';
import { isNativePlatform } from '../utils/capacitor';
import { getRouteSectionParent } from '../utils/routeParent';

const EXIT_CONFIRM_WINDOW_MS = 2000;

/**
 * Maps the Android hardware back button to web-equivalent behavior, using
 * an app-level back stack instead of the WebView's native history. The
 * WebView's canGoBack counts redirects and `replace` calls as separate
 * entries, so we cannot trust its depth — keep our own stack keyed off
 * react-router's useNavigationType.
 *
 *   1. Overlay/modal open → dispatch Escape (closes folds Overlay via
 *      focus-trap-react's escapeDeactivates).
 *   2. App stack has more than one entry → optimistic pop + navigate(-1).
 *      The optimistic pop, combined with pendingPopsRef suppressing the
 *      duplicate pop in the tracking effect, makes rapid back-presses
 *      see the up-to-date stack length before React commits the new
 *      location.
 *   3. Cold-start / deep-link into a nested screen → navigate to the
 *      section-root semantic parent (same logic UI back arrow uses), with
 *      replace so the stack doesn't grow in a loop.
 *   4. At section root with a single-entry stack → require a confirming
 *      second press within EXIT_CONFIRM_WINDOW_MS to exit; first press
 *      shows a native Android toast. Any navigation between presses
 *      resets the window so the prompt can't leak across screens.
 *
 * Stack-bloat sources are addressed at the navigation site (push-tap and
 * sidebar tabs use `replace`, useRoomNavigate auto-replaces same-pathname
 * navs) — keeping this tracker free of dedup logic that would otherwise
 * have to reconcile against phantom router-history entries.
 */
export const useAndroidBackButton = (): void => {
  const navigate = useNavigate();
  const location = useLocation();
  const navType = useNavigationType();
  const { t } = useTranslation();

  const navigateRef = useRef(navigate);
  navigateRef.current = navigate;

  const exitPromptRef = useRef(t('App.back_to_exit'));
  exitPromptRef.current = t('App.back_to_exit');

  const stackRef = useRef<string[]>([location.pathname]);
  const lastKeyRef = useRef(location.key);
  const pendingPopsRef = useRef(0);
  const lastExitPressRef = useRef(0);

  useEffect(() => {
    if (location.key === lastKeyRef.current) return;
    lastKeyRef.current = location.key;

    lastExitPressRef.current = 0;

    if (navType === 'PUSH') {
      stackRef.current = [...stackRef.current, location.pathname];
    } else if (navType === 'REPLACE') {
      stackRef.current = [...stackRef.current.slice(0, -1), location.pathname];
    } else if (navType === 'POP') {
      if (pendingPopsRef.current > 0) {
        pendingPopsRef.current -= 1;
      } else {
        stackRef.current = stackRef.current.slice(0, -1);
      }
    }
  }, [location.key, location.pathname, navType]);

  useEffect(() => {
    if (!isNativePlatform()) return undefined;

    const handlePromise = App.addListener('backButton', () => {
      const portal = document.getElementById('portalContainer');
      if (portal?.firstChild) {
        document.dispatchEvent(
          new KeyboardEvent('keydown', { key: 'Escape', bubbles: true, cancelable: true })
        );
        return;
      }

      if (stackRef.current.length > 1) {
        stackRef.current = stackRef.current.slice(0, -1);
        pendingPopsRef.current += 1;
        navigateRef.current(-1);
        return;
      }

      const current = stackRef.current[0] ?? '/';
      const parent = getRouteSectionParent(current);
      if (parent) {
        navigateRef.current(parent, { replace: true });
        return;
      }

      const now = Date.now();
      if (now - lastExitPressRef.current < EXIT_CONFIRM_WINDOW_MS) {
        App.exitApp();
        return;
      }
      lastExitPressRef.current = now;
      Toast.show({ text: exitPromptRef.current, duration: 'short', position: 'bottom' });
    });

    return () => {
      handlePromise.then((handle) => handle.remove());
    };
  }, []);
};
