import React from 'react';
import { isUndefined } from 'lodash';
import { formatMessage } from '@orchard/frontend-localization';
import {
    Col,
    FormField,
    Form,
    Field,
    Label,
    Row,
    SelectInput,
    Help
} from '@orchard/frontend-react-components';
import { PAYMENT_DETAILS_FIELD_KEY_CURRENCY } from 'src/constants';
import translations from './i18n';

const CLASS_NAME = 'RecipientFormInput';

type Messages = {
    [key: string]: string
};

const messages: Messages = translations;

type Value = string | number;

interface Option {
    name: string;
    key: string;
}

type Props = {
    inputKey: string;
    type: string;
    name: string;
    isRequired?: boolean;
    example?: string | null;
    refreshRequirementsOnChange: boolean;
    valuesAllowed?: Option[] | null;
    onHandleChange(key: string, refresh: boolean): void;
    value?: Value;
    error?: string;
    disabled?: boolean;
    maxLength?: number | null;
    tooltip?: string;
};

export const RecipientFormInput: React.FC<Props> = ({
    inputKey,
    type,
    name,
    isRequired,
    example,
    refreshRequirementsOnChange,
    valuesAllowed,
    onHandleChange,
    value,
    error,
    disabled,
    maxLength,
    tooltip
}) => {
    const getFormattedText = (key: string, text: string) => {
        if (key && messages[key])
            return formatMessage(messages[key]);
        // Fall back on provided text if no translation found
        return text;
    };

    const generateDropdownOptions = (options: Option[]) =>
        options.map(({ name: label, key: optionValue }) => (
            { label, value: optionValue }));

    const renderTooltip = () =>
        tooltip && (
            <Help id={ `${inputKey}-help` } message={ formatMessage(tooltip) } />
        );

    const renderDropdown = () => {
        const isCurrency = inputKey === PAYMENT_DETAILS_FIELD_KEY_CURRENCY;

        return (
            <Row className={ `${CLASS_NAME}-row` }>
                <Col xs={ 3 } className={ `${CLASS_NAME}-option` }>
                    <Label
                        text={ getFormattedText(inputKey, name) }
                        isRequired={ isRequired }
                        hasError={ Boolean(error) }
                    />
                    { renderTooltip() }
                </Col>
                <Col xs={ 5 }>
                    <FormField
                        id={ `${inputKey}-recipient-input-field` }
                        errorMessage={ error }
                    >
                        <SelectInput
                            data-testid={ `${inputKey}-recipient-dropdown` }
                            id={ `${inputKey}-recipient-dropdown` }
                            options={ valuesAllowed && generateDropdownOptions(valuesAllowed) }
                            onChange={ (val: string) => onHandleChange(val, refreshRequirementsOnChange) }
                            value={ value }
                            clearable={ !isCurrency }
                            disabled={ isCurrency ? false : disabled || !valuesAllowed }
                            arrowRenderer={ undefined }
                        />
                    </FormField>
                </Col>
            </Row>
        );
    };

    const renderTextInput = () => (
        <Row className={ `${CLASS_NAME}-row` }>
            <Col xs={ 3 } className={ `${CLASS_NAME}-option` }>
                <Label
                    text={ getFormattedText(inputKey, name) }
                    isRequired={ isRequired }
                    hasError={ Boolean(error) }
                />
                { renderTooltip() }
            </Col>
            <Col
                xs={ (maxLength && maxLength <= 32) ? 3 : 5 }
            >
                <FormField
                    id={ `${inputKey}-recipient-input-field` }
                    errorMessage={ error }
                >
                    <Form.Control
                        id={ `${inputKey}-recipient-text-input` }
                        placeholder={ example || '' }
                        data-testid={ `${inputKey}-recipient-text-input` }
                        onChange={
                            ({ target: { value: targetValue } }) =>
                                onHandleChange(targetValue, refreshRequirementsOnChange)
                        }
                        value={ isUndefined(value) ? '' : value }
                    />
                </FormField>
            </Col>
        </Row>
    );

    const renderRadioInput = () => {
        if (valuesAllowed && valuesAllowed.length === 2) {
            const { name: name1, key: key1 } = valuesAllowed[0];
            const { name: name2, key: key2 } = valuesAllowed[1];
            return (
                <Row className={ `${CLASS_NAME}-row ${CLASS_NAME}-row-radio` }>
                    <Col xs={ 3 } className={ `${CLASS_NAME}-option` }>
                        <Label
                            text={ getFormattedText(inputKey, name) }
                            isRequired={ isRequired }
                            hasError={ Boolean(error) }
                        />
                        { renderTooltip() }
                    </Col>
                    <Col xs={ 4 }>
                        <Field
                            labelText=""
                            controlId={ `${inputKey}-recipient-input-field` }
                            errorMessage={ error }
                        >
                            <Form.Check
                                inline
                                name={ name }
                                type="radio"
                                id={ `${key1}-radio-button` }
                                className={ `${CLASS_NAME}-radio-button` }
                                data-testid={ `${key1}-radio-button` }
                                onChange={ () => onHandleChange(key1, refreshRequirementsOnChange) }
                                label={ getFormattedText(key1, name1) }
                            />
                            <Form.Check
                                inline
                                name={ name }
                                type="radio"
                                id={ `${key2}-radio-button` }
                                className={ `${CLASS_NAME}-radio-button` }
                                data-testid={ `${key2}-radio-button` }
                                onChange={ () => onHandleChange(key2, refreshRequirementsOnChange) }
                                label={ getFormattedText(key2, name2) }
                            />
                        </Field>
                    </Col>
                </Row>
            );
        }
    };

    const renderFormInput = () => {
        let renderedInput;
        switch (type) {
            case 'text':
                renderedInput = renderTextInput();
                break;
            case 'dropdown':
                renderedInput = renderDropdown();
                break;
            case 'select':
                if (valuesAllowed && valuesAllowed.length === 2)
                    renderedInput = renderRadioInput();
                else
                    renderedInput = renderDropdown();
                break;
            case 'radio':
                renderedInput = renderRadioInput();
                break;
            default:
                renderedInput = null;
                break;
        }
        return renderedInput;
    };

    return (
        <Form.Group id={ `${inputKey}-recipient-input` }>
            { renderFormInput() }
        </Form.Group>
    );
};

export default RecipientFormInput;
