import { FocusModal, clx } from "@medusajs/ui";
import {
  ComponentPropsWithoutRef,
  ComponentType,
  PropsWithChildren,
  forwardRef,
  useEffect,
} from "react";
import { useStackedModal } from "../stacked-modal-provider";

type StackedFocusModalProps = PropsWithChildren<{
  /**
   * A unique identifier for the modal. This is used to differentiate stacked modals,
   * when multiple stacked modals are registered to the same parent modal.
   */
  id: string;
  /**
   * An optional callback that is called when the modal is opened or closed.
   */
  onOpenChangeCallback?: (open: boolean) => void;
}>;

/**
 * A stacked modal that can be rendered above a parent modal.
 */
export const Root: ComponentType<StackedFocusModalProps> = ({
  id,
  onOpenChangeCallback,
  children,
}: StackedFocusModalProps) => {
  const { register, unregister, getIsOpen, setIsOpen } = useStackedModal();

  useEffect(() => {
    register(id);

    return () => unregister(id);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const handleOpenChange = (open: boolean) => {
    setIsOpen(id, open);
    onOpenChangeCallback?.(open);
  };

  return (
    <FocusModal open={getIsOpen(id)} onOpenChange={handleOpenChange}>
      {children}
    </FocusModal>
  );
};

const Close = FocusModal.Close;
Close.displayName = "StackedFocusModal.Close";

const Header = FocusModal.Header;
Header.displayName = "StackedFocusModal.Header";

const Body = FocusModal.Body;
Body.displayName = "StackedFocusModal.Body";

const Trigger = FocusModal.Trigger;
Trigger.displayName = "StackedFocusModal.Trigger";

const Footer = FocusModal.Footer;
Footer.displayName = "StackedFocusModal.Footer";

const Title = FocusModal.Title;
Title.displayName = "StackedFocusModal.Title";

const Description = FocusModal.Description;
Description.displayName = "StackedFocusModal.Description";

const Content = forwardRef<
  HTMLDivElement,
  ComponentPropsWithoutRef<typeof FocusModal.Content>
>(({ className, ...props }, ref) => {
  return (
    <FocusModal.Content
      ref={ref}
      className={clx("!top-6", className)}
      overlayProps={{
        className: "bg-transparent",
      }}
      {...props}
    />
  );
});
Content.displayName = "StackedFocusModal.Content";

export const StackedFocusModal: typeof Root & {
  Close: typeof FocusModal.Close;
  Header: typeof FocusModal.Header;
  Body: typeof FocusModal.Body;
  Content: typeof FocusModal.Content;
  Trigger: typeof FocusModal.Trigger;
  Footer: typeof FocusModal.Footer;
  Description: typeof FocusModal.Description;
  Title: typeof FocusModal.Title;
} = Object.assign(Root, {
  Close,
  Header,
  Body,
  Content,
  Trigger,
  Footer,
  Description,
  Title,
});
