import { useState } from 'react';
import { cleanup, fireEvent } from '@testing-library/react';
import { render } from '../../utils/theme-render-wrapper';

import { FilterSwitchComponent } from './stories/customComponents';
import type { FilterSwitchComponentProps } from './stories/customComponents';
import { Filters } from './filters';
import type { FilterFieldProps, FiltersProps, FiltersValuesProps } from './types';
import { primaryFiltersMockData } from './__mocks__/mockFilters';

afterEach(cleanup);

const changeFn = jest.fn();
const saveFn = jest.fn();
const updateFn = jest.fn();
const clearFn = jest.fn();
const saveFieldFn = jest.fn();

const getFilterFieldMockByName = (name: FilterFieldProps['name']) =>
  primaryFiltersMockData.find(filter => filter.name === name);

const defaultProps: FiltersProps = {
  filters: [
    ...primaryFiltersMockData,
    {
      CustomComponent: FilterSwitchComponent,
      name: 'switch',
      title: 'Custom Component',
      field: {}
    } as FilterSwitchComponentProps,
    {
      name: 'nullFilterTest'
    }
  ],
  clearFiltersButtonProps: {
    hidden: false,
    onClick: clearFn
  },
  saveFiltersButtonProps: {
    hidden: false,
    onClick: saveFn
  },
  updateFiltersButtonProps: {
    hidden: false,
    onClick: updateFn
  },
  handleFieldSaveFilters: saveFieldFn,
  showSaveField: true
};

const FiltersWithValuesWrapper = () => {
  const [filtersValues, setFiltersValues] = useState<FiltersValuesProps['values']>({});
  return (
    <Filters
      {...defaultProps}
      values={filtersValues}
      onValuesChange={newValues => {
        setFiltersValues(newValues);
        changeFn(newValues);
      }}
    />
  );
};

describe('<Filters />', () => {
  it(`should render successfully and click on filter buttons`, () => {
    const { queryByTestId, queryByRole } = render(
      <Filters
        {...defaultProps}
        buttonsWithMenuProps={{
          clickHandler: jest.fn(),
          countOfVisible: 3,
          handleDelete: jest.fn(),
          listItems: [],
          onSortEnd: jest.fn()
        }}
      />
    );

    const radioGroupEl = queryByRole('radiogroup');
    expect(radioGroupEl).toBeTruthy();

    const toggleFiltersButtonEl = queryByTestId('toggleFiltersButton');
    toggleFiltersButtonEl?.click();
    expect(changeFn).not.toBeCalled();

    const saveButtonEl = queryByTestId('saveButton');
    saveButtonEl?.click();
    expect(saveFn).toHaveBeenCalled();

    const updateButtonEl = queryByTestId('updateButton');
    updateButtonEl?.click();
    expect(updateFn).toHaveBeenCalled();

    const clearButtonEl = queryByTestId('clearButton');
    clearButtonEl?.click();
    expect(clearFn).toHaveBeenCalled();

    const saveFieldButton = queryByTestId('saveFieldButton');
    saveFieldButton?.click();
    expect(saveFieldFn).toHaveBeenCalled();
  });

  it(`should render component without buttons with menu`, () => {
    const { queryByRole } = render(<Filters {...defaultProps} />);
    const radioGroupEl = queryByRole('radiogroup');
    expect(radioGroupEl).toBeFalsy();
  });

  it(`should render with Autocomplete and filtersButtonProps func`, () => {
    const textToggleClosed = '[Add Filter]';
    const textToggleOpened = '[Filters]';
    const { queryByTestId } = render(
      <Filters
        {...defaultProps}
        autocompleteProps={{ options: [] }}
        filtersButtonProps={openState =>
          openState ? { children: textToggleOpened } : { children: textToggleClosed }
        }
      />
    );

    const toggleFiltersButtonEl = queryByTestId('toggleFiltersButton');
    expect(toggleFiltersButtonEl?.textContent).toBe(textToggleClosed);
    toggleFiltersButtonEl?.click();
    expect(toggleFiltersButtonEl?.textContent).toBe(textToggleOpened);
  });

  it(`should render with values and check filter components`, () => {
    // suppress warnings generated by date-fns (used by datePicker)
    const originalWarn = console.warn;
    console.warn = jest.fn();

    let clearButtonEl, expandButtonEl;
    const { queryByTestId, queryByText } = render(<FiltersWithValuesWrapper />);
    queryByTestId('toggleFiltersButton')?.click();

    // open datePicker, select "One year" range and then clear
    const datePickerFilterEl = queryByTestId('eventDateFilter');
    expandButtonEl = datePickerFilterEl?.querySelector('button[data-testid="openIcon"]');
    expandButtonEl && fireEvent.click(expandButtonEl);
    const yearRangeEl = datePickerFilterEl?.querySelector('div[data-testid="year"]');
    yearRangeEl && fireEvent.click(yearRangeEl);
    expect(changeFn).toBeCalledTimes(1);
    clearButtonEl = datePickerFilterEl?.querySelector('button[data-testid="clearIcon"]');
    clearButtonEl && fireEvent.click(clearButtonEl);
    expect(changeFn).toBeCalledTimes(3);
    jest.clearAllMocks();

    // open globalSearch, select the first user and then clear
    const globalSearchFilterEl = queryByTestId('globalSearchFilter');
    expandButtonEl = globalSearchFilterEl?.querySelector('button[aria-label="Open"]');
    expandButtonEl && fireEvent.click(expandButtonEl);
    const usersOptions = getFilterFieldMockByName('globalSearch')?.field?.groupedOptions?.users;
    queryByText(`${usersOptions?.[0]?.label}`)?.click();
    expect(changeFn).toBeCalledTimes(1);
    clearButtonEl = globalSearchFilterEl?.querySelector('button[aria-label="Clear"]');
    clearButtonEl && fireEvent.click(clearButtonEl);
    expect(changeFn).toBeCalledTimes(2);
    jest.clearAllMocks();

    // open multipleSelect, select the first region and then clear
    const regionsFilterEl = queryByTestId('regionsFilter');
    expandButtonEl = regionsFilterEl?.querySelector('div[data-testid="select"]');
    expandButtonEl && fireEvent.click(expandButtonEl);
    const regionOptions = getFilterFieldMockByName('regions')?.field?.menuContentProps?.listItems;
    queryByText(`${regionOptions?.[0]?.name}`)?.click();
    expect(changeFn).toBeCalledTimes(1);
    clearButtonEl = regionsFilterEl?.querySelector('div[data-testid="clearButton"]');
    clearButtonEl && fireEvent.click(clearButtonEl);
    expect(changeFn).toBeCalledTimes(2);
    jest.clearAllMocks();

    // open singleSelect, select the first device and then clear
    const deviceFilterEl = queryByTestId('deviceFilter');
    expandButtonEl = deviceFilterEl?.querySelector('div[data-testid="select"]');
    expandButtonEl && fireEvent.click(expandButtonEl);
    const deviceOptions = getFilterFieldMockByName('device')?.field?.menuContentProps?.listItems;
    queryByText(`${deviceOptions?.[0]?.name}`)?.click();
    expect(changeFn).toBeCalledTimes(1);
    clearButtonEl = deviceFilterEl?.querySelector('div[data-testid="clearButton"]');
    clearButtonEl && fireEvent.click(clearButtonEl);
    expect(changeFn).toBeCalledTimes(2);

    console.warn = originalWarn;
  });
});
