import { block } from 'bem-cn';
import React from 'react';
import { Select, Button, Spin } from 'lego-on-react';
import { i18n } from 'i18n2';
import metrika from 'api2/metrika';
import directory from 'api2/directory';
import getOrganization from 'lib2/getOrganization';
import getOrgChangeUrl from 'lib2/getOrgChangeUrl';
import getRetpath from 'lib2/getRetpath';
import isDomainUser from 'lib2/isDomainUser';
import isFeatureEnabled from 'lib2/isFeatureEnabled';
import { OrgStore, ConfigStore, SessionStore } from 'lib2/stores';
import ServiceIcon from 'components/Icon/ServiceIcon';
import { WidgetIFrame } from 'components2/WidgetIFrame';

import './index.css';

const b = block('context');

function getCloudOrgUrl(cloudOrgId) {
    const url = new URL(ConfigStore.get('ui.cloud.org'));

    if (cloudOrgId) {
        url.searchParams.set('orgId', cloudOrgId);
    }

    return url.href;
}

export default class Context extends WidgetIFrame {
    featuresCache = {
        [SessionStore.get('context.org_id')]: isFeatureEnabled('use_cloud_proxy'),
    }

    constructor(props) {
        super(props);

        this.POST_MSG_TYPE_PREFIX = '@connect/context/';

        const { searchParams } = new URL(window.location.href);
        const orgId = searchParams.get('org_id');

        this.state = {
            serviceSlug: searchParams.get('source') || 'connect',
            retpath: searchParams.get('retpath'),
        };

        if (orgId && OrgStore.get(orgId)) {
            Object.assign(this.state, {
                orgId,
                hasCloudProxyFeature: this.featuresCache[orgId],
            });
        }

        this._onChange = this._onChange.bind(this);
        this._onAcceptButtonClick = this._onAcceptButtonClick.bind(this);
        this._onNewOrgClick = this._onNewOrgClick.bind(this);
    }

    _update() {
        const nextOrgId = this.state.orgId || getOrganization().id;

        this.setState({
            nextOrgId,
            hasCloudProxyFeature: this.featuresCache[nextOrgId],
        });
    }

    componentDidMount() {
        this._update();
        this._orgStoreListener = OrgStore.onChange(this._update);

        if (this.props.isIframe) {
            this.initFrame();
        }
    }

    componentWillUnmount() {
        this._unmounted = true;
        this._orgStoreListener.remove();

        this.destructFrame();
    }

    _onChange([value]) {
        this.setState({
            nextOrgId: value,
        });

        if (this.featuresCache[value] === undefined) {
            this.setState({ isFeaturesLoading: true, hasCloudProxyFeature: false });

            directory
                .send('GET', `/organizations/${value}/features/`)
                .then(({ ok, body }) => {
                    if (!ok) return; // ignore

                    this.featuresCache[value] = body.use_cloud_proxy.enabled;

                    this.setState({ hasCloudProxyFeature: this.featuresCache[value] });
                })
                .catch(() => ({})) // ignore
                .finally(() => this.setState({ isFeaturesLoading: false }));
        }

        this.setState({ hasCloudProxyFeature: this.featuresCache[value] });
    }

    _onAcceptButtonClick() {
        const { nextOrgId, serviceSlug, retpath } = this.state;

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

        metrika.send(
            'Явная смена контекста',
            serviceSlug
        );

        if (this.props.isIframe) {
            this.postMessage('accept', {
                orgId: nextOrgId,
                url: getOrgChangeUrl(nextOrgId, retpath),
            });
        } else {
            window.location.href = getOrgChangeUrl(nextOrgId, getRetpath('/portal/home'));
        }
    }

    _onNewOrgClick() {
        if (this.props.isIframe) {
            this.postMessage('create');
        } else {
            window.location.assign(this._buildRegistrationUrl());
        }
    }

    _buildRegistrationUrl() {
        if (this._registrationUrl) return this._registrationUrl;

        const { serviceSlug, retpath } = this.state;
        const { origin } = window.location;
        const url = new URL('/portal/registration', origin);

        url.searchParams.set('action', 'context');
        url.searchParams.set('source', serviceSlug);
        retpath && url.searchParams.set('retpath', retpath);

        this._registrationUrl = url.href;

        return this._registrationUrl;
    }

    _getOrgs() {
        return Object.values(OrgStore.getState());
    }

    _hasOrgs() {
        return this._getOrgs().length !== 0;
    }

