/**
 * `useBlocker` and `usePrompt` is no longer part of react-router for the routers other than `DataRouter`.
 *
 * The previous workaround (<v6.4) was to use `block` function in `UNSAFE_NavigationContext` which is now removed.
 *
 * We're using a workaround from the gist https://gist.github.com/MarksCode/64e438c82b0b2a1161e01c88ca0d0355 with some modifications
 * Thanks to @MarksCode(https://github.com/MarksCode) for the workaround.
 */
import { useCallback, useContext, useEffect } from 'react';
import { UNSAFE_NavigationContext as NavigationContext } from 'react-router';

function useConfirmExit(confirmExit: () => boolean, when = true) {
	const { navigator } = useContext(NavigationContext);

	useEffect(() => {
		if (!when) {
			return;
		}

		const go = navigator.go;
		const push = navigator.push;

		navigator.push = (...args: Parameters<typeof push>) => {
			const result = confirmExit();
			if (result !== false) {
				push(...args);
			}
		};

		navigator.go = (...args: Parameters<typeof go>) => {
			const result = confirmExit();
			if (result !== false) {
				go(...args);
			}
		};

		return () => {
			navigator.push = push;
			navigator.go = go;
		};
	}, [navigator, confirmExit, when]);
}

export function usePrompt(message: string, when = true, onConfirm?: () => void, legacy = false) {
	const warnWhenListener = useCallback(
		(e: { preventDefault: () => void; returnValue: string }) => {
			e.preventDefault();

			e.returnValue = message;

			return e.returnValue;
		},
		[message],
	);

	useEffect(() => {
		if (when && !legacy) {
			window.addEventListener('beforeunload', warnWhenListener);
		}

		return () => {
			window.removeEventListener('beforeunload', warnWhenListener);
		};
	}, [warnWhenListener, when, legacy]);

	const confirmExit = useCallback(() => {
		const confirm = window.confirm(message);
		if (confirm && onConfirm) {
			onConfirm();
		}
		return confirm;
	}, [message]);

	useConfirmExit(confirmExit, when);
}
