import React, {forwardRef, useState, useMemo} from 'react';
import {Pressable} from 'react-native';
import {
  TextInput,
  TextInputProps,
  TextInputType,
} from '@components/_core/TextInput';

import {InputAccessibilities, InputCommonProps} from '../../interfaces';
import {
  useInputController,
  UseInputControllerProps,
} from '../../hooks/useInputController';
import {useInputRef} from '../../hooks/useInputRef';
import {InputCore} from '../InputCore';
import {InputOTPLength, InputOTPType} from './interfaces';
import {INPUT_OTP_SIZES} from './constants';
import {styles} from './styles';
import {OTPBox} from './components/OTPBox';

interface InputOTPProps
  extends InputCommonProps,
    InputAccessibilities,
    Omit<TextInputProps, 'size'> {
  rounded?: boolean;
  length?: InputOTPLength;
  type?: InputOTPType;
}

export const InputOTP = forwardRef<TextInputType, InputOTPProps>(
  (
    {
      value,
      onChangeText,
      label,
      helper,
      isError,
      isSuccess,
      disabled,
      onFocus,
      onBlur,
      length = 'md',
      type = 'default',
      ...textInputProps
    },
    ref,
  ) => {
    const {inputRef} = useInputRef({
      ref,
      onFocus,
      onBlur,
      onChangeText,
    });

    const boxArray = useMemo(
      () => new Array(INPUT_OTP_SIZES[length]).fill(''),
      [length],
    );
    const [focused, setFocused] = useState(false);

    const onPress = () => {
      setFocused(true);
      inputRef.current?.focus?.();
    };

    const onBlurWrapper = () => {
      setFocused(false);
    };

    const onChange = (text: string) =>
      onChangeText?.(text.replace(/[^0-9]/g, ''));

    const onInputFocus = () => setFocused(true);

    return (
      <InputCore
        label={label}
        helper={helper}
        isSuccess={isSuccess}
        isError={isError}
        focused={focused}
        disabled={disabled}>
        <Pressable
          disabled={disabled}
          style={styles.boxContainer}
          onPress={onPress}>
          {boxArray.map((_: string, index: number) => (
            <OTPBox
              key={index}
              code={value}
              index={index}
              isError={isError}
              isSuccess={isSuccess}
              focused={focused && index === value?.length}
              length={length}
              type={type}
              disabled={disabled}
            />
          ))}
          <TextInput
            ref={inputRef}
            value={value}
            onChangeText={onChange}
            onBlur={onBlurWrapper}
            editable={!disabled}
            maxLength={INPUT_OTP_SIZES[length]}
            keyboardType="numeric"
            style={styles.inputHidden}
            onFocus={onInputFocus}
            {...textInputProps}
          />
        </Pressable>
      </InputCore>
    );
  },
);

type InputOTPControllerProps = InputOTPProps & UseInputControllerProps;

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

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