"use client";

import classNames from "classnames/dedupe";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useDialog } from "../../hooks";
import { mergeRefs } from "../../utils";
import { supportsDialog } from "../../utils/polyfill-tests";
import { ModalContext } from "./ModalContext";
import type { ModalProps } from "./types";
import "./Modal.css";

export type ModalElementType = HTMLDialogElement;

const TRANSITION_CSS_VARIABLE = "--modal-transition-duration";

const Modal = ({ ref, ...props }: ModalProps) => {
  const {
    isOpen,
    onClose,
    preventEscapeKey = false,
    onOpen,
    children,
    className,
    closeLabel,
    isFullScreen,
    animation,
    ...rest
  } = props;
  const [shouldTransition, setShouldTransition] = useState(false);

  useEffect(() => {
    setShouldTransition(supportsDialog());
  }, []);

  const dialogRef = useRef<HTMLDialogElement | null>(null);
  const { close } = useDialog({
    ref: dialogRef,
    isOpen,
    onOpen,
    onClose,
    transition: {
      isEnabled: !!animation,
      CSSVariable: TRANSITION_CSS_VARIABLE,
    },
  });

  const modalClasses = classNames(
    "mobius",
    "mobius-modal",
    {
      "--no-dialog-support": !shouldTransition, // This class is used to correctly position modal in x/y middle on iOS <= 15.2
      "--should-transition": shouldTransition && animation,
      "--slide-up": animation === "slideUp",
      "--fade": animation === "fade",
      "--is-fullscreen": isFullScreen,
    },
    className,
  );

  const [titleId, setTitleId] = useState<string | undefined>(undefined);

  const handleSetTitleId = useCallback((id: string) => {
    setTitleId(id);
  }, []);

  const contextValue = useMemo(
    () => ({
      onClose: close,
      closeLabel,
      titleId,
      setTitleId: handleSetTitleId,
    }),
    [close, closeLabel, titleId, handleSetTitleId],
  );

  return (
    <dialog
      ref={mergeRefs([dialogRef, ref])}
      onCancel={close}
      onKeyDown={event => {
        if (preventEscapeKey && event.key === "Escape") {
          event.preventDefault();
        }
      }}
      className={modalClasses}
      aria-labelledby={titleId}
      {...rest}
    >
      <ModalContext.Provider value={contextValue}>
        {children}
      </ModalContext.Provider>
    </dialog>
  );
};

Modal.displayName = "Modal";
export { Modal };
