import React, { useState } from 'react';
import cx from 'classnames';
import { formatMessage } from '@orchard/frontend-localization';
import { SearchComponent, SearchOption, SearchQuery } from '@orchard/frontend-workstation';
import { useLazyQuery, useMutation, useQuery } from '@apollo/react-hooks';
import { SearchResultsOutline } from '@orchard/frontend-react-components';
import { SoundRecordingSearch } from 'src/definitions/SoundRecordingSearch';
import { RecentItems } from 'src/definitions/RecentItems';
import { artistDisplayName } from 'src/utils/artist';
import { COMPARISON_NAMESPACE, TRACK_TYPE_MUSIC } from 'src/constants';

import SEARCH_SONGS from 'src/queries/soundRecordingSearch.gql';
import ADD_SELECTED_SONG from 'src/mutations/addSelectedSong.gql';
import RECENT_ITEMS from 'src/queries/recentItems.gql';
import ADD_RECENT_ITEM from 'src/mutations/addRecentItem.gql';

const CLASSNAME = 'SoundRecordingSearch';
const CLASSNAME_EMPTY = `${CLASSNAME}-empty`;
const CLASSNAME_EMPTY_TEXT = `${CLASSNAME_EMPTY}-text`;
const SEARCH_RESULT_LIMIT = 100;

const createOptions = (data?: SoundRecordingSearch) => (
    data ? data.soundRecordingsSearch.soundRecordings.map(item => ({
        type: 'song',
        code: item.isrc,
        title: item.name,
        value: item.isrc,
        subtitle: artistDisplayName(item.primaryArtists),
        imageUrl: item.imageLocation,
        count: data.soundRecordingsSearch.totalCount
    })) : []
);

const createRecents = (data?:RecentItems) => (
    data && data.recentItems.map(item => ({
        type: 'recent',
        code: item.isrc,
        title: item.title,
        value: item.isrc,
        subtitle: item.artist,
        imageUrl: item.artwork,
        count: data.recentItems.length
    }))
);

interface SoundRecordingSearchProps {
    setSearchVisibility: React.Dispatch<React.SetStateAction<boolean>>;
}

const SoundRecordingSearchComponent = ({ setSearchVisibility }: SoundRecordingSearchProps) => {
    const [doSearch, { loading, data, error, variables: { queryId = 0 } = {} }] = useLazyQuery<SoundRecordingSearch>(SEARCH_SONGS);
    const [addSelectedSong] = useMutation(ADD_SELECTED_SONG);
    const [showEmptyState, setEmptyStateVisibility] = useState(true);
    const { data: recentData } = useQuery<RecentItems>(RECENT_ITEMS);
    const [addRecentItem] = useMutation(ADD_RECENT_ITEM);

    const onSearch = (variables: SearchQuery) => {
        if (variables.term !== '')
            doSearch({ variables: { ...variables, limit: SEARCH_RESULT_LIMIT, trackType: TRACK_TYPE_MUSIC } });
        setEmptyStateVisibility(variables.term === '');
    };

    const onSelect = (item: SearchOption) => {
        addSelectedSong({ variables: { id: item.code } });
        addRecentItem({
            variables: {
                item: {
                    isrc: item.code, artist: item.subtitle, artwork: item.imageUrl, title: item.title
                }
            }
        });
        setSearchVisibility(false);
    };

    const options = showEmptyState ? createRecents(recentData) : createOptions(data);

    const formatComparisonMessage = (term: string, args?: object) => (
        formatMessage(`${COMPARISON_NAMESPACE}.${term}`, args)
    );

    return (
        <div className={cx(CLASSNAME, { [CLASSNAME_EMPTY]: showEmptyState })}>
            <SearchComponent
                autoFocus
                openOnFocus
                footerType="limited"
                onSelect={onSelect}
                onSearch={onSearch}
                loading={loading}
                options={options}
                error={!!error}
                categories={['song']}
                formatMessage={formatComparisonMessage}
                queryId={queryId}
            />
            { showEmptyState && !(recentData && recentData.recentItems.length > 0) && (
                <div data-testid="empty-state" className={`${CLASSNAME_EMPTY_TEXT}`}>
                    <SearchResultsOutline />
                </div>
            )}
        </div>
    );
};

export default SoundRecordingSearchComponent;
