import React, { MouseEvent as ReactMouseEvent, useState } from 'react';
import { cleanup, fireEvent, act } from '@testing-library/react';
import { render } from '../../../utils/theme-render-wrapper';
import { DropdownMenu } from '../dropdown-menu';
import type { DropDownMenuProps, DropdownMenuItem } from '../types';
import { mockListItems } from '../__mocks__/menuItems';

afterEach(cleanup);

const buttonText = 'button';

const handleDelete = jest.fn();

const clickableItemName = mockListItems[0].name;

const Wrapper = (props: Partial<DropDownMenuProps>) => {
  const { multiple } = props;
  const [anchorEl, setAnchorEl] = useState<(EventTarget & HTMLButtonElement) | null>(null);
  const handleClick = (event: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => {
    setAnchorEl(event?.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };
  const [listItems, setListItems] = useState<DropdownMenuItem[]>(mockListItems);

  const handleMenuClick = (value: string | number) => () => {
    const newItems = listItems.map((item: DropdownMenuItem) => {
      if (item.name === value) {
        return {
          ...item,
          selected: !item.selected
        };
      }
      return item;
    });
    setListItems(newItems);
    if (!multiple) {
      handleClose();
    }
  };

  return (
    <>
      <button type="button" data-testid="button" onClick={handleClick}>
        {buttonText}
      </button>
      {anchorEl && (
        <DropdownMenu
          {...props}
          anchorElTopAddition={0}
          handleClick={handleMenuClick}
          anchorEl={anchorEl}
          listItems={listItems}
          open={!!anchorEl}
          multiple={multiple}
          disablePortal
          handleDelete={handleDelete}
          onClose={handleClose}
        />
      )}
    </>
  );
};

describe('<DropdownMenu />', () => {
  it(`should render DropdownMenu multiple variant`, () => {
    const { queryByText, container } = render(<Wrapper multiple />);
    const buttonEl = queryByText(buttonText);
    buttonEl?.click();
    const menuItemEl = queryByText(clickableItemName);
    menuItemEl?.click();
    const checkboxEl = container.querySelector('input:checked');
    expect(checkboxEl).toBeTruthy();
  });

  it(`should render DropdownMenu single variant`, () => {
    const { queryByText, queryByTestId } = render(<Wrapper multiple={false} showSelectedIcon />);

    const buttonEl = queryByText(buttonText);
    buttonEl?.click();

    const menuItemEl = queryByText(clickableItemName);
    menuItemEl?.click();
    buttonEl?.click();

    const checkedIconEl = queryByTestId('singleCheckedIcon');
    expect(checkedIconEl).toBeTruthy();
  });

  it(`should render sortable DropdownMenu`, () => {
    const { queryByText, queryByTestId } = render(<Wrapper sortable />);

    const buttonEl = queryByText(buttonText);
    buttonEl?.click();

    const sortIconElm = queryByTestId('sortIcon_0');
    expect(sortIconElm).toBeTruthy();
  });

  it(`should render deletable DropdownMenu`, () => {
    const { queryByText, queryByTestId } = render(<Wrapper deletable />);

    const buttonEl = queryByText(buttonText);
    buttonEl?.click();

    const deleteIconElm = queryByTestId('deleteIcon_0');
    deleteIconElm?.click();

    expect(handleDelete).toHaveBeenCalled();
  });

  it(`should render DropdownMenu with search`, () => {
    const { queryByText, container } = render(<Wrapper search />);

    const buttonEl = queryByText(buttonText);
    buttonEl?.click();

    const inputEl = container.querySelector('input');

    expect(inputEl).toBeTruthy();
    if (inputEl) {
      fireEvent.change(inputEl, { target: { value: 'hello world' } });
    }
  });

  it(`should render DropdownMenu and close it`, () => {
    const { queryByText, queryByTestId } = render(<Wrapper deletable />);

    const buttonEl = queryByText(buttonText);
    buttonEl?.click();

    let dropDownEl = queryByTestId('dropdownMenu');
    expect(dropDownEl).toBeTruthy();

    act(() => {
      if (dropDownEl?.firstChild) {
        fireEvent.click(dropDownEl?.firstChild);
      }
    });
    dropDownEl = queryByTestId('dropdownMenu');
    expect(dropDownEl).toBeNull();
  });

  it(`should render with bottomButtonText`, () => {
    const bottomButtonText = 'Bottom Button Text';
    const bottomButtonClickHandler = jest.fn();

    const { queryByText } = render(
      <Wrapper
        bottomButtonText={bottomButtonText}
        bottomButtonClickHandler={bottomButtonClickHandler}
        noOptionsText="No options"
        noResultsText="No results"
      />
    );
    const buttonEl = queryByText(buttonText);
    buttonEl?.click();

    const bottomButtonEl = queryByText(bottomButtonText);
    bottomButtonEl?.click();
    expect(bottomButtonClickHandler).toHaveBeenCalled();
  });
});
