import { forwardRef, ForwardedRef, useRef } from 'react';

import { styled } from '../../stitches.config';

import { useValue } from '../../hooks';
import {
    BaseFormInputStyles,
    BaseFormInput,
    BaseFormInputProps,
} from '../internal';

const StyledFormInput = styled(BaseFormInput, BaseFormInputStyles, {
    cursor: 'text',
});

const StyledInput = styled('input', {
    backgroundColor: 'transparent',
    height: '$space$full',
    outline: 'none',
    width: '$space$full',
});

type Value = string | number;

export interface InputProps<V extends Value> extends BaseFormInputProps<V> {
    /** Type of the input */
    type?: HTMLInputElement['type'];

    /** Placeholder to show when there is no value */
    placeholder?: string;

    /** Specifies autocomplete on the input */
    autoComplete?: HTMLInputElement['autocomplete'];

    /** Props to pass to the input */
    inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
}

/**
 * Input component
 */
const _Input = <V extends Value>(
    props: InputProps<V>,
    ref: ForwardedRef<HTMLDivElement>,
): JSX.Element => {
    // get the values
    const {
        id,
        value,
        defaultValue,
        onChange = () => null,
        type = 'text',
        placeholder,
        autoComplete = 'off',
        inputProps = {},
        disabled = false,
        ...otherProps
    } = props;

    // store the input in a ref
    const inputRef = useRef<HTMLInputElement | null>(null);

    // manage the internal value
    const [internalValue, setInternalValue] = useValue<V>({
        initialValue: '' as V,
        value: value,
        defaultValue: defaultValue,
        onChange: onChange,
    });

    return (
        <StyledFormInput
            ref={ref}
            focusRef={inputRef}
            disabled={disabled}
            {...otherProps}
        >
            <StyledInput
                ref={inputRef}
                id={id}
                type={type}
                value={internalValue}
                disabled={disabled}
                onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
                    if (disabled) {
                        return;
                    }

                    if (type === 'number') {
                        setInternalValue(Number(event.target.value) as V);
                    } else {
                        setInternalValue(event.target.value as V);
                    }
                }}
                placeholder={placeholder}
                autoComplete={autoComplete}
                {...inputProps}
            />
        </StyledFormInput>
    );
};

export const Input = forwardRef(_Input) as <V extends Value>(
    props: InputProps<V> & {
        ref?: ForwardedRef<HTMLDivElement>;
    },
) => ReturnType<typeof _Input>;
