import type { Story, Meta } from '@storybook/react';
import { useState } from 'react';

import Button from '@mui/material/Button';
import type { ButtonProps } from '@mui/material/Button';

import { arrayMove } from '../../../utils';

import { DropdownMenu } from '../dropdown-menu';
import { DropDownMenuProps } from '../types';

export default {
  component: DropdownMenu,
  title: 'Forms/Dropdown Menu',
  argTypes: {
    listItems: {
      description: 'The items which will be shown in the list.'
    },
    multiple: {
      description:
        'Allow multiple selection. Notice your selection logic should also support multiple selection.'
    },
    showSelectedIcon: {
      description: 'Whether or not to show selected icon on single selection.'
    },
    search: {
      description:
        'Whether or not to allow searching items inside the menu, notice you must pass `handleSearchChangeCallback` to make it work.'
    },
    searchPlaceholder: {
      description: 'Place holder for the search field.'
    },
    deletable: {
      description:
        'Whether or not to show the delete icon for menu items, notice you must pass `handleDelete` to make it work.'
    },
    arrowSide: {
      description: 'On which side to show the menu arrow.',
      options: ['topLeft', 'topRight'],
      control: {
        type: 'select'
      },
      defaultValue: {
        summary: 'topLeft'
      }
    },
    anchorElTopAddition: {
      description:
        'Specify top addition to place the menu correctly relative to the anchor component.'
    },
    leftAddition: {
      description:
        'Specify left addition to place the menu correctly relative to the anchor component.'
    },
    width: {
      description: 'The width of the menu.'
    },
    sortable: {
      description:
        'Whether or not to show the sort icon for menu items, notice you must pass `onSortEnd` to make it work.'
    },
    onSortEnd: {
      description: 'Callback which is fired on sort end.'
    },
    handleSearchChangeCallback: {
      description: 'Callback which is fired on search text change.'
    },
    bottomButtonText: {
      description:
        'If passed, a button will appear in the bottom of the menu, pass `bottomButtonClickHandler` to make it work.'
    },
    bottomButtonClickHandler: {
      description: 'Call back which will be fired on click the bottom button.'
    },
    handleDelete: {
      description: 'Call back which will be fired on click a delete icon.'
    },
    handleClick: {
      description: 'Call back which will be fired on clicking a menu item.'
    },
    anchorEl: {
      description:
        "A HTML element, or a function that returns it. It's used to set the position of the menu."
    }
  }
} as Meta;

const Template: Story<DropDownMenuProps> = args => {
  const { multiple } = args;

  const [anchorEl, setAnchorEl] = useState<(EventTarget & HTMLButtonElement) | null>(null);

  const handleClick: ButtonProps['onClick'] = event => {
    setAnchorEl(event && event.currentTarget);
  };

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

  const [listItems, setListItems] = useState(args.listItems);

  const handleMenuClick: NonNullable<DropDownMenuProps['handleClick']> = value => () => {
    const newItems = listItems.map(item => {
      if (multiple && item.name === value) {
        return {
          ...item,
          selected: !item.selected
        };
      }
      if (!multiple && (item.name === value || item.selected)) {
        return {
          ...item,
          selected: !item.selected
        };
      }
      return item;
    });
    setListItems(newItems);
    handleClose();
  };

  const handleDelete: DropDownMenuProps['handleDelete'] = value => e => {
    e.stopPropagation();
    setListItems(listItems.filter(item => item.name !== value));
  };

  const onSortEnd: DropDownMenuProps['onSortEnd'] = sortArgs => {
    const { oldIndex, newIndex } = sortArgs;
    if (oldIndex !== newIndex) {
      const newArray = arrayMove(listItems, oldIndex, newIndex);
      setListItems(newArray);
    }
  };

  const handleSearchChangeCallback: DropDownMenuProps['handleSearchChangeCallback'] = value => {
    if (!value) {
      return setListItems(args.listItems);
    }
    return setListItems(
      args.listItems.filter(item => item.name.toString().toLowerCase().includes(value))
    );
  };

  return (
    <>
      <Button onClick={handleClick}>Open menu</Button>
      <DropdownMenu
        {...args}
        handleClick={handleMenuClick}
        anchorEl={anchorEl}
        onClose={handleClose}
        listItems={listItems}
        open={!!anchorEl}
        handleDelete={handleDelete}
        onSortEnd={onSortEnd}
        handleSearchChangeCallback={handleSearchChangeCallback}
      />
    </>
  );
};

export const ButtonWithMenu = Template.bind({});
ButtonWithMenu.args = {
  ariaLabel: 'User Menu Links',
  listItems: [{ name: 'Profile' }, { name: 'My account' }, { name: 'Logout' }],
  multiple: false,
  showSelectedIcon: true,
  search: false,
  deletable: false,
  sortable: false,
  width: 200,
  arrowSide: 'topLeft',
  searchPlaceholder: 'Search placeholder',
  anchorElTopAddition: 10,
  leftAddition: -12,
  bottomButtonText: 'Bottom button'
};
