/* eslint-disable react-hooks/exhaustive-deps */
import React, {
  forwardRef,
  useContext,
  useEffect,
  useImperativeHandle,
  useRef,
  useState,
} from 'react';
import {
  NativeSyntheticEvent,
  TextInput,
  TextInputFocusEventData,
  TouchableOpacity,
  View,
} from 'react-native';
import { useComponentId } from '../Application';
import {
  ApplicationContext,
  ComponentContext,
  MiniAppContext,
} from '../Context';
import { Icon } from '../Icon';
import { useScaleSize } from '../Text';
import { Spacing } from '../Consts';
import {
  ErrorView,
  FloatingView,
  getBorderColor,
  getSizeStyle,
  RenderTrailing,
} from './common';
import { InputMoneyProps } from './index';
import styles from './styles';
import { formatNumberToMoney } from './utils';
import SystemTextInput from './SystemTextInput';

const InputMoney = forwardRef(
  (
    {
      value,
      onChangeText,
      floatingValue,
      floatingIcon,
      size = 'small',
      loading,
      onBlur,
      onFocus,
      errorMessage,
      trailing,
      trailingColor,
      onPressTrailing,
      disabled = false,
      floatingIconColor,
      required = false,
      errorSpacing,
      style,
      params,
      hintText,
      onPressFloatingIcon,
      placeholder = '0đ',
      showClearIcon = true,
      currency = 'đ',
      ...props
    }: InputMoneyProps,
    ref,
  ) => {
    const { theme } = useContext(ApplicationContext);
    const context = useContext<any>(MiniAppContext);
    const scaleHeight = useScaleSize(size === 'small' ? 48 : 56, 1.1);
    const scaledFontSize = useScaleSize(20);
    const [focused, setFocused] = useState(false);
    const [displayValue, setDisplayValue] = useState('');
    const [numericValue, setNumericValue] = useState('');
    const [lastDisplayValue, setLastDisplayValue] = useState('');
    const inputRef = useRef<TextInput>(null);
    const componentName = 'InputMoney';

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

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

    const digitLimit =
      typeof (props as any)?.maxLength === 'number'
        ? (props as any).maxLength
        : Number.POSITIVE_INFINITY;

    useEffect(() => {
      if (value !== undefined && typeof value === 'string') {
        const cleanValue = value.replace(/\D/g, '');
        if (cleanValue !== numericValue) {
          setNumericValue(cleanValue);
          updateDisplayValue(cleanValue);
        }
      }
    }, [value]);

    useEffect(() => {
      setLastDisplayValue(displayValue);
    }, [displayValue]);

    const updateDisplayValue = (numeric: string) => {
      if (!numeric) {
        setDisplayValue('');
        return;
      }
      const formatted = formatNumberToMoney(Number(numeric));
      setDisplayValue(formatted ? `${formatted}${currency}` : '');
    };

    const parseInputText = (text: string): string => {
      if (!text) return '';
      const currencyRegex = new RegExp(` ?${currency}$`, 'g');
      const textWithoutCurrency = text.replace(currencyRegex, '').trim();
      return textWithoutCurrency.replace(/[^\d]/g, '');
    };

    const updateNumericValue = (val: string) => {
      let next = val.replace(/[^\d]/g, '');
      if (next.length > digitLimit) next = next.slice(0, digitLimit);
      if (/^\d*$/.test(next)) {
        setNumericValue(next);
        updateDisplayValue(next);
        onChangeText?.(next);
      }
    };

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

    const _onChangeText = (text: string) => {
      if (!text) {
        setDisplayValue('');
        setNumericValue('');
        onChangeText?.('');
        return;
      }
      if (text.length < lastDisplayValue.length) {
        const lastChar = lastDisplayValue.charAt(lastDisplayValue.length - 1);
        const isRemovingCurrency =
          lastDisplayValue.endsWith(currency) || lastChar === ' ';
        const isRemovingDot = lastChar === '.';
        if (isRemovingCurrency || isRemovingDot) {
          const currentNumericValue = numericValue;
          if (currentNumericValue.length > 0) {
            const newNumericValue = currentNumericValue.slice(0, -1);
            updateNumericValue(newNumericValue);
            return;
          }
        }
      }
      const newNumericValue = parseInputText(text);
      updateNumericValue(newNumericValue);
    };

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

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

    const _setText = (text: string) => {
      if (!text) {
        setDisplayValue('');
        setNumericValue('');
        onChangeText?.('');
        return;
      }
      const newNumericValue = parseInputText(text);
      updateNumericValue(newNumericValue);
    };

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

    const renderInputView = () => {
      const disabledColor = theme.colors.text.disable;
      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}>
            <SystemTextInput
              {...props}
              accessibilityLabel={`${componentId}`}
              textAlignVertical="center"
              ref={inputRef}
              accessibilityState={{
                disabled: disabled,
                ...props.accessibilityState,
              }}
              style={[
                {
                  width: '100%',
                  paddingLeft: Spacing.M,
                  height: '100%',
                  fontSize: scaledFontSize,
                  paddingVertical: Spacing.S,
                  fontWeight: 'bold',
                },
                {
                  color: textColor,
                },
              ]}
              allowFontScaling={false}
              textBreakStrategy="highQuality"
              value={displayValue}
              onChangeText={_onChangeText}
              onFocus={_onFocus}
              onBlur={_onBlur}
              placeholder={placeholder}
              selectionColor={theme.colors.primary}
              placeholderTextColor={placeholderColor}
              keyboardType={'numeric'}
              maxLength={undefined}
            />
          </View>
          <View style={styles.iconView}>
            {showClearIcon && focused && displayValue ? (
              <TouchableOpacity
                accessibilityLabel={`${componentId}|clear-icon-touch`}
                style={styles.iconWrapper}
                onPress={onClearText}
              >
                <Icon
                  source="24_navigation_close_circle_full"
                  size={16}
                  color={theme.colors.text.hint}
                  accessibilityLabel={`${componentId}|clear-icon`}
                />
              </TouchableOpacity>
            ) : null}
            <RenderTrailing
              color={iconTintColor}
              icon={trailing}
              onPressIcon={onPressTrailing}
              loading={loading}
              componentId={componentId}
            />
          </View>
        </View>
      );
    };

    let inputState = 'active';
    if (displayValue) {
      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 InputMoney;
