import { Checkbox, IconButton, Tooltip } from '@mui/material';
import { Lock } from '@mui/icons-material';
import Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete';
import React, { FC, ReactNode, useCallback } from 'react';
import { Controller, ControllerRenderProps } from 'react-hook-form';

import { RiCheckboxBlankCircleLine, RiCheckboxCircleLine } from 'react-icons/ri';
import { useTranslation } from '../../locale';
import { callAll, useGeneratedId } from '../../utils';

import { EpicTextField } from '../TextField/EpicTextField';
import { EpicAutocompleteBaseProps } from './EpicAutocompleteBaseProps';

type RHFRenderProps = {
  field: ControllerRenderProps;
};

export const EpicAutoCompleteBase: FC<EpicAutocompleteBaseProps> = ({
  canEdit = true,
  formContext,
  name,
  label,
  options,
  multiple,
  getOptionLabel,
  defaultValue,
  textFieldProps,
  onChange,
  renderInput,
  size = 'small',
  optionLimit,
  error,
  helperText,
  rules,
  required,
  onChangeFactory,
  readOnly,
  renderOption,
  readOnlyReason,
  disableCloseOnSelect,
  InputPropsFactory,
  ...autoCompleteProps
}) => {
  const { t } = useTranslation();
  const filterOptions = createFilterOptions<any>({
    matchFrom: 'any',
    limit: optionLimit,
  });
  const { control } = formContext;

  const renderText = useCallback(
    (value: string | string[] | number | null | undefined): ReactNode => {
      if (!value) {
        return '';
      }
      if (typeof value === 'string' || typeof value === 'number') {
        return getOptionLabel(`${value}`) || `${value}`;
      }
      return (value as string[]).map((x) => getOptionLabel(x)).join(',');
    },
    [getOptionLabel]
  );

  const generatedId = useGeneratedId();

  const renderAutocomplete = ({
    field: { onChange: _onChange, value, ...controllerProps },
  }: RHFRenderProps) => (
    <Autocomplete
      id={generatedId}
      value={value ?? (multiple ? [] : null)}
      multiple={multiple || false}
      disableCloseOnSelect={disableCloseOnSelect ?? (multiple || false)}
      options={options}
      size={size}
      disableClearable={required}
      filterOptions={optionLimit ? filterOptions : undefined}
      onChange={
        (onChangeFactory && onChangeFactory(_onChange)) ??
        ((e, data) => {
          callAll(_onChange, onChange)(data);
        })
      }
      renderOption={
        multiple
          ? (props, option, state) => {
              const { selected } = state;
              return (
                <li {...props}>
                  <Checkbox
                    icon={<RiCheckboxBlankCircleLine />}
                    checkedIcon={<RiCheckboxCircleLine />}
                    style={{ marginRight: 8 }}
                    checked={selected}
                  />
                  {(renderOption && renderOption(props, option, state)) ?? getOptionLabel(option)}
                </li>
              );
            }
          : (props, option, state) => (
              <li {...props}>
                {(renderOption && renderOption(props, option, state)) ?? getOptionLabel(option)}
              </li>
            )
      }
      getOptionLabel={getOptionLabel}
      renderInput={
        renderInput ||
        ((params) => (
          <EpicTextField
            autoComplete={'off'}
            variant={'outlined'}
            label={label}
            ref={params.InputProps.ref}
            error={error}
            helperText={helperText}
            {...textFieldProps}
            required={textFieldProps?.required ?? required}
            {...params}
            inputProps={{
              ...params.inputProps,
              autoComplete: 'off',
              'data-testid': name,
            }}
            InputLabelProps={{
              shrink: true,
            }}
          />
        ))
      }
      {...controllerProps}
      {...autoCompleteProps}
    />
  );

  const renderReadOnlyLockedTextField = ({
    field: { onChange: _onChange, value, ...controllerProps },
  }: RHFRenderProps) => (
    <EpicTextField
      value={renderText(value) || ''}
      label={label}
      size={size}
      fullWidth
      variant={canEdit ? 'outlined' : 'standard'}
      {...textFieldProps}
      {...controllerProps}
      required={false}
      InputLabelProps={{
        shrink: true,
      }}
      inputProps={{
        'data-testid': name,
      }}
      InputProps={{
        ...(textFieldProps?.InputProps ?? {}),
        readOnly: true,
        endAdornment: canEdit ? (
          <Tooltip title={`${t('Locked')}. ${readOnlyReason ?? ''}`}>
            <IconButton size={'small'}>
              <Lock fontSize={'inherit'} />
            </IconButton>
          </Tooltip>
        ) : undefined,
      }}
    />
  );

  const renderDisabledTextField = ({
    field: { onChange: _onChange, value, ...controllerProps },
  }: RHFRenderProps) => (
    <EpicTextField
      value={renderText(value) || ''}
      label={label}
      id={generatedId}
      size={size}
      fullWidth
      variant={'standard'}
      {...textFieldProps}
      {...controllerProps}
      required={false}
      InputLabelProps={{
        shrink: true,
      }}
      inputProps={{
        'data-testid': name,
      }}
      InputProps={{
        ...(textFieldProps?.InputProps ?? {}),
        disabled: true,
        ...((InputPropsFactory && InputPropsFactory(value)) ?? {}),
      }}
    />
  );

  return (
    <Controller
      control={control}
      name={name}
      rules={{
        required: {
          value: (textFieldProps?.required || required) ?? false,
          message: `Required`,
        },
        ...rules,
      }}
      defaultValue={defaultValue}
      render={(renderPops) =>
        canEdit
          ? readOnly
            ? renderReadOnlyLockedTextField(renderPops)
            : renderAutocomplete(renderPops)
          : renderDisabledTextField(renderPops)
      }
    />
  );
};