import React from 'react';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import {
    tracks,
    trackAttachments,
} from 'src/__fixtures__/graphql/track-search-response';
import * as trackSearchResponse from 'src/__fixtures__/graphql/track-search-response.json';
import * as contractTermQuery from 'src/apollo/queries/contract-term';
import * as trackQuery from 'src/apollo/queries/track-search';
import TrackMultiSelect, {
    TrackMultiSelectPropTypes,
} from 'src/components/shared/track-multiselect';
import { USER_FEATURES } from 'src/constants';

describe('<TrackMultiSelect/>', () => {
    const props: TrackMultiSelectPropTypes = {
        accountId: '1',
        contractTermId: '1',
        contractTerms: [],
        onChange: jest.fn(),
        tracksIsrcs: ['QMMZ200T0181', 'QMMZ200T0182'],
        labelIds: [1, 2],
        setErrors: jest.fn(),
    };

    const render = (features: { [x: number]: boolean }) =>
        renderInAppContext(<TrackMultiSelect {...props} />, {
            identity: createIdentity({ features }),
        });

    afterEach(jest.restoreAllMocks);

    let contractTermAttachmentsMock: any;
    let searchTracksMock: any;
    const getContractsTermsMock = jest.fn().mockReturnValue([]);

    const features = {
        [USER_FEATURES.ABACUS_IMPROVE_TRACK_SEARCH]: false,
    };

    beforeEach(() => {
        searchTracksMock = jest
            .spyOn(trackQuery, 'useTrackSearch')
            .mockReturnValue(
                async () =>
                    await Promise.resolve(
                        trackSearchResponse.globalSoundRecordingSearchES.items
                    )
            );
        jest.spyOn(
            contractTermQuery,
            'useContractTermsByAccount'
        ).mockReturnValue({
            data: { abacusContractTermsByAccount: [] },
            loading: false,
            getContractsTerms: getContractsTermsMock,
        });
        contractTermAttachmentsMock = jest
            .spyOn(contractTermQuery, 'useContractTermAttachments')
            .mockReturnValue(
                async () =>
                    await Promise.resolve(
                        trackAttachments?.abacusContractTerm?.attachmentsObjects
                    )
            );
    });

    it('renders', () => {
        render(features);
        expect(screen.getByText('Search for track(s)')).toBeDefined();
    });

    it('searches tracks on input change', async () => {
        render(features);
        const trackSelect = screen.getByRole('combobox', { hidden: true });
        fireEvent.click(trackSelect);
        const trackInput = screen.getByTestId('SuiteListViewFilterInput')!;
        fireEvent.change(trackInput, { target: { value: 'Test' } });
        await waitFor(() => {
            expect(screen.getByText('Test Track 1-QMMZ200T0180')).toBeDefined();
            expect(screen.getByText('Test Track 2-1118978765')).toBeDefined();
            expect(searchTracksMock).toHaveBeenCalled();
        });
    });

    it('searches tracks on input change when ff enabled', async () => {
        searchTracksMock = jest
            .spyOn(trackQuery, 'useTrackSearchByLabelIds')
            .mockReturnValue(
                async () => await Promise.resolve(tracks.trackSearch.tracks)
            );
        render({
            [USER_FEATURES.ABACUS_IMPROVE_TRACK_SEARCH]: true,
        });
        const trackSelect = screen.getByRole('combobox', { hidden: true });
        fireEvent.click(trackSelect);
        const trackInput = screen.getByTestId('SuiteListViewFilterInput')!;
        fireEvent.change(trackInput, { target: { value: 'Test' } });
        await waitFor(() => {
            expect(screen.getByText('Test Track 1-QMMZ200T0180')).toBeDefined();
            expect(screen.getByText('Test Track 2-1118978765')).toBeDefined();
            expect(searchTracksMock).toHaveBeenCalled();
        });
    });

    it('on select value, do not useContractTermsByAccount', async () => {
        render(features);
        const trackSelect = screen.getByRole('combobox', { hidden: true });
        fireEvent.click(trackSelect);
        const trackInput = screen.getByTestId('SuiteListViewFilterInput')!;
        fireEvent.change(trackInput, { target: { value: 'Test' } });
        await waitFor(() => {
            expect(screen.getByText('Test Track 1-QMMZ200T0180')).toBeDefined();
            expect(screen.getByText('Test Track 2-1118978765')).toBeDefined();
        });
        const option = screen.getByText('Test Track 1-QMMZ200T0180');
        fireEvent.click(option);
        expect(getContractsTermsMock).not.toHaveBeenCalled();
        await waitFor(() => {
            expect(getContractsTermsMock).not.toHaveBeenCalled();
        });
    });

    it('shows selected tracks on page load when ff enabled', async () => {
        render({
            [USER_FEATURES.ABACUS_IMPROVE_TRACK_SEARCH]: true,
        });

        await waitFor(() => {
            expect(
                screen.getAllByText('Test Track 3-QMMZ200T0181')
            ).toBeDefined();
            expect(
                screen.getAllByText('Test Track 4-QMMZ200T0182')
            ).toBeDefined();
            expect(contractTermAttachmentsMock).toHaveBeenCalled();
        });
    });
});
