import { memo, useCallback } from 'react';
import { useToggle } from 'react-use';
import noop from 'lodash/noop';

import MuiCollapse from '@mui/material/Collapse';
import MuiGrid from '@mui/material/Grid';

import { Autocomplete } from '../@forms/autocomplete';
import { ButtonsWithMenu } from '../buttons-with-menu';
import { SearchField } from '../@forms/search-field';

import { ActionFiltersButtons, SaveField, ToggleFiltersButton } from './partials';

import { useRenderFilterComponent } from './hooks';
import createClasses from './styles';
import type { FiltersProps } from './types';

const Filters = (props: FiltersProps) => {
  const {
    autocompleteProps,
    searchFieldProps = {},

    filters,
    values = {},
    onValuesChange = noop,

    buttonsWithMenuProps,
    showSaveField,
    saveFiltersFieldText,
    saveFieldProps,
    handleCloseSaveField,
    handleFieldSaveFilters
  } = props;

  const clearFiltersButtonProps = {
    children: props.clearFiltersText,
    hidden: !props.showClear,
    onClick: props.handleClearFilters,
    ...props.clearFiltersButtonProps
  };
  const saveFiltersButtonProps = {
    children: props.saveFiltersText,
    hidden: !props.showSave,
    onClick: props.handleSaveFilters,
    ...props.saveFiltersButtonProps
  };
  const updateFiltersButtonProps = {
    children: props.updateFiltersText,
    hidden: !props.showUpdate,
    onClick: props.handleUpdateFilters,
    ...props.updateFiltersButtonProps
  };

  const styles = createClasses();

  const [open, toggleOpen] = useToggle(false);

  const filtersButtonProps =
    typeof props.filtersButtonProps === 'function'
      ? props.filtersButtonProps(open)
      : props.filtersButtonProps;

  const onFiltersButtonClick = useCallback(
    event => {
      filtersButtonProps?.onClick?.(event);
      toggleOpen();
    },
    [filtersButtonProps, toggleOpen]
  );

  const renderFilterComponent = useRenderFilterComponent(values, onValuesChange);

  return (
    <MuiGrid container direction="column">
      <MuiGrid container>
        <MuiGrid container flexWrap="nowrap" item xs>
          {autocompleteProps ? (
            <Autocomplete className={styles.searchField} {...autocompleteProps} />
          ) : (
            searchFieldProps && <SearchField className={styles.searchField} {...searchFieldProps} />
          )}

          <ToggleFiltersButton
            filtersButtonProps={{
              ...filtersButtonProps,
              onClick: onFiltersButtonClick
            }}
            styles={styles}
          />
        </MuiGrid>

        <MuiGrid data-testid="buttonsWithMenu" display="flex" justifyContent="flex-end">
          {buttonsWithMenuProps && <ButtonsWithMenu {...buttonsWithMenuProps} />}
        </MuiGrid>
      </MuiGrid>

      <MuiCollapse in={open}>
        <MuiGrid container className={styles.filtersContainerInner}>
          {filters.map(filter => (
            <MuiGrid item key={filter.name} xs={4} className={styles.fieldContainer}>
              {renderFilterComponent(filter)}
            </MuiGrid>
          ))}

          {showSaveField && (
            <MuiGrid item xs={4} className={styles.fieldContainer} container alignItems="flex-end">
              <SaveField
                handleFieldSaveFilters={handleFieldSaveFilters}
                saveFiltersFieldText={saveFiltersFieldText}
                saveFieldProps={saveFieldProps}
                handleCloseSaveField={handleCloseSaveField}
                styles={styles}
              />
            </MuiGrid>
          )}

          <MuiGrid container item xs className={styles.buttonsContainer}>
            <MuiGrid item container xs justifyContent="flex-end" flexWrap="nowrap">
              <ActionFiltersButtons
                clearFiltersButtonProps={clearFiltersButtonProps}
                saveFiltersButtonProps={saveFiltersButtonProps}
                updateFiltersButtonProps={updateFiltersButtonProps}
                styles={styles}
              />
            </MuiGrid>
          </MuiGrid>
        </MuiGrid>
      </MuiCollapse>
    </MuiGrid>
  );
};

const m = memo(Filters);
export { m as Filters };
