import React, {
  forwardRef,
  useContext,
  useImperativeHandle,
  useRef,
  useState,
} from 'react';
import {
  NativeSyntheticEvent,
  TextInput,
  TextInputFocusEventData,
  TouchableOpacity,
  View,
} from 'react-native';
import { useComponentId } from '../Application';
import { Icon } from '../Icon';
import { exportFontFamily, useScaleSize } from '../Text';
import { Spacing } from '../Consts';
import {
  ErrorView,
  FloatingView,
  getBorderColor,
  getSizeStyle,
  RenderTrailing,
} from './common';
import { InputProps } from './index';
import styles from './styles';
import SystemTextInput from './SystemTextInput';
import {
  ApplicationContext,
  ComponentContext,
  MiniAppContext,
} from '../Context';

/**
 * Input default component
 */
const Input = forwardRef(
  (
    {
      value,
      onChangeText,
      floatingValue,
      floatingIcon,
      size = 'small',
      placeholder,
      onBlur,
      onFocus,
      errorMessage,
      trailing,
      trailingColor,
      onPressTrailing,
      disabled = false,
      floatingIconColor,
      required = false,
      errorSpacing,
      loading = false,
      leadingIcon,
      leadingIconColor,
      fontWeight,
      secureTextEntry,
      keyboardType,
      style,
      params,
      hintText,
      editable = true,
      onPressFloatingIcon,
      onPressLeadingIcon,
      showClearIcon = true,
      defaultValue,
      ...props
    }: InputProps,
    ref,
  ) => {
    const { theme } = useContext(ApplicationContext);
    const context = useContext<any>(MiniAppContext);
    const scaledFontSize = useScaleSize(14);
    const scaleHeight = useScaleSize(size === 'small' ? 48 : 56, 1.1);
    const [focused, setFocused] = useState(false);
    const haveValue = !!value || !!defaultValue;
    const inputRef = useRef<TextInput | null>(null);
    const componentName = 'Input';

    const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;

    const { componentId } = useComponentId(
      `${componentName}/${placeholder}`,
      props.accessibilityLabel,
    );

    const onClearText = () => {
      inputRef?.current?.clear();
      inputRef.current?.setNativeProps({ text: '' });
      _onChangeText('');
    };

    const _onChangeText = (text: string) => {
      onChangeText?.(text);
    };

    const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
      setFocused(true);
      onFocus?.(e);
    };

    const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
      setFocused(false);
      onBlur?.(e);
    };

    const _setText = (text: string) => {
      inputRef?.current?.setNativeProps({ text });
      _onChangeText(text);
    };

    useImperativeHandle(ref, () => {
      return {
        clear: onClearText,
        focus: () => inputRef.current?.focus(),
        blur: () => inputRef.current?.blur(),
        setText: _setText,
      };
    });

    /**
     * Render input view
     */
    const renderInputView = () => {
      const disabledColor = theme.colors.text.disable;
      const secure = secureTextEntry;
      let textColor = theme.colors.text.default;
      let placeholderColor = theme.colors.text.hint;
      let iconTintColor = trailingColor;

      if (disabled) {
        textColor = disabledColor;
        placeholderColor = disabledColor;
        iconTintColor = disabledColor;
      }

      return (
        <View
          style={[
            styles.inputWrapper,
            { backgroundColor: theme.colors.background.surface },
            getSizeStyle(size, undefined, scaleHeight),
            getBorderColor(theme, focused, errorMessage, disabled),
          ]}
        >
          <FloatingView
            floatingValue={floatingValue}
            floatingIconColor={floatingIconColor}
            disabled={disabled}
            required={required}
            floatingIcon={floatingIcon}
            onPress={onPressFloatingIcon}
            componentId={componentId}
          />
          <View style={styles.inputView}>
            {!!leadingIcon && (
              <View style={styles.leadingIconContainer}>
                <TouchableOpacity
                  onPress={onPressLeadingIcon}
                  accessibilityLabel={`${componentId}|leading-icon-touch`}
                >
                  <Icon
                    color={leadingIconColor}
                    source={leadingIcon}
                    size={size === 'small' ? 24 : 32}
                    accessibilityLabel={`${componentId}|leading-icon`}
                  />
                </TouchableOpacity>
              </View>
            )}
            <SystemTextInput
              {...props}
              accessibilityLabel={`${componentId}`}
              editable={editable && !disabled}
              secureTextEntry={secure}
              textAlignVertical="center"
              ref={inputRef}
              accessibilityState={{
                disabled,
                ...props.accessibilityState,
              }}
              style={[
                {
                  flex: 1,
                  paddingLeft: Spacing.M,
                  fontSize: scaledFontSize,
                  height: '100%',
                },
                {
                  color: textColor,
                  fontFamily: exportFontFamily(fontWeight ?? 'regular'),
                },
                secure && haveValue && { fontSize: size === 'small' ? 18 : 22 },
              ]}
              defaultValue={defaultValue}
              allowFontScaling={false}
              textBreakStrategy="highQuality"
              value={value}
              onChangeText={_onChangeText}
              onFocus={_onFocus}
              onBlur={_onBlur}
              placeholder={placeholder}
              selectionColor={theme.colors.primary}
              placeholderTextColor={placeholderColor}
              keyboardType={keyboardType}
            />
          </View>
          <View style={styles.iconView}>
            {showClearIcon && focused && haveValue && (
              <TouchableOpacity
                accessibilityLabel={`${componentId}|clear-icon-touch`}
                accessible={false}
                style={styles.iconWrapper}
                onPress={onClearText}
              >
                <Icon
                  source="24_navigation_close_circle_full"
                  size={16}
                  color={theme.colors.text.hint}
                  accessibilityLabel={`${componentId}|clear-icon`}
                />
              </TouchableOpacity>
            )}
            <RenderTrailing
              color={iconTintColor}
              icon={trailing}
              onPressIcon={onPressTrailing}
              loading={loading}
              componentId={componentId}
            />
          </View>
        </View>
      );
    };

    let inputState = 'active';
    if (value && value?.length > 0) {
      inputState = 'filled';
    }
    if (errorMessage && errorMessage?.length > 0) {
      inputState = 'error';
    }
    if (disabled) {
      inputState = 'disabled';
    }

    return (
      <ComponentContext.Provider
        value={{
          componentName,
          componentId,
          params,
          state: inputState,
        }}
      >
        <View
          style={[
            style,
            styles.wrapper,
            showBaseLineDebug && styles.debugBaseLine,
          ]}
        >
          {renderInputView()}
          <ErrorView
            errorMessage={errorMessage}
            errorSpacing={errorSpacing}
            hintText={hintText}
            componentId={componentId}
          />
        </View>
      </ComponentContext.Provider>
    );
  },
);

export default Input;
