import React from 'react';
import { block } from 'bem-cn';
import { TextInput, Button, Icon, Spin } from 'lego-on-react';
import { i18n, formatDate } from 'i18n2';

import notify from 'lib2/notify';
import hasPermission from 'lib2/hasPermission';
import { PricingStore } from 'lib2/stores';

import directory from 'api2/directory';

import SpinOverlay from 'components2/SpinOverlay';
import TooltipBox from 'components/TooltipBox';
import Form from 'components2/Form';
import QuestionIcon from 'components/Icon/Question';

import './index.css';

const b = block('promo-code');

function getDefaultPromocode() {
    return location.hash.substring(1);
}

export default class Promocode extends React.PureComponent {
    constructor(props) {
        super(props);

        this.state = {
            text: getDefaultPromocode() || '',
            isFormOpen: !PricingStore.get('promocode'),
        };

        this._onInputChange = this._onInputChange.bind(this);
        this._onPricingStoreChange = this._onPricingStoreChange.bind(this);
        this._onToggle = this._onToggle.bind(this);
        this._setInputRef = this._setInputRef.bind(this);
        this._onSubmit = this._onSubmit.bind(this);
    }

    componentDidMount() {
        this._onPricingStoreChange();
        this._pricingStoreListener = PricingStore.onChange(this._onPricingStoreChange);
    }

    componentWillUnmount() {
        this._pricingStoreListener.remove();
    }

    _onPricingStoreChange() {
        this.setState({
            promocode: PricingStore.get('promocode'),
        });
    }

    _onInputChange(text) {
        this.setState({
            text,
            promocodeError: null,
        });
    }

    _onCancel() {
        this.setState({
            isFormOpen: false,
        });
    }

    _onToggle() {
        this.setState({
            isFormOpen: !this.state.isFormOpen,
            promocodeError: null,
        }, () => {
            this._focus();
        });
    }

    _onSubmit() {
        const { text } = this.state;

        this.setState({
            busy: true,
            promocodeError: null,
        });

        directory.send('POST', '/v11/subscription/promocodes/activate/', {
            body: JSON.stringify({
                id: text,
            }),
        })
            .then(({ body, ok }) => {
                if (!ok) {
                    return this.setState({
                        promocodeError: i18n(`backend_errors.${body.code}`) || i18n('common.status.failed'),
                    });
                }

                PricingStore.set('promocode', body);

                this.setState({
                    isFormOpen: false,
                    text: '',
                });

                notify(i18n('balance.promocode.success'), 'success');
            })
            .finally(() => {
                if (!this._unmounted) {
                    this.setState({
                        busy: false,
                    });
                }
            });
    }

    _renderForm() {
        const { text, promocodeError, busy, promocode } = this.state;

        if (!hasPermission('activate_promocode')) {
            return null;
        }

        return (
            <React.Fragment>
                <div className={b('form')}>
                    <Form
                        cls={b('form')}
                        onSubmit={this._onSubmit}
                    >
                        <Form.Field>
                            <TextInput
                                theme="normal"
                                size="m"
                                cls={b('input')}
                                text={text}
                                hasClear
                                placeholder={i18n('balance.promocode.placeholder')}
                                autoComplete={false}
                                onChange={this._onInputChange}
                                ref={this._setInputRef}
                            />
                            <Button
                                cls={b('button', { role: 'submit' })}
                                text={i18n('common.action.apply')}
                                onClick={this._onSubmit}
                                disabled={!text || busy}
                                theme="normal"
                                size="m"
                            />
                            {promocode && (
                                <Button
                                    cls={b('button', { role: 'cancel' })}
                                    text={i18n('common.action.cancel')}
                                    onClick={this._onToggle}
                                    theme="link"
                                    size="m"
                                />
                            )}
                        </Form.Field>
                        {promocodeError && (
                            <Form.Error cls={b('error')}>
                                {promocodeError}
                            </Form.Error>
                        )}
                        <SpinOverlay
                            progress={busy}
                            spinVisible={false}
                        />
                    </Form>
                    <Spin
                        cls={b('spin')}
                        size="xs"
                        progress={busy}
                    />
                </div>
            </React.Fragment>
        );
    }

    _focus() {
        if (this._input) {
            this._input.focus();
        }
    }

    _setInputRef(input) {
        this._input = input;
    }

    _renderCode() {
        const { promocode } = this.state;

        if (!promocode) {
            return null;
        }

        const { name, id, description, expires } = promocode;
        const details = i18n('balance.promocode.expiration', {
            expiration_date: formatDate(expires),
        });

        return (
            <React.Fragment>
                <div className={b('code')}>
                    <div
                        title={name || id}
                        className={b('value')}
                    >
                        <div className={b('name')}>
                            {name || id}
                        </div>
                        <TooltipBox
                            cls={b('tip')}
                            tip={description}
                            theme="normal"
                            to="right"
                            size="s"
                        >
                            <Icon
                                cls={b('tip-icon')}
                                glyph="yes"
                            >
                                <QuestionIcon />
                            </Icon>
                        </TooltipBox>
                    </div>
                    {hasPermission('activate_promocode') && (
                        <Button
                            cls={b('button', { role: 'toggle' })}
                            text={i18n('balance.promocode.change')}
                            onClick={this._onToggle}
                            theme="link"
                            type="pseudo"
                            size="m"
                        />
                    )}
                    <div className={b('details')}>{details}</div>
                </div>
            </React.Fragment>
        );
    }

    render() {
        const { cls } = this.props;
        const { isFormOpen } = this.state;

        return (
            <div className={b({}).mix(cls)}>
                {isFormOpen ? this._renderForm() : this._renderCode()}
            </div>
        );
    }
}
