import React from 'react';
import { useQuery } from '@apollo/client';
import { render } from '@testing-library/react';
import { usePublishingSongWriters } from 'src/data/queries/songWritersSearch/songWritersSearch';
import {
    OrderDir,
    PublishingSongWriterCompositionsOrderByField,
    PublishingSongWriterOrderByField,
} from 'src/data/schemaTypes';
import type { SongWriterListSort } from 'src/data/queries/songWritersSearch/songWritersSearch';

jest.mock('@apollo/client', () => ({
    ...jest.requireActual('@apollo/client'),
    useQuery: jest.fn(),
}));

const useQueryMock = useQuery as jest.Mock;

// Renders the hook so we can inspect the variables it hands to Apollo. These are
// the variables that actually go over the wire, which is what the feature flag
// has to control - not just the arguments the page passes to the hook.
const Probe: React.FC<{ sort?: SongWriterListSort }> = ({ sort }) => {
    usePublishingSongWriters(
        { label: null },
        1,
        25,
        // The nested compositions sort. A different enum, a pre-existing
        // feature, and deliberately outside the flag.
        PublishingSongWriterCompositionsOrderByField.TITLE,
        OrderDir.ASC,
        sort
    );

    return null;
};

const getVariables = () => {
    const { calls } = useQueryMock.mock;
    expect(calls.length).toBeGreaterThan(0);

    return calls[calls.length - 1][1].variables;
};

describe('usePublishingSongWriters', () => {
    beforeEach(() => {
        useQueryMock.mockReset();
        useQueryMock.mockReturnValue({
            error: undefined,
            loading: false,
            data: undefined,
            refetch: jest.fn(),
            networkStatus: 7,
        });
    });

    describe('without a songwriter sort (ADMIN_UX_IMPROVEMENTS off)', () => {
        it('leaves the songwriter sort variables out of the request entirely', () => {
            render(<Probe />);

            const variables = getVariables();

            // Not "present but undefined" - genuinely absent, so the request is
            // the same one the page made before the feature existed and the
            // server applies its own default ordering.
            expect(variables).not.toHaveProperty('songWriterOrderBy');
            expect(variables).not.toHaveProperty('songWriterOrderDir');
            expect(Object.keys(variables).sort()).toEqual([
                'filter',
                'limit',
                'offset',
                'orderBy',
                'orderDir',
            ]);
        });

        it('still sends the nested composition sort', () => {
            render(<Probe />);

            const variables = getVariables();

            expect(variables.orderBy).toBe('TITLE');
            expect(variables.orderDir).toBe('ASC');
        });
    });

    describe('with a songwriter sort (ADMIN_UX_IMPROVEMENTS on)', () => {
        const sort: SongWriterListSort = {
            orderBy: PublishingSongWriterOrderByField.LEGAL_NAME,
            orderDir: OrderDir.DESC,
        };

        it('sends the songwriter sort variables', () => {
            render(<Probe sort={sort} />);

            const variables = getVariables();

            expect(variables.songWriterOrderBy).toBe('LEGAL_NAME');
            expect(variables.songWriterOrderDir).toBe('DESC');
        });

        it('still sends the nested composition sort alongside it', () => {
            render(<Probe sort={sort} />);

            const variables = getVariables();

            expect(variables.orderBy).toBe('TITLE');
            expect(variables.orderDir).toBe('ASC');
        });
    });
});
