import React from 'react';
import { NavDropdown, ChevronIcon } from '@orchard/frontend-react-components';
import { useAppConfig } from '@theorchard/suite-frontend';
import { Link } from 'react-router-dom';
import {
    PROFILE_LINK,
    SWITCH_USER_LINK,
    getAccountSwitchLink,
    LOGOFF_LINK,
} from 'src/constants';
import { FEATURE_WORKSTATION_IMPERSONATE_SWITCH } from 'src/constants/permissions';
import IdentityContext from 'src/context';
import { formatMessage } from 'src/utils';
import { getSwitchKeySessId } from 'src/utils/auth';
import type { LinkedAccount, WorkstationConfig } from 'src/types';

const CLASS_NAME = 'LinkedAccountsDropdown';
// Client-side pagination for now. Consider react-window and/or paginated
// backend queries for linked_accounts when the API supports it.
const ACCOUNTS_PAGE_SIZE = 50;

interface LinkedMenuItemProps {
    accountName?: string;
    accountId?: number;
    href?: string;
    checkmark?: boolean;
    isSubaccount?: boolean;
    vendorName?: string;
}

export const LinkedMenuItem: React.FC<LinkedMenuItemProps> = ({
    accountName,
    accountId,
    href,
    checkmark,
    isSubaccount,
    vendorName,
}) => (
    <NavDropdown.Item className={`${CLASS_NAME}-linked-menu-item`} href={href}>
        <div className={`${CLASS_NAME}-linked-menu-item-row`}>
            <div className={`${CLASS_NAME}-account-title`}>
                {isSubaccount && (
                    <div className={`${CLASS_NAME}-vendor-name`}>
                        {vendorName}
                    </div>
                )}
                <div className={`${CLASS_NAME}-account-name`}>
                    <div className={`${CLASS_NAME}-vendor-or-subaccount`}>
                        {accountName}
                    </div>
                    &nbsp;:&nbsp;
                    <div className={`${CLASS_NAME}-vendor-or-subaccount-id`}>
                        {accountId}
                    </div>
                </div>
            </div>
            {checkmark && <div className={`${CLASS_NAME}-checkmark`} />}
        </div>
    </NavDropdown.Item>
);

interface LinkedAccountsDropdownProps {
    className: string;
    linkedAccounts?: LinkedAccount[];
    title: React.ReactNode;
    accountName?: string;
    accountId?: number;
    isSubaccount?: boolean;
    vendorName?: string;
    isEmbedOnPhp?: boolean;
    showAdminLink?: boolean;
}

const LinkedAccountsDropdown: React.FC<LinkedAccountsDropdownProps> = ({
    className,
    linkedAccounts = [],
    title,
    accountName,
    accountId,
    isSubaccount,
    vendorName,
    isEmbedOnPhp,
}) => {
    const config = useAppConfig() as WorkstationConfig;
    const { identity } = React.useContext(IdentityContext);
    const isImpersonateSwitchEnabled = identity.hasFeatureFlag(
        FEATURE_WORKSTATION_IMPERSONATE_SWITCH
    );
    const [visibleCount, setVisibleCount] = React.useState(ACCOUNTS_PAGE_SIZE);
    const [loadingMore, setLoadingMore] = React.useState(false);

    const totalAccounts = linkedAccounts.length;
    const visibleLinkedAccounts = linkedAccounts.slice(0, visibleCount);
    const hasMore = visibleCount < totalAccounts;
    const remaining = totalAccounts - visibleCount;
    const showMoreText = formatMessage('header.dropdown.showMore', {
        remaining,
    });
    const loadingMoreText = formatMessage(
        'header.dropdown.loadingMoreAccounts'
    );

    const loadMore = (e: React.MouseEvent | React.KeyboardEvent) => {
        e.preventDefault();
        e.stopPropagation();
        setLoadingMore(true);
        // rAF lets browser paint the spinner, setTimeout ensures it's visible
        requestAnimationFrame(() => {
            setTimeout(() => {
                setVisibleCount(prev => prev + ACCOUNTS_PAGE_SIZE);
                setLoadingMore(false);
            }, 0);
        });
    };

    return (
        <NavDropdown title={title} id="header-dropdown" className={className}>
            {visibleLinkedAccounts.length > 0 && (
                <LinkedMenuItem
                    accountName={accountName}
                    accountId={accountId}
                    isSubaccount={isSubaccount}
                    vendorName={vendorName}
                    href={PROFILE_LINK}
                    checkmark
                />
            )}
            {visibleLinkedAccounts.length > 0 &&
                visibleLinkedAccounts.map(
                    ({
                        vcId,
                        vendorId,
                        company,
                        subaccountId,
                        subaccountName,
                    }) => (
                        <LinkedMenuItem
                            key={`account-${vcId}`}
                            accountId={subaccountId || vendorId}
                            accountName={subaccountName || company}
                            isSubaccount={Boolean(subaccountId)}
                            vendorName={company}
                            href={
                                isImpersonateSwitchEnabled
                                    ? getAccountSwitchLink(vcId)
                                    : SWITCH_USER_LINK(
                                          vcId,
                                          getSwitchKeySessId(
                                              config,
                                              identity
                                          ) ?? undefined
                                      )
                            }
                        />
                    )
                )}
            {hasMore && (
                <div
                    role="button"
                    tabIndex={0}
                    aria-label={`${showMoreText}...`}
                    className={`${CLASS_NAME}-load-more dropdown-item`}
                    onClick={loadingMore ? undefined : loadMore}
                    onKeyDown={e => {
                        if (e.key === 'Enter' && !loadingMore) loadMore(e);
                    }}
                >
                    {!loadingMore && (
                        <span className={`${CLASS_NAME}-load-more-icon`}>
                            <ChevronIcon />
                        </span>
                    )}
                    <span>{loadingMore ? loadingMoreText : showMoreText}</span>
                </div>
            )}
            <NavDropdown.Item href={PROFILE_LINK}>
                {formatMessage('header.dropdown.myAccount')}
            </NavDropdown.Item>

            {isEmbedOnPhp ? (
                <NavDropdown.Item
                    id="NavDropdown-logout"
                    onClick={() => {
                        window.location.href = LOGOFF_LINK;
                    }}
                >
                    {formatMessage('header.dropdown.logOut')}
                </NavDropdown.Item>
            ) : (
                <NavDropdown.Item
                    id="NavDropdown-logout"
                    as={Link}
                    to={LOGOFF_LINK}
                >
                    {formatMessage('header.dropdown.logOut')}
                </NavDropdown.Item>
            )}
        </NavDropdown>
    );
};

export default LinkedAccountsDropdown;
