"use client";

import classNames from "classnames/dedupe";
import { useEffect, useId, useMemo, useRef, useState } from "react";
import { useDialog } from "../../hooks";
import { mergeRefs, supportsDialog } from "../../utils";
import { VisuallyHidden } from "../VisuallyHidden";
import { DrawerContext } from "./DrawerContext";
import type { DrawerProps } from "./types";
import "./Drawer.css";

export type DialogElementType = HTMLDialogElement;

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

const Drawer = ({ ref, ...props }: DrawerProps) => {
  const {
    isOpen,
    className,
    closeLabel,
    direction,
    announce = "Drawer opened on screen",
    onOpen,
    onClose,
    children,
  } = props;
  const dialogRef = useRef<HTMLDialogElement | null>(null);
  const [shouldTransition, setShouldTransition] = useState(false);
  const { close } = useDialog({
    ref: dialogRef,
    isOpen,
    onOpen,
    onClose,
    transition: {
      isEnabled: true,
      CSSVariable: TRANSITION_CSS_VARIABLE,
    },
  });
  const hiddenId = `dialog-screen-reader-announce-${useId()}`;
  const headerId = `dialog-header-${useId()}`;

  const dialogClasses = classNames(
    "mobius",
    "mobius-drawer",
    `--${direction}`,
    className,
    {
      "--should-transition": shouldTransition,
    },
  );

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

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

  return (
    <dialog
      id={useId()}
      ref={mergeRefs([dialogRef, ref])}
      onCancel={close}
      className={dialogClasses}
      aria-describedby={hiddenId}
      aria-labelledby={headerId}
    >
      <VisuallyHidden>
        <div id={hiddenId}>{announce}</div>
      </VisuallyHidden>
      <DrawerContext.Provider value={contextValue}>
        {children}
      </DrawerContext.Provider>
    </dialog>
  );
};

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