import '@testing-library/jest-dom/extend-expect';
import { fireEvent, act, cleanup } from '@testing-library/react';
import renderWithProvider from 'lib/testing/provider';
import { mockQuery } from 'lib/testing/mocks';
import { CountryRecords } from 'src/selectors';
import * as queries from 'src/queries';
import TopCountries, { TERM_HEADER, CLASSNAME } from '../TopCountries';
import { TEST_ID as COUNTRY_TEST_ID } from '../topCountriesTable/TopCountriesTable';
import { TEST_ID as HEADER_TEST_ID } from '../../compareSectionHeader/CompareSectionHeader';
import { TERM_TRIGGER_LABEL as DATASOURCES_TERM_TRIGGER } from '../../sourcesStatus/SourcesStatus';
import { TopCountry } from '../../../selectors/soundRecordingCountries';

type BatchCountriesQueryResult = {
    loading: boolean;
    data: CountryRecords[],
    error: Error | undefined;
    count: number | undefined;
    showCount: (count?: number | undefined) => void;
};

const DUMMY_COUNTRY:TopCountry = {
    code: 'AS',
    alpha3: 'ASD',
    name: 'asd',
    value: 1000,
    highlight: false,
    position: 1
};

describe('<TopCountries>', () => {
    const selectedSongIds = ['CODE1', 'CODE2'];
    let queryData: BatchCountriesQueryResult;

    const renderMocked = async () => {
        const container = await renderWithProvider(TopCountries, {
            filter: { selectedSongIds },
            mocks: selectedSongIds.map(isrc =>
                mockQuery('SoundRecordingMetadataQuery', {
                    variables: { isrc }
                }))
        });

        return container;
    };

    beforeEach(() => {
        queryData = {
            loading: false,
            data: [{
                isrc: 'test_ISRC',
                name: 'Test Name',
                countries: Array(6).fill(DUMMY_COUNTRY).map((country, i) => ({
                    ...country,
                    code: country.code + i
                })),
            }],
            error: undefined,
            count: 5,
            showCount: jest.fn(),
        };
    });

    afterEach(() => {
        jest.restoreAllMocks();
        cleanup();
    });

    test('renders TopCountries', async () => {
        const component = await renderMocked();

        const header = component.getByText(TERM_HEADER);
        const content = component.container.getElementsByClassName(CLASSNAME);
        expect(header).toBeVisible();
        expect(content.length).toBe(1);
    });

    test('renders Header Menu', async () => {
        const component = await renderMocked();
        const header = component.getByTestId(HEADER_TEST_ID);

        expect(header).toBeVisible();
    });

    test('renders two topCountries tables', async () => {
        const container = await renderMocked();

        const components = container.getAllByTestId(COUNTRY_TEST_ID);
        expect(components.length).toBe(2);
    });

    test('shows sources', async () => {
        const container = await renderMocked();

        const sourcePopoverTrigger = container.getByText(DATASOURCES_TERM_TRIGGER);
        expect(sourcePopoverTrigger).toBeVisible();
    });

    test('calls handleMore handler', async () => {
        jest.spyOn(queries, 'useBatchCountriesQuery').mockImplementation(() => queryData);
        const container = await renderMocked();
        const showMoreButton = container.getByText(/show.more/);
        act(() => {
            fireEvent.click(showMoreButton);
        });

        expect(queryData.showCount).toHaveBeenCalled();
    });

    test('does not call handleMore when number of countries <= 5', async () => {
        jest.spyOn(queries, 'useBatchCountriesQuery').mockImplementation(() => ({
            ...queryData,
            data: queryData.data.map(data => ({
                ...data,
                countries: []
            }))
        }));
        const container = await renderMocked();
        const showMoreButton = container.getByText(/show.more/);
        act(() => {
            fireEvent.click(showMoreButton);
        });

        expect(showMoreButton).toBeDisabled();
        expect(queryData.showCount).not.toHaveBeenCalled();
    });

    test('calls handleLess handler', async () => {
        jest.spyOn(queries, 'useBatchCountriesQuery').mockImplementation(() => queryData);
        const container = await renderMocked();
        let showMoreButton = container.getByText(/show.more/);
        act(() => {
            fireEvent.click(showMoreButton);
        });

        showMoreButton = container.getByText(/show.less/);
        act(() => {
            fireEvent.click(showMoreButton);
        });

        expect(queryData.showCount).toHaveBeenCalledWith(5);
    });
});