    _renderCreateButton() {
        const hasOrg = this._hasOrgs();

        return (
            <Button
                cls={b('create')}
                size="m"
                theme={hasOrg ? 'normal' : 'action'}
                text={i18n(`context.create.${hasOrg ? 'new' : 'first'}`)}
                disabled={this.state.busy}
                onClick={this._onNewOrgClick}
            />
        );
    }

    _renderOrgsSelect() {
        const { nextOrgId, busy, isFeaturesLoading } = this.state;
        const orgs = this._getOrgs();

        return (
            <div className={b('select-wrap')}>
                <Select
                    cls={b('select')}
                    theme="normal"
                    type="radio"
                    size="m"
                    val={nextOrgId}
                    maxHeight={140}
                    onChange={this._onChange}
                    button={{ id: nextOrgId }}
                    disabled={busy}
                >
                    {orgs.map(({ id, name }) => (
                        <Select.Item val={id} key={id}>
                            {name}
                        </Select.Item>
                    ))}
                </Select>
                {isFeaturesLoading && (
                    <Spin
                        size="xs"
                        progress
                        view="default"
                        tone="default"
                        cls={b('select-spin')}
                    />
                )}
            </div>
        );
    }

    _renderSelectView() {
        const { orgId, busy, isFeaturesLoading, hasCloudProxyFeature } = this.state;
        const canCreateOrg = !isDomainUser();

        return (
            <div className={b('content', { view: 'select' })}>
                <h1 className={b('title')}>
                    {i18n(`context.no_org_id.${canCreateOrg ? 'title2' : 'title'}`)}
                </h1>
                <p className={b('text')}>
                    {i18n('context.no_org_id.text')}
                </p>
                {this._renderOrgsSelect()}
                {hasCloudProxyFeature && (
                    <p className={b('text')}>
                        {i18n('context.cloud_org.text')}
                    </p>
                )}
                <div className={b('actions')}>
                    {hasCloudProxyFeature ? (
                        <Button
                            cls={b('accept')}
                            theme="action"
                            size="m"
                            text={i18n('context.go_to_cloud')}
                            type="link"
                            url={getCloudOrgUrl(OrgStore.get([orgId, 'cloud_org_id']))}
                            disabled={isFeaturesLoading}
                        />
                    ) : (
                        <Button
                            cls={b('accept')}
                            theme="action"
                            size="m"
                            text={i18n('context.accept')}
                            onClick={this._onAcceptButtonClick}
                            progress={busy}
                            disabled={isFeaturesLoading}
                        />
                    )}
                    {canCreateOrg && this._renderCreateButton()}
                </div>
            </div>
        );
    }

    _renderContent() {
        const { orgId, busy } = this.state;

        if (this.featuresCache[orgId]) {
            return this._renderSelectView();
        }

        if (orgId) {
            return (
                <div className={b('content', { view: 'accept' })}>
                    <h1 className={b('title')}>
                        {i18n('context.org_id.title', {
                            org_name: OrgStore.get([orgId, 'name']),
                        })}
                    </h1>
                    <p className={b('text')}>
                        {i18n('context.org_id.text')}
                    </p>
                    <div className={b('actions')}>
                        <Button
                            cls={b('accept')}
                            theme="action"
                            size="m"
                            text={i18n('context.accept')}
                            onClick={this._onAcceptButtonClick}
                            progress={busy}
                        />
                    </div>
                </div>
            );
        }

        if (!this._hasOrgs()) {
            return (
                <div className={b('content', { view: 'create' })}>
                    <h1 className={b('title')}>
                        {i18n('context.create_org.title')}
                    </h1>
                    <p className={b('text')}>
                        {i18n('context.create_org.text')}
                    </p>
                    <div className={b('actions')}>
                        {this._renderCreateButton()}
                    </div>
                </div>
            );
        }

        return this._renderSelectView();
    }

    render() {
        const { isIframe } = this.props;
        const { serviceSlug, widgetStyle } = this.state;

        return (
            <React.Fragment>
                {widgetStyle && <style className={b('widget-style')}>{widgetStyle}</style>}
                <div
                    className={b({ widget: isIframe })}
                    ref={this.initRef}
                >
                    <div className={b('container')}>
                        <ServiceIcon
                            cls={b('icon')}
                            serviceSlug={serviceSlug}
                        />
                        {this._renderContent()}
                    </div>
                </div>
            </React.Fragment>
        );
    }
}
