import React, { useCallback, useState } from 'react';
import PropTypes from 'prop-types';
import { createNamespace } from '../../tools/namingTools';
import FormLabel from '../form-label/FormLabel';
import { generateUniqueID } from '../../tools/helpers';
// IMPORTANT: (s)css should be imported after other atoms/components
import './styles/Textarea.scss';

const n = createNamespace('Textarea');

const Textarea = ({
    name,
    label,
    defaultValue,
    error,
    inputRef,
    hiddenLabel,
    placeholder,
    required,
    maxLength,
    ...otherProps
}) => {
    const [currentValue, setCurrentValue] = useState(defaultValue || '');

    const handleInputChange = useCallback(event => {
        const newValue = event.target.value;
        setCurrentValue(newValue);

        if (otherProps.onChange) {
            otherProps.onChange(event);
        }
    }, [otherProps]);

    if (!label) {
        return null;
    }

    const controlModifier = error && 'with-errors';
    const labelTextModifier = hiddenLabel ? 'hidden' : null;
    const errorId = generateUniqueID(['error', name]);
    const characterCountId = generateUniqueID(['character-count', name]);

    // Character count logic
    const showCharacterCount = Boolean(maxLength);
    const currentLength = currentValue.length;
    const remaining = maxLength - currentLength;
    const isOverLimit = remaining < 0;
    const characterCountText = showCharacterCount ? `${remaining}` : null;
    const characterCountState = isOverLimit ? 'error' : null;

    return (
        <div {...n('group').props}>
            <FormLabel
                labelText={label}
                required={required}
                labelProps={n('label').withTestId().props}
                textProps={n('text', labelTextModifier).props}
                htmlFor={name}
            />
            <div {...n('textarea-wrapper').props}>
                <textarea
                    id={name}
                    name={name}
                    ref={inputRef}
                    defaultValue={defaultValue}
                    placeholder={placeholder}
                    aria-invalid={Boolean(error)}
                    aria-describedby={[
                        Boolean(error) && errorId,
                        characterCountText && characterCountId
                    ].filter(Boolean).join(' ')}
                    onChange={handleInputChange}
                    {...otherProps}
                    {...n('control', controlModifier).props}
                />
                {characterCountText && (
                    <div
                        {...n('character-count', characterCountState ? [characterCountState] : null).props}
                        id={characterCountId}
                        aria-live="polite"
                    >
                        {characterCountText}
                    </div>
                )}
            </div>
            {error && (
                <span {...n('error').withTestId().props} aria-live="polite" id={errorId}>
                    {error}
                </span>
            )}
        </div>
    );
};

Textarea.propTypes = {
    name: PropTypes.string.isRequired,
    label: PropTypes.string.isRequired,
    defaultValue: PropTypes.string,
    error: PropTypes.string,
    placeholder: PropTypes.string,
    inputRef: PropTypes.func,
    hiddenLabel: PropTypes.bool,
    required: PropTypes.bool,
    maxLength: PropTypes.number
};

Textarea.defaultProps = {
    defaultValue: '',
    error: null,
    inputRef: null,
    placeholder: null,
    hiddenLabel: false,
    required: false,
    maxLength: null
};

export default Textarea;
