import { type FC, Fragment, type ReactElement, type RefObject } from 'react';
import { Controller, useFormContext } from 'react-hook-form';

import { merge, uniq } from 'lodash-es';
import CheckBoxIcon from '@material-hu/icons/material/CheckBox';
import CheckBoxOutlineBlankIcon from '@material-hu/icons/material/CheckBoxOutlineBlank';
import Autocomplete from '@material-hu/mui/Autocomplete';
import Checkbox from '@material-hu/mui/Checkbox';
import CircularProgress from '@material-hu/mui/CircularProgress';
import TextField, { type TextFieldProps } from '@material-hu/mui/TextField';
import { createFilterOptions } from '@material-hu/mui/useAutocomplete';

import { type MUIAutocompleteProps } from '@material-hu/components/design-system/Inputs/Autocomplete/types';

const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;
const filter = createFilterOptions();

export type FormAutocompleteProps = Partial<
  MUIAutocompleteProps<any, boolean, boolean, boolean>
> & {
  name: string;
  textFieldProps?: TextFieldProps;
  loading?: boolean;
  showLoadingText?: boolean;
  onChange?: (param) => any;
  freeSolo?: boolean;
  multiple?: boolean;
  StartAdornmentCustom?: JSX.Element;
  rules?: any;
  showErrorText?: boolean;
  query?: Function;
  infinite?: ReactElement;
  hideCheckbox?: boolean;
  hideEndAdornment?: boolean;
};

/**
 * @deprecated Use `@material-hu/components/design-system/Inputs/Autocomplete/form` instead
 */
export const FormAutocomplete: FC<FormAutocompleteProps> = props => {
  const {
    name,
    textFieldProps,
    loading = false,
    showLoadingText = false,
    onChange = null,
    freeSolo,
    multiple,
    StartAdornmentCustom = null,
    rules,
    showErrorText = true,
    query,
    infinite,
    hideCheckbox,
    hideEndAdornment,
    ...autocompleteProps
  } = props;

  const { control } = useFormContext();

  const sanitizeValues = (array: unknown[]) => {
    let newArray = array.filter(value => !!value.toString().trim().length);
    newArray = uniq(newArray);
    return newArray;
  };

  return (
    <Controller
      render={({ field, fieldState }) => (
        <Autocomplete
          {...field}
          onInputChange={(_event, value, reason) => query?.(value, reason)}
          onChange={(e, v) =>
            onChange ? field.onChange(onChange(v)) : field.onChange(v)
          }
          disableCloseOnSelect={multiple}
          limitTags={3}
          filterOptions={filter}
          options={[]}
          renderOption={(renderProps, option: any, { selected, index }) => (
            <Fragment key={option.id}>
              <li {...renderProps}>
                {!hideCheckbox && (
                  <Checkbox
                    icon={icon}
                    checkedIcon={checkedIcon}
                    style={{ marginRight: 8 }}
                    checked={selected}
                  />
                )}
                {option.title || option}
              </li>
              {index === autocompleteProps.options.length - 1 && infinite}
            </Fragment>
          )}
          renderInput={params => (
            <TextField
              {...merge(params, textFieldProps)}
              InputLabelProps={{
                shrink:
                  (params.inputProps.ref as RefObject<HTMLInputElement>)
                    .current === document.activeElement ||
                  !!params.inputProps.value,
              }}
              helperText={
                showErrorText ? fieldState?.error?.message : undefined
              }
              error={!!fieldState?.error?.message}
              InputProps={{
                ...params.InputProps,
                startAdornment: (
                  <>
                    {StartAdornmentCustom}
                    {params.InputProps.startAdornment}
                  </>
                ),
                endAdornment: (
                  <>
                    {loading && (
                      <CircularProgress
                        color="inherit"
                        size={20}
                      />
                    )}
                    {!hideEndAdornment && params.InputProps.endAdornment}
                  </>
                ),
              }}
            />
          )}
          clearOnBlur
          onBlur={(e: any) => {
            if (freeSolo) {
              field.onChange(
                multiple
                  ? sanitizeValues([...field.value, e.target.value])
                  : e.target.value,
              );
            }
          }}
          multiple={multiple}
          freeSolo={freeSolo}
          loading={showLoadingText && loading}
          {...autocompleteProps}
        />
      )}
      name={name}
      control={control}
      rules={rules}
    />
  );
};

export default FormAutocomplete;
