import React, { useCallback } from 'react';
import { Field, SearchDropdown } from '@theorchard/suite-components';
import { formatMessage } from '@theorchard/suite-frontend';
import { usePublishingPublishers } from 'src/data/queries';
import type { PublishingPublishersFilterLabelInput } from 'src/data/queries';
import type {
    DropdownOption,
    Label,
    Publisher,
    SearchableDropdownOption,
} from 'src/types';

interface ExcludeFilter {
    publisherIds: string[];
}

interface Props {
    label: Label | null;
    publisher?: Publisher;
    onChange: (value: Publisher | undefined) => void;
    withAddNewOption?: boolean;
    excludeFilter?: ExcludeFilter;
}

const generateOptions = (
    publisherList: Publisher[] = [],
    withAddNewOption: boolean,
    excludeFilter?: ExcludeFilter
) => {
    const publishers = publisherList
        .filter(p => !excludeFilter?.publisherIds.includes(p.id))
        .map(p => ({ label: p.name || '', value: p.id, data: p }));

    if (!withAddNewOption) return publishers;

    return [
        {
            label: '+ Add New Publisher',
            value: '',
            data: undefined,
        },
        ...publishers,
    ];
};

const generateOption = (p: Publisher): DropdownOption<Publisher> => ({
    label: p.name || '',
    value: p.id,
    data: p,
});

const PublisherAsyncSelect: React.FC<Props> = ({
    label,
    publisher,
    onChange,
    withAddNewOption = true,
    excludeFilter,
}) => {
    const filter: PublishingPublishersFilterLabelInput = {
        label,
    };

    const { data, refetch } = usePublishingPublishers(filter, 1);

    const loadPublishingPublishersOptions = async (
        nameSearch: string
    ): Promise<DropdownOption<Publisher>[]> => {
        const opts = nameSearch ? { nameSearch, label } : { label: null };

        const { data: refetchData } = await refetch(opts);

        return generateOptions(
            refetchData?.publishingPublishers?.publishers as Publisher[],
            withAddNewOption,
            excludeFilter
        );
    };

    const onPublisherSelect = useCallback(
        (value: SearchableDropdownOption<Publisher>) => {
            onChange(value?.data);
        },
        [onChange]
    );

    const props = {
        isClearable: false,
        defaultOptions: generateOptions(
            data.publishers,
            withAddNewOption,
            excludeFilter
        ),
        onLoadOptions: loadPublishingPublishersOptions,
        onChange: onPublisherSelect,
        formatOptionLabel: (p: DropdownOption<Publisher>) => p.label,
        placeholder: formatMessage('songWriterManager.publisherPlaceholder'),
        defaultValue: publisher && generateOption(publisher),
    };

    if (!data) return null;

    return (
        <Field
            controlId="publishingCompanySelect"
            labelText={formatMessage('generic.publishingCompanySelect')}
        >
            <SearchDropdown {...props} />
        </Field>
    );
};

export default PublisherAsyncSelect;
