import type { FC } from 'react';
import React, { useCallback, useEffect, useMemo } from 'react';
import { useApolloClient } from '@apollo/client';
import { SearchDropdown } from '@theorchard/suite-components';
import { useOrchardLabelByIdQuery } from 'src/data/queries/orchardLabel/orchardLabelById';
import { useOrchardLabels } from 'src/data/queries/orchardLabels/orchardLabels';
import { getPromisedLabelSearch } from 'src/data/queries/orchardLabelSearch/orchardLabelSearch';
import type {
    DropdownOption,
    Label,
    SearchableDropdownOption,
} from 'src/types';

export const CLASSNAME = 'LabelSearchDropdown';

export interface Props {
    disabled?: boolean;
    showAllOption?: boolean;
    onChange: (data?: Label) => void;
    vendorId?: number;
}

export const getOptionName = (label: Label) => `${label.name} - ${label.uuid}`;

const createOption = (label: Label): DropdownOption<Label> => ({
    label: getOptionName(label),
    value: label.uuid,
    data: label,
});

export const SHOW_ALL_LABEL_UUID = 'all';
export const SHOW_ALL_LABEL_NAME = 'Show All Labels';
const allOption = {
    label: SHOW_ALL_LABEL_NAME,
    value: SHOW_ALL_LABEL_UUID,
    data: {
        id: { vendorId: 0, subaccountId: 0 },
        name: SHOW_ALL_LABEL_NAME,
        uuid: SHOW_ALL_LABEL_UUID,
    },
};

const LabelSearchDropdown: FC<Props> = ({
    disabled,
    showAllOption = true,
    onChange,
    vendorId,
}) => {
    const apolloClient = useApolloClient();
    const { data: listData } = useOrchardLabels();
    // our vendors won't have subaccountIds so can just set this to 0.
    const { data: selectedLabel } = useOrchardLabelByIdQuery({
        id: { subaccountId: 0, vendorId },
    });

    const inputChangeCallback = async (searchTerm: string) => {
        const data = await getPromisedLabelSearch(searchTerm, apolloClient);

        return data.map(createOption);
    };

    const labelOptions = useMemo<DropdownOption<Label>[]>(
        () => [...(listData ?? [])].map(createOption),
        [listData]
    );

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

    const handleSingleLabel = useCallback(
        (newValue?: Label) => {
            onChange(newValue);
        },
        [onChange]
    );

    useEffect(() => {
        if (listData?.length === 1 && listData[0].id.vendorId !== vendorId)
            handleSingleLabel(listData[0]);
    }, [vendorId, listData, handleSingleLabel]);

    let selectedOption: DropdownOption<Label> | null = null;
    if (selectedLabel?.name)
        selectedOption = createOption({
            id: {
                vendorId: selectedLabel.id.vendorId,
                subaccountId: 0,
            },
            name: selectedLabel.name,
            uuid: selectedLabel.uuid,
        });

    const formattedOption = (option: DropdownOption<Label>) => (
        <div className={`${CLASSNAME}-option`}>
            <div className={`${CLASSNAME}-option-name`}>
                {option.data?.name}
            </div>
        </div>
    );

    const options: DropdownOption<Label>[] = [
        allOption,
        ...(labelOptions || []),
    ];

    if (!showAllOption) options.shift();

    if (listData?.length === 1) {
        const label: Label = listData[0];
        handleSingleLabel(label);
        return <h3 className="singleItem">{label.name}</h3>;
    }

    return (
        <SearchDropdown
            isClearable={false}
            name="labelSearchDropdown"
            className={CLASSNAME}
            onChange={handleChange}
            onLoadOptions={inputChangeCallback}
            defaultOptions={options}
            value={selectedOption || allOption}
            formatOptionLabel={formattedOption}
            debounceTime={300}
            isDisabled={disabled}
        />
    );
};

export default LabelSearchDropdown;
