import type { FC } from 'react';
import React, { useCallback, useMemo } from 'react';
import { Select } from '@theorchard/suite-components';
import { BrandIcon } from '@theorchard/suite-icons';
import { BRAND_ORCHARD, SIZE_16 } from 'src/constants';
import { useAccountsQuery, useAccountSearchQuery } from 'src/data/queries';
import type { Account } from 'src/data/types';
import type {
    AccountDropdownGroupedOption,
    AccountSearchDropdownProps,
    DropdownOptionWithIcon,
    SearchableDropdownOption,
} from 'src/types';

export const CLASSNAME = 'AccountSearchDropdown';

const createLabel = (account: Account): string =>
    `${account.name} • ${account.id}`;

const createOption = (account: Account): DropdownOptionWithIcon<Account> => ({
    label: createLabel(account),
    value: account.id.toString(),
    icon: <BrandIcon brand={BRAND_ORCHARD} size={SIZE_16} />,
    data: account,
});

const AccountSearchDropdown: FC<AccountSearchDropdownProps> = props => {
    const {
        disabled,
        menuWidth,
        onChange,
        placeholder,
        testId,
        selectedAccount,
    } = props;
    const { data: accountsData } = useAccountsQuery();
    const [executeSearch] = useAccountSearchQuery();

    const handleAccountGroupedOptions = useCallback(
        (
            accountsOptionsData: Account[]
        ): AccountDropdownGroupedOption<Account>[] => {
            return [
                {
                    label: 'Accounts',
                    options: accountsOptionsData.map(createOption),
                },
            ];
        },
        []
    );

    const accountGroupedOptions = useMemo<
        AccountDropdownGroupedOption<Account>[]
    >(
        () =>
            accountsData?.length
                ? handleAccountGroupedOptions(accountsData)
                : [],
        [accountsData, handleAccountGroupedOptions]
    );

    const onChangeHandler = useCallback(
        (newValue?: SearchableDropdownOption<Account>) => {
            onChange(newValue?.data);
        },
        [onChange]
    );

    const onLoadOptionsHandler = useCallback(
        async (term?: string) => {
            if (term) {
                const searchAccountsData = await executeSearch({
                    variables: { term },
                });
                return {
                    data: searchAccountsData?.length
                        ? handleAccountGroupedOptions(searchAccountsData)
                        : [],
                };
            }
            return {};
        },
        [executeSearch, handleAccountGroupedOptions]
    );

    return (
        <Select
            name="accountSearchDropdown"
            className={CLASSNAME}
            disabled={disabled}
            onChange={onChangeHandler}
            onLoadOptions={onLoadOptionsHandler}
            placeholder={placeholder}
            testId={testId}
            options={accountGroupedOptions}
            menuWidth={menuWidth}
            selectedValue={
                selectedAccount ? createLabel(selectedAccount) : undefined
            }
        />
    );
};

export default AccountSearchDropdown;
