import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";

function useForceUpdate() {
	const [, setVal] = useState(false);

	return () => setVal((val) => !val);
}

export type PortalProps = {
	children: React.ReactNode;
	root?: string;
	type?: string;
};

export function Portal({ children, root, type = "div" }: PortalProps) {
	const forceUpdate = useForceUpdate();
	const mountNode = useRef<HTMLDivElement>(null);
	const portalNode = useRef<HTMLElement | null>(null);

	// oxlint-disable-next-line react-hooks/exhaustive-deps -- because reasons
	useEffect(() => {
		const ownerDocument = mountNode.current?.ownerDocument;
		if (ownerDocument && !portalNode.current) {
			let parent = root ? ownerDocument.querySelector(root) || ownerDocument.body : ownerDocument.body;

			const node = ownerDocument.createElement(type);
			portalNode.current = node;
			parent.appendChild(node);
			forceUpdate();

			return () => {
				parent.removeChild(node);
			};
		}
	}, [root, type]);

	if (!portalNode.current) {
		return <div ref={mountNode} />;
	}

	return createPortal(children, portalNode.current);
}
