import type { FC } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import { Dropdown, TruncatedText } from '@theorchard/suite-components';
import {
    useGetOwnershipNrParticipants,
    useOwnershipNrParticipantByIdQuery,
    useOwnershipNrParticipantSearchQuery,
} from 'src/data/queries';
import { recordPrimaryArtistFilter } from 'src/utils/segment/filterEvents';
import type { InputChangeCallback } from 'src/components/utils';
import type {
    ParticipantNodeRelationship,
    OwnershipParticipantType,
} from 'src/data/globalTypes';
import type { OwnershipNrParticipant } from 'src/data/types';
import type { DropdownOption, SearchableDropdownOption } from 'src/types';
import type { SetParamsCallback } from 'src/utils/route';

export const CLASSNAME = 'ParticipantSearchDropdown';

export interface Props {
    disabled?: boolean;
    onChange: SetParamsCallback;
    participantId?: string;
    placeholder: string;
    relationshipTo?: ParticipantNodeRelationship;
    participantType?: OwnershipParticipantType;
}

const createOption = (
    participant: OwnershipNrParticipant
): DropdownOption<OwnershipNrParticipant> => ({
    label: participant.name,
    value: participant.id,
    data: participant,
});

const ParticipantSearchDropdown: FC<Props> = props => {
    const {
        onChange,
        disabled,
        participantId,
        placeholder,
        relationshipTo,
        participantType,
    } = props;
    const [inputValue, setInputValue] = useState('');
    const [term, setTerm] = useState<string>();
    const [executeSearch, { data: searchData, loading }] =
        useOwnershipNrParticipantSearchQuery();
    const { data: listData } = useGetOwnershipNrParticipants({
        limit: 100,
        relationshipTo,
        participantType,
    });
    const dataSource: OwnershipNrParticipant[] | null | undefined = term
        ? searchData
        : listData?.participants;
    const { data: participantData } = useOwnershipNrParticipantByIdQuery({
        id: participantId || '',
    });

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

    const participantOptions = useMemo<
        DropdownOption<OwnershipNrParticipant>[]
    >(() => {
        const options = [...(dataSource ?? [])].map(createOption);
        return options;
    }, [dataSource]);

    const handleChange = useCallback(
        (newValue?: SearchableDropdownOption<OwnershipNrParticipant>) => {
            onChange({ participant: newValue?.data?.id });
            recordPrimaryArtistFilter(newValue?.data?.name);
        },
        [onChange]
    );

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

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

    const isLoading = loading && !searchData;

    return (
        <Dropdown.Custom
            type="Select"
            name="participantSearchDropdown"
            inputValue={inputValue}
            className={CLASSNAME}
            onChange={handleChange}
            isSearchable
            onInputChange={handleInputChange}
            options={participantOptions}
            isDisabled={disabled}
            value={selectedOption}
            formatOptionLabel={formattedOption}
            isLoading={isLoading}
            placeholder={placeholder}
            isClearable
            filterOption={() => true}
        />
    );
};

export default ParticipantSearchDropdown;
