import React, { useRef, useState } from 'react';
import {
  TextInput,
  NativeSyntheticEvent,
  TextInputKeyPressEventData,
} from 'react-native';
import { Box } from '../Box';
import { Normalize } from '../../utils/normalize';
import styles from './styles';

export type TextInputProps = React.ComponentPropsWithRef<typeof TextInput> & {
  defaultValue: string;
  numInputs: number;
  inputCellLength?: number;
  handleTextChange: Function;
  keyboardType?: string;
  error?: boolean;
};

const getOTPTextChucks = (
  numInputs: number,
  inputCellLength: number,
  text: string
) => {
  let otpText =
    text.match(new RegExp('.{1,' + inputCellLength + '}', 'g')) || [];

  otpText = otpText.slice(0, numInputs) as RegExpMatchArray;

  return otpText;
};

export const TextFieldDigit = React.forwardRef<TextInput, TextInputProps>(
  (
    {
      defaultValue = '',
      numInputs = 4,
      inputCellLength = 1,
      handleTextChange = () => {},
      keyboardType = 'numeric',
      error = false,
      ...textInputProps
    },
    ref
  ) => {
    const [focusedInput, setFocusedInput] = useState(0);
    const [otpText, setOtpText] = useState(
      getOTPTextChucks(numInputs, inputCellLength, defaultValue)
    );

    const inputCodeRef = useRef<TextInput[]>([]);
    const basicValidation = (text: string) => {
      const validText = /^[0-9a-zA-Z]+$/;
      return text.match(validText);
    };

    const onKeyPress = (
      event: NativeSyntheticEvent<TextInputKeyPressEventData>,
      index: number
    ) => {
      const key = event.nativeEvent.key;
      if (key === 'Backspace') {
        const indexOnBackspace = index > 0 ? index - 1 : 0;
        return inputCodeRef.current[indexOnBackspace].focus();
      }

      const currentIndex = index < numInputs - 1 ? index + 1 : numInputs - 1;
      return inputCodeRef.current[currentIndex].focus();
    };

    const onTextChange = (text: string, i: number) => {
      if (text && !basicValidation(text)) {
        return;
      }
      const typedCode = text.slice(-1);
      const currentCodes = [...otpText] as RegExpMatchArray;
      currentCodes[i] = typedCode;
      setOtpText(currentCodes);
      handleTextChange(otpText.join(''));
    };

    const onInputFocus = (i: number) => {
      const prevIndex: number = i - 1;

      if (prevIndex > -1 && !otpText[prevIndex] && !otpText.join('')) {
        inputCodeRef.current[prevIndex].focus();
        return;
      }

      setFocusedInput(i);
    };

    const getBorderColor = (i: number) => {
      if (error) return 'chiperBrandRed';
      if (focusedInput === i) return 'yankeesBlue';
      return 'gray25';
    };

    const TextInputs = [];

    for (let i = 0; i < numInputs; i += 1) {
      TextInputs.push(
        <Box
          borderWidth={1}
          padding={'spacing-xxs'}
          borderRadius={Normalize(4)}
          marginHorizontal={'spacing-xxs'}
          flexDirection="row"
          justifyContent="center"
          alignItems="center"
          height={Normalize(44)}
          width={Normalize(42)}
          borderColor={getBorderColor(i)}
          key={i + 'view'}
          testID="inputSlotView"
        >
          <TextInput
            testID="textInput"
            ref={(element) => element && inputCodeRef.current.push(element)}
            key={i}
            autoCorrect={false}
            keyboardType={keyboardType}
            autoFocus={i === 0}
            value={otpText[i] || ''}
            style={styles.textInput}
            maxLength={inputCellLength}
            selectTextOnFocus={true}
            onFocus={() => onInputFocus(i)}
            onChangeText={(text) => onTextChange(text, i)}
            multiline={false}
            onKeyPress={(e) => onKeyPress(e, i)}
            {...textInputProps}
          />
        </Box>
      );
    }

    return (
      <Box
        testID="TextFieldDigitInputView"
        flexDirection="row"
        justifyContent="center"
        ref={ref}
      >
        {TextInputs}
      </Box>
    );
  }
);
