import { useCallback, useEffect, useRef, } from "react";
import { useCombinedRefs } from "../../hook/useCombinedRefs";
import { useFocusTrap } from "../../hook/useFocusTrap";
import { usePreventScroll } from "../../hook/usePreventScroll";
import { cx } from "../../utils";
import * as styles from "./dialog.css";
/**
 * A responsive, accessible Dialog component built on top of the native HTML `<dialog>` element.
 *
 * @remarks
 * Features:
 * - Native `<dialog>` implementation for accessibility.
 * - Automatic focus trapping using {@link useFocusTrap}.
 * - Body scroll prevention using {@link usePreventScroll}.
 * - Backdrop click-to-close functionality.
 * - Support for entry and exit animations.
 *
 * @param props - The properties for the Dialog component.
 * @returns A JSX element representing the Dialog.
 *
 * @example
 * ### Basic Usage
 * ```tsx
 * const [isOpen, setIsOpen] = useState(false);
 *
 * return (
 *   <>
 *     <button onClick={() => setIsOpen(true)}>Open Dialog</button>
 *     <Dialog open={isOpen} onClose={() => setIsOpen(false)}>
 *       <h2>Welcome</h2>
 *       <p>This is a native dialog.</p>
 *       <button onClick={() => setIsOpen(false)}>Close</button>
 *     </Dialog>
 *   </>
 * );
 * ```
 *
 * @example
 * ### With Animations
 * ```tsx
 * <Dialog
 *   open={isOpen}
 *   enterAnimation="slide-up 0.3s ease-out"
 *   exitAnimation="slide-down 0.2s ease-in"
 *   onClose={handleClose}
 * >
 *   <p>Animated content</p>
 * </Dialog>
 * ```
 */
export function Dialog({ open = false, ref, onClose, enterAnimation = "", exitAnimation = "", ...props }) {
    /** Reference to the underlying HTMLDialogElement for imperative API access and backdrop detection. */
    let dialogRef = useRef(null);
    /** Manages focus entrapment within the dialog when it's open. */
    let focusRef = useFocusTrap(open);
    /** Combines internal refs and the external forwarded ref. */
    let combinedRef = useCombinedRefs(dialogRef, focusRef, ref);
    /** Prevents the document body from scrolling while the modal is active. */
    usePreventScroll(open);
    /**
     * Handles clicks on the dialog element.
     * Detects if the click occurred on the backdrop (outside the bounding rect)
     * and triggers the `onClose` callback if so.
     *
     * @param event - The pointer event from the dialog container.
     */
    let handleCloseBackdrop = useCallback((event) => {
        if (!dialogRef.current) {
            return;
        }
        let rect = dialogRef.current.getBoundingClientRect();
        if (rect.left > event.clientX ||
            rect.right < event.clientX ||
            rect.top > event.clientY ||
            rect.bottom < event.clientY) {
            onClose?.(event);
        }
    }, [onClose]);
    /**
     * Syncs the component the `open` prop state with the native `<dialog>` DOM state.
     * Handles `showModal()`, `close()`, and manages animation lifecycles.
     */
    useEffect(() => {
        if (dialogRef.current === null) {
            return;
        }
        if (open) {
            // Show the dialog via native API to enable top-layer rendering.
            dialogRef.current.showModal();
            dialogRef.current.style.animation = enterAnimation;
            // Wait for all animations to complete before resetting the animation style.
            Promise.allSettled(dialogRef.current.getAnimations().map((a) => a.finished)).then(() => {
                if (dialogRef.current) {
                    dialogRef.current.style.animation = "";
                }
            });
        }
        else {
            // Apply exit animation before closing the native DOM element.
            dialogRef.current.style.animation = exitAnimation;
            // Wait for exit animations to finish before calling close() on the DOM element.
            Promise.allSettled(dialogRef.current.getAnimations().map((a) => a.finished)).then(() => {
                if (dialogRef.current) {
                    dialogRef.current?.close();
                    dialogRef.current.style.animation = "";
                }
            });
        }
    }, [open, enterAnimation, exitAnimation]);
    return (<dialog {...props} ref={combinedRef} onPointerDown={handleCloseBackdrop} onClose={onClose} className={cx(styles.dialog, props.className)} inert={!open}>
			{/* Placeholder for focus management baseline */}
			<div tabIndex={open ? 0 : -1} style={{
            width: "1px",
            height: "0px",
            padding: 0,
            overflow: "hidden",
            position: "absolute",
            insetBlockStart: "1px",
            insetInlineStart: "1px",
        }}/>
			{props.children}
		</dialog>);
}
