import React, {forwardRef, useMemo} from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
import {IconButton} from '@components/_HuGo/Button';
import {
  TextInput,
  TextInputProps,
  TextInputType,
} from '@components/_core/TextInput';
import {Typography} from '@components/_core/Typography';
import {useTheme} from '@shared/theme';
import {CURRENCIES, CurrencyKey} from '@shared/currencies';
import {INTEGER_REGEX} from '@shared/regexs';

import {InputAccessibilities, InputCommonProps} from '../../interfaces';
import {INPUT_ICONS} from '../../constants';
import {
  UseInputControllerProps,
  useInputController,
} from '../../hooks/useInputController';
import {useInputRef} from '../../hooks/useInputRef';
import {InputCore} from '../InputCore';
import {InputBox} from '../InputBox';
import {formatNumber, isValidInput, limitDecimals} from '../../utils';
import {InputHelper} from '../InputHelper';
import {styles} from './styles';
import {InputCurrencySelect} from './components/InputCurrencySelect';

export type InputMoneyVariant = 'default' | 'withCurrency';

interface InputMoneyProps
  extends InputCommonProps,
    InputAccessibilities,
    Omit<TextInputProps, 'size'> {
  currencySymbol?: string;
  withDecimals?: boolean;
  variant?: InputMoneyVariant;
  currencyCode?: CurrencyKey;
  onChangeCurrencyCode?: (currencyCode: CurrencyKey) => void;
  withLimitDecimals?: boolean;
}

const Input = forwardRef<TextInputType, InputMoneyProps>(
  (
    {
      value,
      onChangeText,
      label,
      currencySymbol = '$',
      helper,
      isError,
      isSuccess,
      disabled,
      onFocus,
      onBlur,
      style,
      withDecimals = true,
      size,
      withLimitDecimals = false,
      ...textInputProps
    },
    ref,
  ) => {
    const {theme} = useTheme();
    const {
      inputRef,
      focused,
      focusInput,
      onInputBlur,
      onInputFocus,
      clearInput,
    } = useInputRef({ref, onFocus, onBlur, onChangeText});

    const formattedValue = useMemo(
      () => formatNumber(value, withDecimals),
      [value, withDecimals],
    );

    const onChange = (text: string) => {
      const isInteger = !text || text.match(INTEGER_REGEX);
      if (isValidInput(text) && (withDecimals || isInteger)) {
        const limitedText = withLimitDecimals
          ? limitDecimals(text, withDecimals)
          : text;
        onChangeText?.(limitedText);
      }
    };

    return (
      <InputCore
        label={label}
        helper={helper}
        isSuccess={isSuccess}
        isError={isError}
        focused={focused}
        disabled={disabled}
        style={style as StyleProp<ViewStyle>}>
        <InputBox
          isSuccess={isSuccess}
          isError={isError}
          disabled={disabled}
          size={size}
          focused={focused}
          onPress={focusInput}
          LeftComponent={
            !!currencySymbol && (
              <Typography
                color={theme.text.neutral[disabled ? 'disabled' : 'lighter']}>
                {currencySymbol}
              </Typography>
            )
          }
          RightComponent={
            focused &&
            value?.length && (
              <IconButton
                Icon={INPUT_ICONS.clear}
                variant="flat"
                onPress={clearInput}
              />
            )
          }>
          <View style={styles.flex}>
            <Typography
              color={
                disabled
                  ? theme.text.neutral.disabled
                  : theme.text.neutral.default
              }>
              {formattedValue}
            </Typography>
            <TextInput
              ref={inputRef}
              value={value}
              onChangeText={onChange}
              onFocus={onInputFocus}
              onBlur={onInputBlur}
              editable={!disabled}
              keyboardType="numeric"
              style={styles.hidden}
              {...textInputProps}
            />
          </View>
        </InputBox>
      </InputCore>
    );
  },
);

type InputMoneyControllerProps = InputMoneyProps & UseInputControllerProps;

export const InputMoney = forwardRef<TextInputType, InputMoneyProps>(
  (props, ref) => {
    const {
      variant = 'default',
      currencyCode,
      onChangeCurrencyCode,
      ...restProps
    } = props;

    return variant === 'withCurrency' ? (
      <>
        <View style={styles.inputMoneyContainer}>
          <InputCurrencySelect
            {...restProps}
            value={currencyCode}
            onChange={onChangeCurrencyCode}
            style={styles.inputSelect}
            helper="" // Need this so that restProps.helper is not passed to InputCurrencySelect
          />
          <Input
            {...restProps}
            label=" " // Need an empty label to have some marginTop
            currencySymbol={
              currencyCode ? CURRENCIES[currencyCode].symbol : undefined
            }
            style={styles.inputMoney}
            helper="" // Need this so that restProps.helper is not passed to Input
          />
        </View>
        <InputHelper {...props} style={props.style as StyleProp<ViewStyle>} />
      </>
    ) : (
      <Input {...props} ref={ref} />
    );
  },
);

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

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