import {
  StyleSheet,
  TextInput,
  Animated,
  TouchableWithoutFeedback,
  View,
  Platform,
} from 'react-native';
import React, { useRef, useState } from 'react';
import type { Theme, RsTextStyle, RsTextInputProps } from '../styles/types';
import { useTheme } from '../hooks/ThemeProvider';
import { useMemo } from 'react';

const FLOAT_LABEL_ANIMATION_DURATION = 150;

const RsTextInput: React.FC<RsTextInputProps & RsTextStyle> = ({
  value = '',
  placeholder = '',
  onChangeText = () => {},
  onFocus,
  onBlur,
  containerStyle = undefined,
  fontSize = 14,
  fontWeight = 'Regular',
  textAlign = 'left',
  textTransform = 'none',
  color,
  style,
  ...props
}) => {
  const [isFocused, setIsFocused] = useState(false);
  const [inputValue, setInputValue] = useState(value);

  const animatedIsFocused = React.useRef(
    new Animated.Value(value ? 1 : 0)
  ).current;

  const theme = useTheme();
  const styles = useMemo(
    () =>
      generateStyles(
        theme,
        {
          fontSize,
          fontWeight,
          textAlign,
          textTransform,
          color,
        },
        isFocused,
        inputValue
      ),
    [
      theme,
      fontSize,
      fontWeight,
      textAlign,
      textTransform,
      color,
      isFocused,
      inputValue,
    ]
  );

  React.useEffect(() => {
    Animated.timing(animatedIsFocused, {
      toValue: isFocused || inputValue ? 1 : 0,
      duration: FLOAT_LABEL_ANIMATION_DURATION,
      useNativeDriver: false,
    }).start();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isFocused, inputValue]);

  const labelStyle = {
    position: 'absolute',
    left: 8,
    top: animatedIsFocused.interpolate({
      inputRange: [0, 1],
      outputRange: [26 - 8, 8],
    }),
    fontSize: 14,
    color: theme.Text.inputPlaceholder,
    zIndex: 2,
    fontFamily: 'Cairo-Light-Tight',
    includeFontPadding: Platform.OS === 'android' ? false : undefined,
    padding: Platform.OS === 'android' ? 0 : undefined,
    textAlignVertical: Platform.OS === 'android' ? 'bottom' : undefined,
  };

  const inputRef = useRef<TextInput>(null);

  return (
    <TouchableWithoutFeedback
      onPress={() => {
        inputRef.current?.focus();
      }}
    >
      <View style={containerStyle ?? styles.container}>
        <Animated.Text style={labelStyle as any} pointerEvents="none">
          {placeholder}
        </Animated.Text>
        <TextInput
          ref={inputRef}
          value={inputValue}
          onChangeText={(text) => {
            setInputValue(text);
            onChangeText(text);
          }}
          style={[styles.inputText, style ?? styles.input]}
          onFocus={(e) => {
            setIsFocused(true);
            onFocus && onFocus(e);
          }}
          onBlur={(e) => {
            setIsFocused(false);
            onBlur && onBlur(e);
          }}
          submitBehavior="blurAndSubmit"
          selectionColor={theme.Borders.inputActive}
          {...props}
        />
      </View>
    </TouchableWithoutFeedback>
  );
};

export default RsTextInput;

const generateStyles = (
  theme: Theme,
  style: RsTextStyle,
  isFocused: boolean,
  inputValue: string
) =>
  StyleSheet.create({
    container: {
      width: '100%',
      height: 52,
      overflow: 'hidden',
      padding: 8,
      borderWidth: 1,
      borderRadius: 10,
      borderColor: isFocused ? theme.Borders.inputActive : theme.Borders.input,
      backgroundColor: theme.Background.input,
      alignItems: 'stretch',
      justifyContent: 'center',
      position: 'relative',
    },
    input: {
      position: 'absolute',
      width: '100%',
      maxHeight: style.fontSize ? style.fontSize * 1.2 : 16,
      alignItems: 'center',
      left: 8,
      bottom: isFocused || inputValue.length > 0 ? 8 : 26 - 8,
      textAlignVertical: Platform.OS === 'android' ? 'bottom' : undefined,
      padding: Platform.OS === 'android' ? 0 : undefined,
      includeFontPadding: Platform.OS === 'android' ? false : undefined,
    },
    inputText: {
      color: style.color || theme.Text.text,
      fontSize: style.fontSize,
      textAlign: style.textAlign,
      fontFamily: `Cairo-${style.fontWeight}-Tight`,
      includeFontPadding: false,
      lineHeight: style.fontSize ? style.fontSize * 1.2 : 28,
      textTransform: style.textTransform,
      textDecorationColor: style.color || theme.Text.text,
    },
  });
