import _ from 'lodash';
import React from 'react';
import PureRenderMixin from 'react-addons-pure-render-mixin';
import classSet from 'classnames';
import { Button, Checkbox } from 'lego-on-react';
import Avatar from 'ui-components/lib/Avatar';
import Loader from 'ui-components/lib/Loader';
import { TRIAL_STATUS } from 'constants/Services';
import StoreMixin from 'lib/StoreMixin';
import { i18n, pluralize } from 'lib/i18n';
import Url from 'lib/Url';
import { toRecord } from 'records/util';

import StatusBarActions from 'actions/StatusBar';
import SubscriptionActions from 'actions/Subscription';
import LicenseActions from 'actions/Licenses';
import ModalActions from 'actions/Modal';

import Icon from 'ui/Icon';
import Tip from 'ui/Tip';

import SubscriptionStore from 'stores/Subscription';
import LicenseStore from 'stores/Licenses';
import OrganizationStore from 'stores/Organizations';
import ConfigStore from 'stores/Config';
import AuthStore from 'stores/Auth';
import PermissionStore from 'stores/Permissions';

import notify from 'services/notify';
import AddSubscribers from './AddSubscribers';

const LicensesList = React.createClass({

    mixins: [StoreMixin, PureRenderMixin],

    getStoreState() {
        const serviceName = this.props.serviceSlug;

        // return ({
        //     serviceName: 'tracker',
        //     pricing: {
        //         per_user: 99,
        //         per_user_with_discount: null,
        //         currency: 'RUB'
        //     },
        //     usersCount: 10,
        //     isContractAvailable: true,
        //     subscribers: [],
        //     subscriberRecordList: [],
        //     selectedItems: this.state ? this.state.selectedItems : [],
        //     isAllChecked: this.state ? this.state.isAllChecked : false,
        //     trial: serviceData && serviceData.trial,
        //     trialStatus: AuthStore.getServiceTrialStatus(serviceName),
        //     isLoading: false
        //
        // });

        this._mountHook = Promise.resolve();

        return {
            serviceName,
            pricing: SubscriptionStore.getPricing(serviceName),
            usersCount: SubscriptionStore.getCurrentUserCount(serviceName),
            isContractAvailable: SubscriptionStore.hasContract(),
            subscribers: LicenseStore.getCurrentSubscribers(serviceName),
            subscriberRecordList: LicenseStore.getCurrentSubscribers(serviceName).map(toRecord),
            selectedItems: this.state ? this.state.selectedItems : [],
            isAllChecked: this.state ? this.state.isAllChecked : false,
            trialStatus: AuthStore.getServiceTrialStatus(serviceName),
            isLoading: false,
            isReady: true,
        };
    },

    componentDidMount() {
        this.subscribe([SubscriptionStore, LicenseStore, OrganizationStore, PermissionStore]);

        const fromQuery = Url.getQueryParam('from');

        // Если перешли со страницы с платежными данными, то сразу показываем попап с добавлением подписок
        if (fromQuery === 'agreement' || Url.getInitialAction() === Url.Actions.ADD_SUBSCRIPTION) {
            // FIXME: нужно разобраться почему это место не работает без setTimeout
            setTimeout(() => {
                if (window.history) {
                    history.replaceState(null, '', location.pathname);
                }

                this._showAddSubscribersPopup();
            }, 0);
        }

        this._update();
    },

    componentWillUnmount() {
        this._mountHook = new Promise(() => {
            // Noop
        });
    },

    _update() {
        this.setState({ isReady: false });

        LicenseActions.read(this.state.serviceName)
            .finally(() => this._mountHook)
            .then(() => {
                this.setState({
                    isReady: true,
                });
            });
    },

    _isSubscriptionListEmpty() {
        return this.state.subscribers.length === 0;
    },

    _onToggleAll(event) {
        const { target } = event;
        const selectedItems = target.checked ? this.state.subscribers : [];

        this.setState({
            isAllChecked: target.checked,
        });

        this._updateSelectedItems(selectedItems);
    },

    _renderList() {
        const { subscriberRecordList } = this.state;

        if (subscriberRecordList.length === 0) {
            return (
                <div className="licenses__list-body" />
            );
        }

        return (
            <div className="licenses__list-body">
                {subscriberRecordList.map(this._renderListItem)}
            </div>
        );
    },

    _renderListItem(item) {
        const compactItemData = { id: Number(item.getId()), type: item.getType() };
        const isSelected = this._isSelectedItem(compactItemData);
        const classes = classSet({
            'licenses__list-item': true,
            action: true,
            'licenses__list-item_selected': isSelected,
        });
        const allowsTrackerManagement = PermissionStore.allowsTrackerManagement();

        const description = item.get('members_count') !== undefined ?
            pluralize(item.get('members_count'), i18n('balance.services.persons')) :
            item.getDescription();
        const component = {};

        if (allowsTrackerManagement) {
            component.checkbox = (
                <Checkbox
                    size="m"
                    theme="normal"
                    onChange={this._onListItemClick.bind(this, compactItemData)}
                    checked={isSelected}
                />
            );

            component.controls = (
                <div className="licenses__list-item-controls">
                    <Button
                        text={i18n('licenses.unsubscribe_one_item')}
                        onClick={this._onRemoveOneItem.bind(this, compactItemData)}
                        size="m"
                        theme="normal"
                    />
                </div>
            );
        }

        return (
            <div
                className={classes}
                key={`${item.getType()}_${item.getId()}`}
            >

                {component.checkbox}

                <Avatar url={item.getAvatar()} />
                <div className="licenses__list-item-info">
                    <span className="licenses__list-item-name">{item.getName()}</span>
                    <span className="licenses__list-item-description">
                        {description}
                    </span>
                </div>
                {component.controls}
            </div>
        );
    },

    _onRemoveOneItem(itemData, event) {
        event.stopPropagation();

        this._deselectItem(itemData);

        this._removeSubscribers([itemData]);
    },

    _onListItemClick(data, event) {
        event.stopPropagation();

        this._toggleListItem(data);
    },

    _toggleListItem(data) {
        const isSelected = this._isSelectedItem(data);

        return isSelected ? this._deselectItem(data) : this._selectItem(data);
    },

    _selectItem(data) {
        const { selectedItems } = this.state;

        this._updateSelectedItems(selectedItems.concat([data]));
    },

    _deselectItem(data) {
        let { selectedItems } = this.state;
        const { isAllChecked } = this.state;

        selectedItems = selectedItems.filter(item => Number(item.id) !== Number(data.id) || item.type !== data.type);

        if (isAllChecked) {
            this.setState({ isAllChecked: false });
        }

        this._updateSelectedItems(selectedItems);
    },

    _updateSelectedItems(selectedItems) {
        this.setState({ selectedItems });

        if (selectedItems.length === 0) {
            return StatusBarActions.clear();
        }

        const { serviceName } = this.state;
        const isUsers = selectedItems.reduce((result, item) => result && item.type === 'user', true);

        const statusBarData = {
            confirmText: i18n('licenses.unsubscribe_several_item'),
            onConfirm: this._submit,
            onClose: this._deselectAll,
        };

        if (selectedItems.length === 1) {
            const count = selectedItems[0].type === 'user' ?
                selectedItems.length :
                toRecord(selectedItems[0]).get('members_count');

            statusBarData.message = this._getSelectedSubscriptionText(count);

            return StatusBarActions.add(statusBarData);
        }

        if (isUsers) {
            statusBarData.message = this._getSelectedSubscriptionText(selectedItems.length);

            return StatusBarActions.add(statusBarData);
        }

        statusBarData.message = i18n('licenses.subscription_counting');
        StatusBarActions.add(statusBarData);

        LicenseActions.calculate(serviceName, selectedItems)
            .then(response => {
                const subscriptionData = _.get(response, `subscription.pricing.services.${serviceName}`, {});

                if (selectedItems === this.state.selectedItems) {
                    const message = this._getSelectedSubscriptionText(subscriptionData.users_count);

                    StatusBarActions.add(_.extend({}, statusBarData, { message }));
                }
            })
            .catch(() => {
                const message = i18n('licenses.selected_several_element', {
                    n_elements: pluralize(selectedItems.length, i18n('licenses.elements')),
                });

                StatusBarActions.add(_.extend({}, statusBarData, { message }));
            });
    },

    _getSelectedSubscriptionText(count) {
        if (count === 1) {
            return i18n('licenses.selected_one_subscription');
        }

        return i18n('licenses.selected_several_subscriptions', {
            n_subscriptions: pluralize(count, i18n('balance.services.subscriptions')),
        });
    },

    _submit() {
        this._removeSubscribers(this.state.selectedItems);
    },

    _deselectAll() {
        this.setState({
            isAllChecked: false,
        });

        this._updateSelectedItems([]);
    },

    _isSelectedItem(data, selectedItems = this.state.selectedItems) {
        const matches = selectedItems.filter(item => Number(item.id) === Number(data.id) && item.type === data.type);

        return matches.length > 0;
    },

    _removeSubscribers(deletedSubscribers) {
        const { serviceName, subscribers: prevSubscribers } = this.state;
        const draftSubscribers = {
            [serviceName]: prevSubscribers.filter(item => !this._isSelectedItem(item, deletedSubscribers)),
        };

        this.setState({
            isLoading: true,
        });

        return LicenseActions.update(serviceName, { subscribers: draftSubscribers })
            .then(() => {
                this._deselectAll();

                this.setState({
                    isLoading: false,
                });

                notify(i18n('licenses.remove.success'), 'success');
            })
            .catch(() => {
                this.setState({
                    isLoading: false,
                });

                notify(i18n('licenses.remove.error'), 'error');
            });
    },

    _showAddSubscribersPopup() {
        const { serviceName, isContractAvailable, trialStatus } = this.state;

        if (!isContractAvailable && !AuthStore.isPartnerOrganization()) {
            ModalActions.confirm({
                title: i18n('licenses.paid_info_popup.title'),
                message: trialStatus === TRIAL_STATUS.IN_PROGRESS ?
                    i18n('licenses.paid_info_popup.description_for_trial') :
                    i18n('licenses.paid_info_popup.description'),
                confirmButtonText: i18n('licenses.paid_info_popup.confirm_button'),
                onConfirm() {
                    SubscriptionActions.toAgreement(`${serviceName}.licenses`);
                },
            });

            return;
        }

        // показать попап с добавлением
        ModalActions.open({
            component: AddSubscribers,
            props: {
                id: serviceName,
                onCancel: () => ModalActions.close(),
            },
        });
    },

    render() {
        const { usersCount, isAllChecked, serviceName, trialStatus, isReady } = this.state;

        if (!isReady) {
            return (
                <div className="licenses__list">
                    <Loader visible />
                </div>
            );
        }

        const allowsTrackerManagement = PermissionStore.allowsTrackerManagement();
        const component = {};

        if (allowsTrackerManagement) {
            component.checkbox = (
                <Checkbox
                    size="m"
                    theme="normal"
                    checked={isAllChecked}
                    disabled={false}
                    onChange={this._onToggleAll}
                />
            );

            component.controls = (
                <Button
                    text={i18n('licenses.subscribe_now')}
                    onClick={this._showAddSubscribersPopup}
                    size="m"
                    theme="action"
                />
            );
        }

        if (this._isSubscriptionListEmpty()) {
            return (
                <div className="licenses-empty">
                    <div className="licenses-empty__image" />
                    <h3 className="licenses-empty__title">
                        {i18n('licenses.empty_list.title')}
                    </h3>
                    <p className="licenses-empty__description">
                        {i18n(`licenses.empty_list.description.trial_${trialStatus}`)}
                    </p>
                    {component.controls}
                </div>
            );
        }

        let tooltipContent = i18n(`licenses.subscription_tooltip.${serviceName}`, {
            help_url: ConfigStore.getHelpUrl(`ui.help.${serviceName}.licenses`),
        });

        return (
            <div className="licenses__list">
                <div className="licenses__controls">
                    <h3 className="licenses__controls-title">
                        {i18n('licenses.users_with_subscription')}
                    </h3>
                    {component.controls}
                </div>
                <div className="licenses__list-header action">
                    {component.checkbox}
                    <span className="licenses__list-header-text">
                        {pluralize(usersCount, i18n('balance.services.persons'))}
                    </span>
                    <div className="licenses__list-header-tooltip">
                        <Icon type="question" />
                        <Tip theme="light">
                            <div className="licenses__list-header-tooltip-content">
                                <span dangerouslySetInnerHTML={{ __html: tooltipContent }} />
                            </div>
                        </Tip>
                    </div>
                </div>
                {this._renderList()}

                <Loader visible={this.state.isLoading} />
            </div>
        );
    },
});

export default LicensesList;
