import { type ReactNode, useEffect, useState } from "react";
import { Prompt } from "react-router-dom";

import { Modal } from "@ax/components";
import { useModal } from "@ax/hooks";

import * as S from "./style";

const RouteLeavingGuard = (props: IProps) => {
	const { when, action, text, allowedRoutes } = props;
	const { isOpen, toggleModal } = useModal();

	const [lastLocation, setLastLocation] = useState<Location | null>(null);
	const [confirmedNavigation, setConfirmedNavigation] = useState(false);

	const handleBlockedNavigation = (nextLocation: Location): boolean => {
		const isAllowedNavigation = allowedRoutes?.includes(nextLocation.pathname);
		if (!confirmedNavigation && !isAllowedNavigation) {
			toggleModal();
			setLastLocation(nextLocation);
			return false;
		}
		return true;
	};

	const confirmNavigation = () => {
		toggleModal();
		setConfirmedNavigation(true);
	};

	const mainAction = {
		title: "Yes, discard changes",
		onClick: confirmNavigation,
	};

	const secondaryAction = {
		title: "Cancel",
		onClick: toggleModal,
	};

	useEffect(() => {
		if (confirmedNavigation && lastLocation) {
			action(lastLocation.pathname);
		}
	}, [confirmedNavigation, lastLocation, action]);

	return (
		<>
			<Prompt when={when} message={handleBlockedNavigation} />
			<Modal
				isOpen={isOpen}
				hide={toggleModal}
				size="S"
				title="Unsaved changes"
				mainAction={mainAction}
				secondaryAction={secondaryAction}
			>
				<S.ModalContent>
					{text} If you exit without saving it, it will be lost. Do you want to discard your changes?
				</S.ModalContent>
			</Modal>
		</>
	);
};

interface IRouterLeavingProps {
	when: boolean;
	action(path: string): void;
	text: ReactNode;
	allowedRoutes?: string[];
}

type IProps = IRouterLeavingProps;

export default RouteLeavingGuard;
