import type { FC } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Select } from '@theorchard/suite-components';
import {
    NrContributionSearchOrderByField,
    OrderDir,
} from 'src/data/globalTypes';
import {
    useGetAllNrContributors,
    useNrContributorSearchQuery,
    useNrContributorByIdQuery,
    useGetNrContributorsByNrSr,
} from 'src/data/queries';
import type { Contributor } from 'src/data/types';
import type { SearchableDropdownOption } from 'src/types';

export const CLASSNAME = 'ContributorSearchDropdown';
export const TEST_ID = 'Select_contributorSearchDropdown';

interface OptionValue {
    value: string;
    label: string;
    data: Contributor;
    subtitle?: string;
}

export interface Props {
    disabled?: boolean;
    onChange: (data?: Contributor) => void;
    contributorId?: string;
    placeholder: string;
    soundRecordingId?: string;
    displayUuid?: boolean;
}

const mapLabelToOption = (
    contributor: Contributor,
    displayUuid?: boolean
): OptionValue => ({
    value: contributor.id,
    label: contributor.name,
    data: contributor,
    subtitle: displayUuid ? contributor.id.toString() : '',
});

const ContributorSearchDropdown: FC<Props> = props => {
    const {
        onChange,
        disabled,
        contributorId,
        placeholder,
        soundRecordingId,
        displayUuid,
    } = props;
    const [term, setTerm] = useState<string>();
    const [executeSearch, { data: searchData }] = useNrContributorSearchQuery();

    const { data: contribByNrSrData } = useGetNrContributorsByNrSr({
        filters: { soundRecordingId },
        limit: 50,
        offset: 0,
        orderBy: NrContributionSearchOrderByField.CONTRIBUTOR_RELATIONSHIP_NAME,
        orderDir: OrderDir.ASC,
    });
    const { data } = useGetAllNrContributors(
        { limit: 100 },
        !!soundRecordingId
    );

    const listData = soundRecordingId ? contribByNrSrData : data?.contributors;

    const dataSource: Contributor[] | null | undefined = term
        ? searchData
        : listData;
    const { data: contributorData } = useNrContributorByIdQuery({
        id: contributorId || '',
    });

    const onLoadOptionsHandler = async (searchTerm?: string) => {
        if (searchTerm) {
            setTerm(searchTerm);
            const data = await executeSearch({
                variables: { term: searchTerm },
            });
            const options = data?.map(item =>
                mapLabelToOption(item, displayUuid)
            );
            return {
                data: options,
            };
        }
        return {};
    };

    const contributorOptions = useMemo(
        () =>
            [...(dataSource ?? [])].map(item =>
                mapLabelToOption(item, displayUuid)
            ),
        [dataSource, displayUuid]
    );

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

    /*
        This useEffect is used for the purpose of the first landing on delivery tab,
        to have contributor in params for querying.
    */
    useEffect(() => {
        if (soundRecordingId && !contributorId)
            handleChange(contributorOptions[0]);
    }, [soundRecordingId, contributorId, handleChange, contributorOptions]);

    let selectedOption = null;
    if (contributorData?.name)
        selectedOption = mapLabelToOption(contributorData);

    return (
        <Select
            name="contributorSearchDropdown"
            className={CLASSNAME}
            placeholder={selectedOption ? '' : placeholder}
            options={contributorOptions}
            onChange={handleChange}
            onLoadOptions={onLoadOptionsHandler}
            disabled={disabled}
            selectedValue={selectedOption ? selectedOption : undefined}
            hideClearButton={!!soundRecordingId}
            testId={TEST_ID}
            compact
        />
    );
};

export default ContributorSearchDropdown;
