import { clsx } from '@trail-ui/shared-utils';
import { MenuSlots, MenuVariantProps, SlotsToClasses, menu } from '@trail-ui/theme';
import { createContext, useMemo } from 'react';
import type { Placement } from 'react-aria';
import type { MenuProps as AriaMenuProps } from 'react-aria-components';
import { Menu as AriaMenu } from 'react-aria-components';
import { Popover } from '../popover';

import { MenuItemProps } from './menu-item';

export interface MenuProps<T> extends AriaMenuProps<T>, MenuVariantProps {
  placement?: Placement;
  /**
   * Classes object to style the menu and its children.
   */
  classNames?: SlotsToClasses<MenuSlots>;
  /**
   * The menu items classNames.
   */
  itemClasses?: MenuItemProps['classNames'];
}

interface InternalMenuContextValue {
  itemClasses?: MenuItemProps['classNames'];
}

export const InternalMenuContext = createContext<InternalMenuContextValue>(
  {} as InternalMenuContextValue,
);

export function Menu<T extends object>(props: MenuProps<T>) {
  const {
    children,
    className,
    classNames,
    placement = 'bottom',
    itemClasses,
    ...otherProps
  } = props;

  const slots = useMemo(() => menu(), []);

  const baseStyles = clsx(classNames?.base, className);

  return (
    <Popover
      isMenuPopover
      isNonModal
      placement={placement}
      className={slots.popover({ class: classNames?.popover })}
    >
      <InternalMenuContext.Provider value={{ itemClasses }}>
        <AriaMenu className={slots.base({ class: baseStyles })} {...otherProps}>
          {children}
        </AriaMenu>
      </InternalMenuContext.Provider>
    </Popover>
  );
}
