import React from 'react';
import { screen } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { Route } from 'react-router-dom';
import {
    assignedContributionsList,
    unassignedContributionsList,
} from 'src/__fixtures__/graphql/contributions';
import * as nrContributionQuery from 'src/apollo/queries/nr-contributions';
import {
    sortByColumn,
    sortDirection,
} from 'src/apollo/type-constants/schedule';
import {
    ContributionsList,
    ContributionsListPropTypes,
} from 'src/components/contributor-detail/contributions-list';
import {
    getContributorDetail,
    getContributorScheduleDetail,
} from 'src/urls/frontend-royalties';

describe('<ContributionsList/>', () => {
    describe('Assigned Contributions', () => {
        const defaultProps = {
            hasAbacusSchedule: true,
            includeOnlyValidContributions: false,
        };
        const contributorId =
            assignedContributionsList.nrContributions.items[0].nrContributor.id;
        const scheduleId =
            assignedContributionsList.nrContributions.items[0].abacusScheduleId;

        let requestSpy: any;

        afterEach(jest.restoreAllMocks);

        const render = (props: ContributionsListPropTypes) =>
            renderInAppContext(
                <Route path="/contributor/:contributorId/schedule/:scheduleId">
                    <ContributionsList {...props} />
                </Route>,
                {
                    pathname: getContributorScheduleDetail(
                        contributorId,
                        scheduleId
                    ),
                }
            );

        beforeEach(() => {
            requestSpy = jest
                .spyOn(nrContributionQuery, 'useNRContributionsList')
                .mockReturnValue({
                    data: assignedContributionsList,
                    error: undefined,
                    loading: false,
                    fetchMore: jest.fn(),
                    fetchNextExistingPage: jest.fn(),
                });
        });

        it('renders', () => {
            const { container } = render(defaultProps);
            expect(container).toBeDefined();
        });

        it('requests assigned contributions list on render', () => {
            render(defaultProps);
            expect(requestSpy).toHaveBeenCalledWith({
                filters: {
                    abacusScheduleId: scheduleId,
                    contributorId,
                    hasAbacusSchedule: true,
                    validContributions: false,
                },
                limit: 100,
                offset: 0,
                orderBy: sortByColumn['nrsrNameVersion'],
                orderDir: sortDirection['asc'],
            });
        });

        it('renders contributions list', () => {
            render(defaultProps);
            const list = screen.getAllByTestId('Contributions-list-item');

            expect(list.length).toEqual(2);
            assignedContributionsList?.nrContributions?.items?.forEach(
                (item: any) =>
                    expect(
                        `${item.nrSoundRecording.recordingTitle} - ID ${item.nrSoundRecording.mainArtist}`
                    ).toBeDefined()
            );
        });

        it('displays message when there are no assigned contributions', () => {
            jest.spyOn(
                nrContributionQuery,
                'useNRContributionsList'
            ).mockReturnValue({
                data: { nrContributions: { totalCount: 0, items: [] } },
                error: undefined,
                loading: false,
                fetchMore: jest.fn(),
                fetchNextExistingPage: jest.fn(),
            });
            render(defaultProps);
            expect(screen.getByText('No Assigned Contributions')).toBeDefined();
        });
    });

    describe('Unassigned Contributions', () => {
        const defaultProps = {
            hasAbacusSchedule: false,
            includeOnlyValidContributions: false,
        };
        const contributorId =
            unassignedContributionsList.nrContributions.items[0].nrContributor
                .id;

        let requestSpy: any;

        afterEach(jest.restoreAllMocks);

        const render = (props: ContributionsListPropTypes) =>
            renderInAppContext(
                <Route path="/contributor/:contributorId">
                    <ContributionsList {...props} />
                </Route>,
                { pathname: getContributorDetail(contributorId) }
            );

        beforeEach(() => {
            requestSpy = jest
                .spyOn(nrContributionQuery, 'useNRContributionsList')
                .mockReturnValue({
                    data: unassignedContributionsList,
                    error: undefined,
                    loading: false,
                    fetchMore: jest.fn(),
                    fetchNextExistingPage: jest.fn(),
                });
        });

        it('renders', () => {
            const { container } = render(defaultProps);
            expect(container).toBeDefined();
        });

        it('requests unassigned contributions list on render', () => {
            render(defaultProps);
            expect(requestSpy).toHaveBeenCalledWith({
                filters: {
                    abacusScheduleId: null,
                    contributorId,
                    hasAbacusSchedule: false,
                    validContributions: false,
                },
                limit: 100,
                offset: 0,
                orderBy: sortByColumn['nrsrNameVersion'],
                orderDir: sortDirection['asc'],
            });
        });

        it('renders contributions list', () => {
            render(defaultProps);
            const list = screen.getAllByTestId('Contributions-list-item');

            expect(list.length).toEqual(2);
            unassignedContributionsList?.nrContributions?.items?.forEach(
                (item: any) => {
                    expect(
                        `${item.nrSoundRecording.recordingTitle} - ID ${item.nrSoundRecording.mainArtist}`
                    ).toBeDefined();
                    expect(`${item.id}`).toBeDefined();
                }
            );
        });

        it('displays message when there are no unassigned contributions', () => {
            jest.spyOn(
                nrContributionQuery,
                'useNRContributionsList'
            ).mockReturnValue({
                data: { nrContributions: { totalCount: 0, items: [] } },
                error: undefined,
                loading: false,
                fetchMore: jest.fn(),
                fetchNextExistingPage: jest.fn(),
            });
            render(defaultProps);
            expect(
                screen.getByText('No Unassigned Contributions')
            ).toBeDefined();
        });
    });
});
