import { act, cleanup, fireEvent } from '@testing-library/react';
import { render } from '../../../utils/theme-render-wrapper';
import type { Theme } from '../../@styles/theme-provider';

import TestUtils from 'react-dom/test-utils';

import { Autocomplete } from './autocomplete';
import type { AutocompleteOptionProps } from './types';

declare module '@mui/styles/defaultTheme' {
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
  interface DefaultTheme extends Theme {}
}

beforeEach(() => {
  jest.clearAllMocks();
  jest.useFakeTimers();
});

afterEach(() => {
  jest.useRealTimers();
  cleanup();
});

const items: AutocompleteOptionProps[] = [
  {
    name: 'Item1',
    selected: true
  },
  {
    name: 'Item2',
    selected: false
  },
  {
    name: 'Item3',
    selected: false
  },
  {
    name: '',
    selected: false
  }
];

const handleClear = jest.fn();
const handleCreate = jest.fn();
const handleDelete = jest.fn();
const handleMenuClick = jest.fn();

describe('<Autocomplete />', () => {
  it(`should render single selection with defaultValue`, () => {
    const { baseElement } = render(<Autocomplete options={items} defaultValue={items[0]} />);
    expect(baseElement).toBeTruthy();
  });

  it(`should render single selection input`, () => {
    const { queryByTestId, queryByText } = render(
      <Autocomplete options={items} value={items[0]} handleMenuClick={handleMenuClick} />
    );

    // Open menu
    const inputEl = queryByTestId('autocompleteInput');
    expect(inputEl).toBeTruthy();
    inputEl?.click();

    // Click on item
    const itemEl = queryByText(items[0].name);
    expect(itemEl).toBeTruthy();
    itemEl?.click();

    expect(handleMenuClick).toHaveBeenCalled();
  });

  it(`should render input in small size`, () => {
    const { container, queryByTestId } = render(
      <Autocomplete size="small" options={items} value={items[0]} />
    );

    // Open menu
    const inputEl = queryByTestId('autocompleteInput');
    expect(inputEl).toBeTruthy();
    inputEl?.click();

    // Click away
    container?.click();
  });

  it(`should render multiple selection input`, () => {
    const { queryByTestId, container } = render(
      <Autocomplete
        disablePortal
        multiple
        options={items}
        displayOptions={items}
        value={[items[0]]}
        handleMenuClick={handleMenuClick}
        handleDelete={handleDelete}
        handleClear={handleClear}
      />
    );

    act(() => {
      // Test chip button
      const chipDeleteButtonEl = container.querySelector('.MuiChip-deleteIcon');
      if (chipDeleteButtonEl) {
        fireEvent.click(chipDeleteButtonEl);
      }
    });
    expect(handleDelete).toHaveBeenCalled();

    act(() => {
      // Test clear button
      const clearButtonEl = queryByTestId('clearIcon');
      clearButtonEl?.click();
    });
    expect(handleClear).toHaveBeenCalled();

    act(() => {
      // Open menu
      const inputEl = queryByTestId('autocompleteInput');
      inputEl?.click();
    });

    const inputEls = container.querySelectorAll('input');
    const menuInputEl = inputEls[1];
    if (menuInputEl) {
      TestUtils.Simulate.change(menuInputEl);
    }
  });

  it(`should render freeSolo selection input`, () => {
    const { container, queryByTestId } = render(
      <Autocomplete
        multiple
        freeSolo
        options={items}
        displayOptions={items}
        value={items}
        handleMenuClick={handleMenuClick}
        handleCreate={handleCreate}
      />
    );

    const inputRootEl = queryByTestId('autocompleteInput');
    const inputEl = inputRootEl?.querySelector('input');

    // Click on input field
    inputRootEl?.click();
    expect(inputEl).toBeTruthy();

    // Test create button
    if (inputEl) {
      fireEvent.change(inputEl, { target: { value: 'Test' } });
      fireEvent.keyDown(inputEl, { key: 'Enter' });
    }

    expect(handleCreate).toHaveBeenCalled();
    jest.runAllTimers();
  });

  it(`should render freeSolo and create on blur`, () => {
    const { container, queryByTestId } = render(
      <Autocomplete
        multiple
        freeSolo
        options={items}
        displayOptions={items}
        value={items}
        handleCreate={handleCreate}
      />
    );

    const inputRootEl = queryByTestId('autocompleteInput');
    const inputEl = inputRootEl?.querySelector('input');

    // Click on input field
    inputRootEl?.click();
    expect(inputEl).toBeTruthy();

    // Test create or blur
    if (inputEl) {
      fireEvent.change(inputEl, { target: { value: 'Test' } });
      fireEvent.blur(inputEl);
    }

    expect(handleCreate).toHaveBeenCalled();
  });

  it(`should render with showLimitTagsTooltip`, () => {
    const { queryByTestId } = render(
      <Autocomplete
        multiple
        defaultLimitTags={2}
        showLimitTagsTooltip
        options={items}
        displayOptions={items}
        value={items}
        handleMenuClick={handleMenuClick}
      />
    );

    const inputRootEl = queryByTestId('autocompleteInput');
    expect(inputRootEl).toBeTruthy();
    jest.runAllTimers();
  });

  it(`should render renderInputProps correctly`, () => {
    const onClick = jest.fn();
    const { queryByTestId } = render(
      <Autocomplete
        options={items}
        value={items[0]}
        handleMenuClick={handleMenuClick}
        renderInputProps={{
          onClick
        }}
      />
    );

    act(() => {
      const inputEl = queryByTestId('autocompleteInput');
      inputEl?.click();
    });
    expect(onClick).toHaveBeenCalled();
  });
});
