import React, { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
import { createRoot } from "react-dom/client";
import Paper from "./Paper";

type Props = DetailedHTMLProps<
    HTMLAttributes<HTMLDivElement>,
    HTMLDivElement
> & {
    target: React.ReactNode;
    targetRef?: React.MutableRefObject<HTMLDivElement | undefined>;
};

/**
 * # Modal Component
 * @className_wrapper twui-modal-root
 * @className_wrapper twui-modal
 */
export default function Modal({ target, targetRef, ...props }: Props) {
    const [wrapper, setWrapper] = React.useState<HTMLDivElement | null>(null);

    React.useEffect(() => {
        const wrapperEl = document.createElement("div");

        wrapperEl.className = twMerge(
            "fixed z-[200000] top-0 left-0 w-screen h-screen",
            "flex flex-col items-center justify-center",
            "twui-modal-root"
        );

        setWrapper(wrapperEl);
    }, []);

    const modalEl = (
        <React.Fragment>
            <div
                className={twMerge(
                    "absolute top-0 left-0 bg-slate-900/80 z-0",
                    "w-screen h-screen"
                )}
                onClick={(e) => {
                    closeModal({ wrapperEl: wrapper });
                }}
            ></div>
            <Paper
                {...props}
                className={twMerge("z-10 max-w-[500px]", props.className)}
            >
                {props.children}
            </Paper>
        </React.Fragment>
    );

    const targetEl = (
        <div
            onClick={(e) => {
                if (!wrapper) return;
                document.body.appendChild(wrapper);
                const root = createRoot(wrapper);
                root.render(modalEl);
            }}
            ref={targetRef as any}
        >
            {target}
        </div>
    );

    return targetEl;
}

function closeModal({ wrapperEl }: { wrapperEl: HTMLDivElement | null }) {
    if (!wrapperEl) return;
    wrapperEl.parentElement?.removeChild(wrapperEl);
}
