import '@testing-library/jest-dom/extend-expect';
import React from 'react';
import { act } from 'react-dom/test-utils';
import { fireEvent } from '@testing-library/react';
import renderWithProvider from 'lib/testing/provider';

import SoundRecordingMetadataQuery from 'src/queries/soundRecordingMetadata.gql';
import { SoundRecordingMetadata } from 'src/definitions';
import { createSoundRecordingMetadata } from '../../../../../lib/factories/soundRecording';
import SelectedSong, { CLASSNAME_CLOSE } from '../SelectedSong';

describe('<SelectedSong>', () => {
    const ARTIST_NAME = 'Billy Bob';
    const SONG_NAME = 'Kangaroo Corgi';
    const IMAGE_LOCATION = 'http://example.org/image.jpg';
    const ISRC = 'AB12345678';
    const RELEASE_DATE_TEXT = 'comparison.releaseDate Jan 1, 2020';
    const RELEASE_DATE = '2020-01-01T00:00:00Z';

    const defaultSoundRecording = createSoundRecordingMetadata({
        name: SONG_NAME,
        imageLocation: IMAGE_LOCATION,
        primaryArtists: [{
            artistName: ARTIST_NAME,
            artistType: 'performer'
        }],
        products: [{
            genreId: null,
            releaseDate: RELEASE_DATE,
            deletions: 'N'
        }]
    });

    const renderMocked = ({ data = defaultSoundRecording, onRemove, index = 0, wait = 1 }: {
        data?: (SoundRecordingMetadata | null),
        onRemove?: (id: string) => void,
        index?: number,
        wait?: number
    } = {}) => {
        const mocks = [{
            request: {
                query: SoundRecordingMetadataQuery,
                variables: {
                    isrc: ISRC
                }
            },
            result: { data }
        }];

        return renderWithProvider(() =>
            <SelectedSong index={index} isrc={ISRC} onRemove={onRemove} />, { mocks, wait });
    };

    test('shows default loading state', async () => {
        const { baseElement } = await renderMocked({ wait: 0 });

        const loaderItems = baseElement.getElementsByClassName('LoaderWrapper-item');
        expect(loaderItems).toHaveLength(4);
    });

    test('shows correctly rendered song metadata', async () => {
        const component = await renderMocked();

        const artistName = await component.findByText(ARTIST_NAME);
        expect(artistName).toBeVisible();

        expect(component.getByText(SONG_NAME)).toBeVisible();
        expect(component.getByAltText('').getAttribute('src')).toBe(IMAGE_LOCATION);
        expect(component.getByText(RELEASE_DATE_TEXT)).toBeVisible();
    });

    test.each([1, 2])('shows color dot with class "bg-dataviz-%s"', async index => {
        const component = await renderMocked({ index });
        const dotElement = component.baseElement.getElementsByClassName(`bg-dataviz-${index}`).item(0);
        expect(dotElement).toBeVisible();
    });

    describe('on remove', () => {
        test('calls onRemove prop', async () => {
            const onRemove = jest.fn();
            const component = await renderMocked({ onRemove });

            const closeButton = component.baseElement.getElementsByClassName(CLASSNAME_CLOSE).item(0);
            if (!closeButton) throw new Error('Remove button not found');

            act(() => {
                fireEvent.click(closeButton);
            });

            expect(onRemove).toHaveBeenCalledWith(ISRC);
        });
    });
});
