import type { FC } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import { Dropdown, TruncatedText } from '@theorchard/suite-components';
import {
    useAccountSearchQuery,
    useAccountByIdQuery,
    useAccountsQuery,
} from 'src/data/queries';
import { recordAccountFilter } from 'src/utils/segment/filterEvents';
import type { InputChangeCallback } from '../utils';
import type { Account } from 'src/data/types';
import type { DropdownOption, SearchableDropdownOption } from 'src/types';

export const CLASSNAME = 'AccountSearchDropdown';

export interface Props {
    disabled?: boolean;
    onChange: (data?: Account) => void;
    accountId?: number;
    placeholder: string;
    formatOptionLabel?: (option: DropdownOption<Account>) => JSX.Element;
}

export const getOptionName = (account: Account) => `${account.name}`;

const createOption = (account: Account): DropdownOption<Account> => ({
    label: getOptionName(account),
    value: `${account.id}`,
    data: account,
});

const AccountSearchDropdown: FC<Props> = props => {
    const [inputValue, setInputValue] = useState('');
    const { onChange, disabled, accountId, placeholder, formatOptionLabel } =
        props;
    const [term, setTerm] = useState<string>();
    const [executeSearch, { data: searchData, loading }] =
        useAccountSearchQuery();
    const { data: listData } = useAccountsQuery();
    const dataSource: Account[] | undefined = term ? searchData : listData;
    // our vendors won't have subaccountIds so can just set this to 0.
    const variables = { id: { subaccountId: 0, vendorId: accountId } };
    const { data: accountData } = useAccountByIdQuery(variables);

    const handleInputChange: InputChangeCallback = (searchTerm, { action }) => {
        setTerm(searchTerm);
        if (action !== 'menu-close')
            executeSearch({ variables: { term: searchTerm } });
        if (action !== 'input-blur' && action !== 'menu-close')
            setInputValue(searchTerm);
    };

    const accountOptions = useMemo<DropdownOption<Account>[]>(
        () => [...(dataSource ?? [])].map(createOption),
        [dataSource]
    );

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

    let selectedOption: DropdownOption<Account> | null = null;
    if (accountData?.name) selectedOption = createOption(accountData);

    const formattedOption = (option: DropdownOption<Account>) => (
        <div className={`${CLASSNAME}-option`}>
            <div className={`${CLASSNAME}-option-name`}>
                <TruncatedText text={option.data?.name ?? ''} />
            </div>
            <div className={`${CLASSNAME}-option-id`}>
                <TruncatedText text={option.data?.id.toString() ?? '-'} />
            </div>
        </div>
    );

    const optionsWithLabel = [
        {
            label: `${$t('ownershipRights.accountSearchDropdown.accountName')}`,
            options: accountOptions,
        },
    ];

    const CustomGroupHeading = () => (
        <>
            <span className={`${CLASSNAME}-account-name`}>
                {$t('ownershipRights.accountSearchDropdown.accountName')}
            </span>
        </>
    );

    const isLoading = loading && !searchData;

    return (
        <Dropdown.Custom
            name="accountSearchDropdown"
            inputValue={inputValue}
            className={CLASSNAME}
            onChange={handleChange}
            onInputChange={handleInputChange}
            options={optionsWithLabel}
            isDisabled={disabled}
            value={selectedOption}
            formatOptionLabel={formatOptionLabel || formattedOption}
            isLoading={isLoading}
            placeholder={placeholder}
            isClearable
            components={{ GroupHeading: CustomGroupHeading }}
            type="Select"
        />
    );
};

export default AccountSearchDropdown;
