import { Menu, Portal } from '@mantine/core';
import React, { useState } from 'react';

import { type MantineBetterMenuInstanceItem, useMantineBetterMenus } from './Store';

export function MenuRenderer() {
  const { menus, providerID, setInstanceState, width } = useMantineBetterMenus((s) => ({
    menus: s.menus,
    providerID: s.providerID,
    setInstanceState: s.setInstanceState,
    setState: s.setState,
    width: s.width,
  }));

  return (
    <Portal id={`bmm_portal_${providerID}`} key={`bmm_portal_${providerID}`}>
      {React.Children.toArray(
        menus?.map((m, menuIndex) => {
          return (
            <Menu
              shadow="md"
              width={width ?? '300'}
              {...m.menuProps}
              key={`bmm_menu_${providerID}_${menuIndex}`}
              onClose={() => {
                setInstanceState(m.id, 'visible', false);
                m.menuProps?.onClose?.();
              }}
              opened={m.visible}
            >
              <Menu.Target>
                <div
                  id={`bmm_${providerID}_${menuIndex}_target`}
                  style={{ left: m.x, position: 'fixed', top: m.y, visibility: 'hidden' }}
                />
              </Menu.Target>

              <Menu.Dropdown>
                {m.renderer
                  ? m.renderer
                  : React.Children.toArray(
                      m.items?.map((item, itemIndex) => (
                        <MenuItemRenderer
                          key={`bmm_${providerID}_${menuIndex}_item${itemIndex}`}
                          {...item}
                        />
                      ))
                    )}
              </Menu.Dropdown>
            </Menu>
          );
        })
      )}
    </Portal>
  );
}

const MenuItemRenderer = ({ children, label, ...props }: MantineBetterMenuInstanceItem) => {
  const [loading, setLoading] = useState<boolean>(false);

  if (typeof props.renderer === 'function') {
    return props.renderer({ ...props, loading, renderer: undefined, setLoading });
  }
  if (typeof props.renderer === 'object') {
    return props.renderer;
  }

  if (props.isDivider) {
    return <Menu.Divider />;
  }

  if (props.items && props.items.length > 0) {
    return (
      <Menu.Sub>
        <Menu.Sub.Target>
          <Menu.Sub.Item
            {...props}
            disabled={loading}
            onClick={(e) => {
              props.onClick?.(e);
              if (props.onClickAsync) {
                setLoading(true);
                props.onClickAsync().finally(() => setLoading(false));
              }
            }}
            styles={{
              itemLabel: {
                overflow: 'auto',
                wordWrap: 'break-word',
              },
              ...props.styles,
            }}
          >
            {children ?? label}
          </Menu.Sub.Item>
        </Menu.Sub.Target>
        <Menu.Sub.Dropdown>
          {React.Children.toArray(
            props.items.map((subitem, subitemIndex) => (
              <MenuItemRenderer
                key={`bmm_subitem_${subitem?.id ?? ''}${subitemIndex}`}
                {...subitem}
              />
            ))
          )}
        </Menu.Sub.Dropdown>
      </Menu.Sub>
    );
  }

  if (!props.onClick && !props.onClickAsync) {
    return <Menu.Label {...(props as Record<string, unknown>)}> {children ?? label}</Menu.Label>;
  }

  return (
    <Menu.Item
      {...props}
      disabled={loading}
      onClick={(e) => {
        props.onClick?.(e);
        if (props.onClickAsync) {
          setLoading(true);
          props.onClickAsync().finally(() => setLoading(false));
        }
      }}
      styles={{
        itemLabel: {
          overflow: 'auto',
          wordWrap: 'break-word',
        },
        ...props.styles,
      }}
    >
      {children ?? label}
    </Menu.Item>
  );
};
