import React, {
  FC,
  ReactType,
  RefObject,
  ReactNode,
  useState,
  useEffect,
} from 'react';
import classNames from 'classnames';
import css from './index.module.css';

export interface InputProps {
  id?: string;
  label?: string;
  labelStyle?: string;
  type?: 'text' | 'number' | 'email' | 'hidden' | 'search' | 'password' | 'tel';
  placeholder?: string;
  name?: string;
  autocomplete?: string;
  hideLabel?: boolean;
  required?: boolean;
  value?: string;
  Icon?: ReactType;
  error?: string;
  autoFocus?: boolean;
  disabled?: boolean;
  readOnly?: boolean;
  roundedCorners?: boolean;
  onChange?: (e) => void;
  onBlur?: (e) => void;
  onKeyDown?: (e) => void;
  onKeyUp?: (e) => void;
  onFocus?: (e) => void;
  onInvalid?: (e) => void;
  onInput?: (e) => void;
  inputRef?: RefObject<HTMLInputElement>;
  children?: ReactNode;
  style?: 'normal' | 'booking';
  isOptionalDisplay?: boolean;
  data?: unknown;
  isKeyBoardOpen?: (e) => void;
}

const Input: FC<InputProps> = ({
  id,
  autocomplete,
  label,
  labelStyle,
  type = 'submit',
  placeholder,
  hideLabel,
  required,
  name,
  value,
  onChange,
  onKeyDown,
  onKeyUp,
  onBlur,
  onFocus,
  Icon,
  error,
  disabled,
  readOnly,
  onInvalid,
  onInput,
  inputRef,
  children,
  style = 'normal',
  isOptionalDisplay = false,
  data,
  isKeyBoardOpen,
}) => {
  const [isActive, setActive] = useState(false);

  const inputClassNames = classNames(css.input, {
    [css.inputIcon]: Icon,
    [css.inputError]: error,
    [css.inputSmall]: labelStyle === 'small',
    [css.inputBooking]: style === 'booking',
    [css.inputActive]: isActive,
  });

  useEffect(() => {
    setActive(value != '');
  }, [value]);

  const disableFocus = (e): void => {
    if (e.target.value === '') {
      setActive(false);
    }
  };

  const dataAttributes = {};
  Object.keys(data || {}).forEach(k => (dataAttributes[`data-${k}`] = data[k]));

  return (
    <>
      <label className={inputClassNames} data-testid="Input">
        {!hideLabel && style != 'booking' && (
          <span className={css.input__label}>{label}</span>
        )}

        <div className={css.input__fieldWrap}>
          {Icon && <Icon className={css.input__icon} width="18px" />}
          {!hideLabel && style === 'booking' && (
            <span className={css.input__label}>{label}</span>
          )}
          <input
            id={id}
            autoComplete={autocomplete}
            disabled={disabled}
            ref={inputRef}
            onBlur={(e: React.FocusEvent<HTMLInputElement>): void => {
              disableFocus(e);
              if (isKeyBoardOpen) isKeyBoardOpen(false);
              if (onBlur) onBlur(e);
            }}
            name={name}
            required={required}
            type={type}
            placeholder={placeholder}
            aria-label={label}
            className={css.input__field}
            value={value}
            onChange={(e: React.ChangeEvent<HTMLInputElement>): void => {
              setActive(true);
              if (onChange) onChange(e);
            }}
            onKeyDown={onKeyDown}
            onKeyUp={onKeyUp}
            onFocus={(e: React.FocusEvent<HTMLInputElement>): void => {
              setActive(true);
              if (isKeyBoardOpen) isKeyBoardOpen(true);
              if (onFocus) onFocus(e);
            }}
            onInvalid={onInvalid}
            onInput={onInput}
            readOnly={readOnly}
            {...dataAttributes}
          />
          {children}
        </div>
        {error && <div className={css.input__error}>{error}</div>}
      </label>
      {!error && !required && isOptionalDisplay && (
        <span className={css.input__optional}>Optional</span>
      )}
    </>
  );
};

export default Input;
