import React, {forwardRef, useCallback, useMemo} from 'react';
import {StyleProp, ViewStyle} from 'react-native';
import {useTranslation} from 'react-i18next';
import {
  TextInput,
  TextInputProps,
  TextInputType,
} from '@components/_core/TextInput';
import {IconButton} from '@components/_HuGo/Button';
import {useTheme} from '@shared/theme';

import {InputAccessibilities, InputCommonProps} from '../../interfaces';
import {
  useInputController,
  UseInputControllerProps,
} from '../../hooks/useInputController';
import {useInputRef} from '../../hooks/useInputRef';
import {INPUT_ICONS} from '../../constants';
import {InputCore} from '../InputCore';
import {InputBox} from '../InputBox';

interface InputSearchProps
  extends InputCommonProps,
    InputAccessibilities,
    Omit<TextInputProps, 'size'> {
  variant?: 'default' | 'secondary' | 'custom' | 'disabled';
  blurOnClear?: boolean;
}

export const InputSearch = forwardRef<TextInputType, InputSearchProps>(
  (
    {
      value,
      onChangeText,
      label,
      helper,
      isError,
      isSuccess,
      disabled,
      onFocus,
      onBlur,
      style,
      size,
      variant,
      blurOnClear,
      pointerEvents = 'auto',
      ...textInputProps
    },
    ref,
  ) => {
    const {t} = useTranslation();
    const {theme, iconSizes, spacing} = useTheme();
    const {
      inputRef,
      focused,
      focusInput,
      onInputBlur,
      onInputFocus,
      clearInput,
    } = useInputRef({ref, onFocus, onBlur, onChangeText});
    const variantDisabled = variant === 'disabled';
    const showClearButton = value && value.length > 0;

    const inputBoxStyle = useMemo(() => {
      switch (variant) {
        case 'secondary':
          return {
            backgroundColor: theme.background.elements.grey,
          };
        case 'custom':
          return {
            backgroundColor: theme.background.elements.grey,
            borderWidth: 0,
            minHeight: 48,
            padding: spacing['x1.5'],
          };
        default:
          return undefined;
      }
    }, [variant, theme, spacing]);

    const onClear = useCallback(() => {
      clearInput(blurOnClear);
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [blurOnClear]);

    return (
      <InputCore
        disabled={disabled || variantDisabled}
        focused={focused}
        helper={helper}
        label={label}
        isError={isError}
        isSuccess={isSuccess}
        style={style as StyleProp<ViewStyle>}>
        <InputBox
          isSuccess={isSuccess}
          isError={isError}
          disabled={disabled || variantDisabled}
          focused={focused}
          size={size}
          onPress={focusInput}
          pointerEvents={pointerEvents}
          style={inputBoxStyle}
          accessible={false}
          LeftComponent={
            <INPUT_ICONS.search
              size={iconSizes.x6}
              color={theme.text.neutral.lighter}
            />
          }
          RightComponent={
            showClearButton ? (
              <IconButton
                Icon={INPUT_ICONS.clear}
                variant="flat"
                onPress={onClear}
                iconColor={theme.text.neutral.lighter}
                accessibilityRole="alert"
                accessibilityLabel={t('general.clear_filter')}
              />
            ) : null
          }>
          <TextInput
            ref={inputRef}
            value={value}
            onChangeText={onChangeText}
            onFocus={onInputFocus}
            onBlur={onInputBlur}
            editable={!disabled || variantDisabled}
            autoCorrect={false}
            autoComplete="off"
            returnKeyType="search"
            {...textInputProps}
          />
        </InputBox>
      </InputCore>
    );
  },
);

type InputSearchControllerProps = InputSearchProps & UseInputControllerProps;

export const InputSearchController = forwardRef<
  TextInputType,
  InputSearchControllerProps
>(({name, showSuccess, helper, ...props}, ref) => {
  const {onChange, ...inputController} = useInputController({
    name,
    showSuccess,
    helperText: helper,
  });

  return (
    <InputSearch
      {...props}
      {...inputController}
      ref={ref}
      onChangeText={onChange}
    />
  );
});
