import React, { useState, useEffect } from 'react';
import { isEmpty } from 'lodash-es';
import { useContractTermsByAccount } from 'src/apollo/queries/contract-term';
import {
    useTrackSearch,
    useTrackByIsrc,
} from 'src/apollo/queries/track-search';
import SearchableSelectList from 'src/components/shared/searchable-select-list';
import { existingContractAttachments } from 'src/utils/contract';
import type { GetTracksByLabelIdQuery } from 'src/apollo/queries/track-search/__generated__/get-tracks-by-label-id';

type GlobalSoundRecordingItem =
    GetTracksByLabelIdQuery['globalSoundRecordingSearchES']['items'][0];

const SEARCH_PLACEHOLDER = 'Search for track(s)';

export interface TrackSearchableSelectPropTypes {
    accountId: string;
    contractTermId: string;
    onChange: (params: any) => void;
    selectedTrackExceptionIsrcs: any;
    tracksIsrcs: any;
    labelIds: any;
    setErrors: any;
}

const TrackSearchableSelect: React.FC<TrackSearchableSelectPropTypes> = ({
    accountId,
    contractTermId,
    onChange,
    selectedTrackExceptionIsrcs,
    tracksIsrcs,
    labelIds,
    setErrors,
}) => {
    const selectName = 'trackIsrcs';
    const [searchTerm, setSearchTerm] = useState('');
    const [searchResults, setSearchResults] = useState<
        { label: string; value: string }[]
    >([]);
    const { data: contractTerms, getContractsTerms } =
        useContractTermsByAccount();
    const [tracks, setTracks] = useState<any>([]);
    const { data: trackData, getTrackByIsrc } = useTrackByIsrc();
    const [selectedTracksIsrcs, setSelectedTracksIsrcs] = useState([]);
    const [selectedTracks, setSelectedTracks] = useState([]);
    const [areTracksLoaded, setAreTracksLoaded] = useState(false);
    const getPromisedTrackSearch = useTrackSearch();

    const performSearch = async (term: string) => {
        const trimmedTerm = term.trim().replace('\\', '');
        if (trimmedTerm) {
            setSearchTerm(trimmedTerm);
            const data = await getPromisedTrackSearch(
                trimmedTerm,
                labelIds,
                100,
                0
            );
            const searchResults = data?.map(
                (row: GlobalSoundRecordingItem) => ({
                    label: `${row.item.name}-${row.item.isrc}`,
                    value: row.item.isrc,
                })
            );
            setSearchResults(searchResults);
            return searchResults;
        }
    };

    const onBlur = () => {
        setErrors([]);
        if (!isEmpty(tracks)) {
            const tracksIsrc: any = [];
            tracks.forEach((track: any) => {
                tracksIsrc.push(track.value);
            });
            const tracksDifference = tracksIsrc.filter(
                (x: any) => !selectedTrackExceptionIsrcs.includes(x)
            );
            if (!isEmpty(tracksDifference)) {
                setSelectedTracks(tracksDifference);
                getContractsTerms(accountId, tracksDifference, 'track');
            }
        }
    };

    useEffect(() => {
        if (!isEmpty(contractTerms)) {
            const terms = contractTerms?.abacusContractTermsByAccount;
            const { baseLevelAttachments, exceptionsAttachments }: any =
                existingContractAttachments(
                    contractTermId,
                    terms,
                    selectedTracks
                );
            const messages: any = [];
            Object.keys(baseLevelAttachments).forEach(key =>
                messages.push(
                    `[${baseLevelAttachments[key]}] This track is already attached
                    to track-level contract ${key} for this account.
                    You must remove that track to create this track exception.`
                )
            );

            Object.keys(exceptionsAttachments).forEach(key =>
                messages.push(
                    `[${exceptionsAttachments[key]}] This track is already a
                    track exception on contract ${key} for this account.
                    You must remove that track exception to create this contract.`
                )
            );
            if (!isEmpty(messages)) setErrors(messages);
        }
    }, [contractTerms, selectedTracks]);

    const onItemChange = (e: any) => {
        onChange({
            target: {
                name: selectName,
                value: e && e.map(({ value }: any) => value),
            },
        });
        setTracks(e);
        setAreTracksLoaded(true);
    };

    useEffect(() => {
        if (isEmpty(tracksIsrcs)) {
            setSearchResults([]);
            setSearchTerm('');
            setTracks([]);
        } else setSelectedTracksIsrcs(tracksIsrcs);
    }, [tracksIsrcs]);

    useEffect(() => {
        if (!isEmpty(selectedTracksIsrcs)) {
            const isrc = selectedTracksIsrcs[0];
            getTrackByIsrc(isrc);
        }
    }, [selectedTracksIsrcs]);

    useEffect(() => {
        if (
            trackData &&
            trackData?.globalSoundRecordingByIsrc &&
            !areTracksLoaded
        ) {
            const track = trackData?.globalSoundRecordingByIsrc;
            const item = {
                label: `${track.name}-${track.isrc}`,
                value: track.isrc,
            };
            setSearchResults([...searchResults, item]);
            setTracks([...tracks, item]);
            if (selectedTracksIsrcs.length) {
                const newTracksIsrcs = selectedTracksIsrcs.slice(1);
                if (newTracksIsrcs.length)
                    setSelectedTracksIsrcs([...selectedTracksIsrcs.slice(1)]);
                else setAreTracksLoaded(true);
            }
        }
    }, [trackData]);

    return (
        <SearchableSelectList
            className="track-select"
            clearable={true}
            defaultOptions={searchResults}
            isMultiSelect={true}
            id="trackSearch"
            isLoading={false}
            onBlur={onBlur}
            onChange={onItemChange}
            onLoadOptionsHandler={performSearch}
            placeholder={SEARCH_PLACEHOLDER}
            searchTerm={searchTerm}
            value={tracks}
        />
    );
};

export default TrackSearchableSelect;
