import React from 'react';
import clsx from 'clsx';
import { Link } from 'react-router-dom';
import { FormattedMessage as Message } from 'react-intl';

import { connect } from 'app/functions';
import * as loader from 'app/services/loader';
import { SKIN_DARK, COLOR_WHITE, Skin } from 'app/components/ui';
import { Button } from 'app/components/ui/form';
import { authenticate, revoke } from 'app/components/accounts/actions';
import { getActiveAccount, Account } from 'app/components/accounts/reducer';
import { State as AccountState } from 'app/components/accounts/reducer';

import styles from './accountSwitcher.scss';

interface Props {
    switchAccount: (account: Account) => Promise<Account>;
    removeAccount: (account: Account) => Promise<void>;
    // called after each action performed
    onAfterAction: () => void;
    // called after switching an account. The active account will be passed as arg
    onSwitch: (account: Account) => void;
    accounts: AccountState;
    skin: Skin;
    // whether active account should be expanded and shown on the top
    highlightActiveAccount: boolean;
    // whether to show logout icon near each account
    allowLogout: boolean;
    // whether to show add account button
    allowAdd: boolean;
}

export class AccountSwitcher extends React.Component<Props> {
    static defaultProps: Partial<Props> = {
        skin: SKIN_DARK,
        highlightActiveAccount: true,
        allowLogout: true,
        allowAdd: true,
        onAfterAction() {},
        onSwitch() {},
    };

    render() {
        const { accounts, skin, allowAdd, allowLogout, highlightActiveAccount } = this.props;
        const activeAccount = getActiveAccount({ accounts });

        if (!activeAccount) {
            return null;
        }

        let { available } = accounts;

        if (highlightActiveAccount) {
            available = available.filter((account) => account.id !== activeAccount.id);
        }

        return (
            <div
                className={clsx(styles.accountSwitcher, styles[`${skin}AccountSwitcher`])}
                data-testid="account-switcher"
            >
                {highlightActiveAccount && (
                    <div className={styles.item} data-testid="active-account">
                        <div className={clsx(styles.accountIcon, styles.activeAccountIcon, styles.accountIcon1)} />
                        <div className={styles.activeAccountInfo}>
                            <div className={styles.activeAccountUsername}>{activeAccount.username}</div>
                            <div className={clsx(styles.accountEmail, styles.activeAccountEmail)}>
                                {activeAccount.email}
                            </div>
                            <div className={styles.links}>
                                <div className={styles.link}>
                                    <a href={`http://ely.by/u${activeAccount.id}`} target="_blank">
                                        <Message key="goToEly" defaultMessage="Go to Ely.by profile" />
                                    </a>
                                </div>
                                <div className={styles.link}>
                                    <a
                                        className={styles.link}
                                        data-testid="logout-account"
                                        onClick={this.onRemove(activeAccount)}
                                        href="#"
                                    >
                                        <Message key="logout" defaultMessage="Log out" />
                                    </a>
                                </div>
                            </div>
                        </div>
                    </div>
                )}

                {available.map((account, index) => (
                    <div
                        className={clsx(styles.item, styles.accountSwitchItem)}
                        key={account.id}
                        data-e2e-account-id={account.id}
                        onClick={this.onSwitch(account)}
                    >
                        <div
                            className={clsx(
                                styles.accountIcon,
                                styles[`accountIcon${(index % 7) + (highlightActiveAccount ? 2 : 1)}`],
                            )}
                        />

                        {allowLogout ? (
                            <div
                                className={styles.logoutIcon}
                                data-testid="logout-account"
                                onClick={this.onRemove(account)}
                            />
                        ) : (
                            <div className={styles.nextIcon} />
                        )}

                        <div className={styles.accountInfo}>
                            <div className={styles.accountUsername}>{account.username}</div>
                            <div className={styles.accountEmail}>{account.email}</div>
                        </div>
                    </div>
                ))}
                {allowAdd ? (
                    <Link to="/login" onClick={this.props.onAfterAction}>
                        <Button color={COLOR_WHITE} data-testid="add-account" block small className={styles.addAccount}>
                            <span>
                                <div className={styles.addIcon} />
                                <Message key="addAccount" defaultMessage="Add account" />
                            </span>
                        </Button>
                    </Link>
                ) : null}
            </div>
        );
    }

    onSwitch = (account: Account) => (event: React.MouseEvent<any>) => {
        event.preventDefault();

        loader.show();

        this.props
            .switchAccount(account)
            .finally(() => this.props.onAfterAction())
            .then(() => this.props.onSwitch(account))
            // we won't sent any logs to sentry, because an error should be already
            // handled by external logic
            .catch((error) => console.warn('Error switching account', { error }))
            .finally(() => loader.hide());
    };

    onRemove = (account: Account) => (event: React.MouseEvent<any>) => {
        event.preventDefault();
        event.stopPropagation();

        this.props.removeAccount(account).then(() => this.props.onAfterAction());
    };
}

export default connect(
    ({ accounts }) => ({
        accounts,
    }),
    {
        switchAccount: authenticate,
        removeAccount: revoke,
    },
)(AccountSwitcher);
