import {
  createContext,
  type ReactNode,
  useContext,
  useEffect,
  useId,
  useState,
} from 'react';

import {
  type MenuItemProps,
  Menu as MuiMenu,
  MenuItem as MuiMenuItem,
} from '@mui/material';

type RenderTriggerProps = {
  ariaProps: object;
  handleOpen: (event: React.MouseEvent<HTMLButtonElement>) => void;
  open: boolean;
};

type MenuProps = {
  children: ReactNode;
  renderTrigger: (props: RenderTriggerProps) => JSX.Element;
  closeOnSelect?: boolean;
  onOpenChange?: (nextOpen: boolean) => void;
};

type MenuContextValue = {
  closeMenu: () => void;
  closeOnSelect?: boolean;
};

const MenuContext = createContext<MenuContextValue>({
  closeOnSelect: false,
  closeMenu: () => {},
});

const useMenu = () => {
  const context = useContext(MenuContext);
  if (context === undefined) {
    throw new Error('useMenu must be used within a <PXMenu />');
  }
  return context;
};

export const ActionsMenuItem = ({ onClick, sx, ...props }: MenuItemProps) => {
  const { closeOnSelect, closeMenu } = useMenu();
  const handleClick: MenuItemProps['onClick'] = event => {
    if (closeOnSelect) {
      closeMenu();
    }
    onClick?.(event);
  };
  return (
    <MuiMenuItem
      {...props}
      onClick={handleClick}
      sx={{ borderRadius: '12px', ...sx }}
    />
  );
};

const ActionsMenu = ({
  children,
  renderTrigger,
  closeOnSelect,
  onOpenChange,
}: MenuProps) => {
  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
  const id = useId();
  const isOpen = Boolean(anchorEl);

  const handleOpen = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  useEffect(() => onOpenChange?.(isOpen), [isOpen]);

  return (
    <MenuContext.Provider value={{ closeMenu: handleClose, closeOnSelect }}>
      {renderTrigger({
        ariaProps: {
          id,
          'aria-controls': isOpen ? 'actions-menu' : undefined,
          'aria-haspopup': 'true',
          'aria-expanded': isOpen ? 'true' : undefined,
        },
        handleOpen,
        open: isOpen,
      })}
      <MuiMenu
        id="actions-menu"
        anchorEl={anchorEl}
        open={isOpen}
        onClose={handleClose}
        PaperProps={{
          sx: { maxHeight: '360px' },
        }}
        MenuListProps={{
          'aria-labelledby': id,
          sx: { p: 0.5 },
        }}
      >
        {children}
      </MuiMenu>
    </MenuContext.Provider>
  );
};

export default ActionsMenu;
