import React from 'react'
import PropTypes from 'prop-types'
import Form from 'react-toolkit/form'
import FormError, {reason} from 'common-fe/utils/form-error'
import TextInput from 'react-uikit/input-text'
import Button from 'react-uikit/button'
import inputNames from 'common-fe/constants/input-names'
import {densifyObj} from 'common-fe/utils'
import {validateInput} from 'common-fe/utils/validation'
import BEMModule from 'utils/bem'
import styles from './styles.scss'
const bem = new BEMModule(styles)

class PasswordSettingsForm extends React.Component {
    static formName = 'password-settings'

    static defaultState = {
        data: {
            [inputNames.PASSWORD_CONFIRM]: '',
            [inputNames.PASSWORD_NEW]: '',
            [inputNames.PASSWORD]: '',
        },
        error: {},
    }

    form = React.createRef()

    get initialState() {
        return {
            data: {...PasswordSettingsForm.defaultState.data},
            error: {...PasswordSettingsForm.defaultState.error},
        }
    }

    change = ({name, value}) => {
        this.props.onChange && this.props.onChange({[name]: value})
    }

    updatePassword = (data) => {
        const {updatePassword, user, onError, onSubmit} = this.props

        if (!updatePassword) {
            return
        }

        const payload = densifyObj({
            userId: user.id,
            [inputNames.PASSWORD_NEW]: data[inputNames.PASSWORD_NEW],
            [inputNames.PASSWORD]: data[inputNames.PASSWORD],
        })

        updatePassword(payload)
            .then(() => onSubmit && onSubmit(payload))
            .catch((err) => {
                if (!err.inlineErrors || !err.inlineErrors.length || !onError) {
                    return
                }

                const error = new FormError(
                    Object.keys(PasswordSettingsForm.defaultState.data),
                    err.inlineErrors
                )

                onError && onError(error)
            })
    }

    update = ({name}) => {
        const {data} = this.props

        switch (name) {
            case inputNames.PASSWORD_NEW:
                // Revalidate the new password confirmation when we update
                // the new password.
                if (data[inputNames.PASSWORD_CONFIRM].length !== 0) {
                    setTimeout(() => {
                        this.form && this.form.current.validate()
                    }, 0)
                }
        }
    }

    validate = ({name, value, isRequired}) => {
        const {data, error: errors} = this.props

        let error = validateInput({name, value, isRequired})

        switch (name) {
            case inputNames.PASSWORD:
                error = null
                break

            case inputNames.PASSWORD_NEW:
                if (error) {
                    delete errors[inputNames.PASSWORD_CONFIRM]
                }

                break

            case inputNames.PASSWORD_CONFIRM: {
                const isNewPasswordValid = !this.validate({
                    name: inputNames.PASSWORD_NEW,
                    value: data[inputNames.PASSWORD_NEW],
                    isRequired: true,
                })

                if (!isNewPasswordValid) {
                    error = null
                    break
                }

                if (value !== data[inputNames.PASSWORD_NEW]) {
                    error = reason.PASSWORD_MATCH_ERR
                    break
                }

                break
            }

            default:
                break
        }

        return error
    }

    render() {
        const {data, error, validateOnUpdate, onCancel, onError} = this.props

        const classNames = bem.classNames('c-password-settings-form')
        const labelClassNames = bem.classNames(
            'c-password-settings-form__label'
        )
        const fieldClassNames = bem.classNames(
            'c-password-settings-form__field'
        )
        const buttonClassNames = bem.classNames(
            'c-password-settings-form__button'
        )
        const submitClassNames = bem.classNames(
            'c-password-settings-form__submit'
        )
        const editClassNames = bem.classNames('c-password-settings-form__edit')

        return (
            <Form
                className={classNames}
                data={data}
                error={error}
                name={PasswordSettingsForm.formName}
                ref={this.form}
                submitOnEnter={false}
                validate={this.validate}
                validateOnUpdate={validateOnUpdate}
                onChange={this.change}
                onError={onError}
                onSubmit={this.updatePassword}
                onUpdate={this.update}
            >
                <p className={editClassNames} title="Edit password">
                    Change password
                </p>
                <label
                    className={labelClassNames}
                    htmlFor={inputNames.PASSWORD}
                >
                    Old Password
                </label>
                <Form.Field
                    component={TextInput}
                    className={fieldClassNames}
                    name={inputNames.PASSWORD}
                    required
                    size="small"
                    type="password"
                />
                <label
                    className={labelClassNames}
                    htmlFor={inputNames.PASSWORD_NEW}
                >
                    New Password
                </label>
                <Form.Field
                    component={TextInput}
                    className={fieldClassNames}
                    name={inputNames.PASSWORD_NEW}
                    required
                    size="small"
                    type="password"
                />
                <label
                    className={labelClassNames}
                    htmlFor={inputNames.PASSWORD_CONFIRM}
                >
                    Confirm new
                </label>
                <Form.Field
                    component={TextInput}
                    className={fieldClassNames}
                    name={inputNames.PASSWORD_CONFIRM}
                    required
                    size="small"
                    type="password"
                />
                <div className={submitClassNames}>
                    <Button
                        className={buttonClassNames}
                        isOutline
                        variant="neutral"
                        size="small"
                        text="Cancel"
                        onClick={onCancel}
                    />
                    <Form.SubmitTrigger
                        render={({submit}) => (
                            <Button
                                className={buttonClassNames}
                                variant="primary"
                                text="Save"
                                size="small"
                                onClick={submit}
                            />
                        )}
                    />
                </div>
            </Form>
        )
    }
}

PasswordSettingsForm.propTypes = {
    data: PropTypes.shape({
        [inputNames.FIRST_NAME]: PropTypes.string,
        [inputNames.LAST_NAME]: PropTypes.string,
    }),
    error: PropTypes.shape({
        [inputNames.FIRST_NAME]: PropTypes.string,
        [inputNames.LAST_NAME]: PropTypes.string,
    }),
    updatePassword: PropTypes.func,
    user: PropTypes.shape({
        email: PropTypes.string,
        firstName: PropTypes.string,
        id: PropTypes.string,
        isActive: PropTypes.bool,
        isEmailVerified: PropTypes.bool,
        lastName: PropTypes.string,
        portfolios: PropTypes.Array,
        roles: PropTypes.Array,
    }),
    validateOnUpdate: PropTypes.bool,
    onCancel: PropTypes.func,
    onChange: PropTypes.func,
    onError: PropTypes.func,
    onSubmit: PropTypes.func,
}

PasswordSettingsForm.defaultProps = {
    data: {...PasswordSettingsForm.defaultState.data},
    error: {...PasswordSettingsForm.defaultState.error},
    validateOnUpdate: true,
}
export default PasswordSettingsForm
