import React, {forwardRef, ReactNode, useMemo} from 'react';
import {StyleProp, StyleSheet, ViewStyle} from 'react-native';
import {IconButton} from '@components/_HuGo/Button';
import {
  TextInput,
  TextInputProps,
  TextInputType,
} from '@components/_core/TextInput';
import {TypographyWithLinks} from '@components/_custom/TypographyWithLinks';
import {TaggedUser} from '@interfaces/taggedUsers';
import {SPACING} from '@shared/theme';

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

export interface InputTagsProps
  extends InputCommonProps,
    InputAccessibilities,
    Omit<TextInputProps, 'style' | 'size'> {
  RightComponent?: ReactNode;
  withClearButton?: boolean;
  /**
   * Show letters counter. This should be used with "maxLength" prop
   */
  showCounter?: boolean;
  style?: StyleProp<ViewStyle>;
  taggedUsers?: TaggedUser[];
}

export const InputTags = forwardRef<TextInputType, InputTagsProps>(
  (
    {
      value = '',
      onChangeText,
      label,
      helper,
      isError,
      isSuccess,
      disabled,
      onFocus,
      onBlur,
      showCounter,
      maxLength,
      RightComponent,
      withClearButton,
      multiline,
      style,
      size,
      /**
       * Use "defaultValue" instead of "value" if there are flickering issues in BottomSheet or other components.
       */
      defaultValue,
      taggedUsers,
      ...textInputProps
    },
    ref,
  ) => {
    const {
      inputRef,
      focused,
      focusInput,
      onInputBlur,
      onInputFocus,
      clearInput,
    } = useInputRef({ref, onFocus, onBlur, onChangeText});
    const inputValue = value ?? defaultValue;
    const inputLength = showCounter ? inputValue?.length || 0 : undefined;

    const TextInputContent = useMemo(() => {
      return <TypographyWithLinks value={value} attributes={taggedUsers} />;
    }, [value, taggedUsers]);

    return (
      <InputCore
        label={label}
        helper={helper}
        isSuccess={isSuccess}
        isError={isError}
        focused={focused}
        disabled={disabled}
        inputLength={inputLength}
        inputMaxLength={maxLength}>
        <InputBox
          isSuccess={isSuccess}
          isError={isError}
          disabled={disabled}
          focused={focused}
          size={size}
          onPress={focusInput}
          style={style}
          RightComponent={
            RightComponent ||
            (withClearButton && focused && inputValue?.length && (
              <IconButton
                Icon={INPUT_ICONS.clear}
                variant="flat"
                onPress={clearInput}
              />
            ))
          }>
          <TextInput
            ref={inputRef}
            onChangeText={onChangeText}
            onFocus={onInputFocus}
            onBlur={onInputBlur}
            maxLength={maxLength}
            editable={!disabled}
            style={multiline ? InputTagsStyle.multiline : undefined}
            multiline={multiline}
            {...textInputProps}>
            {TextInputContent}
          </TextInput>
        </InputBox>
      </InputCore>
    );
  },
);

type InputTagsControllerProps = InputTagsProps & UseInputControllerProps;

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

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

export const InputTagsStyle = StyleSheet.create({
  multiline: {
    paddingRight: SPACING['x1.5'],
  },
});
