const useCrudPermissionsMock = jest.fn();
const useIdentityMock = jest.fn();

import React from 'react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { MAIN_CONTENT_CLASSNAME } from 'src/constants';
import {
    OrderDir,
    OwnershipNrProductContentType,
    OwnershipNrSoundRecordingOrderByField,
    OwnershipNrTrackRecordingType,
} from 'src/data/globalTypes';
import { LOAD_MAX_SOUND_RECORDINGS as PAGE_SIZE } from 'src/data/queries';
import * as soundRecordingQuery from 'src/data/queries/getOwnershipNrSoundRecordings/getOwnershipNrSoundRecordings';
import {
    CatalogOwnershipNrSoundRecording,
    OwnershipSoundRecordingsResult,
} from 'src/data/queries/getOwnershipNrSoundRecordings/getOwnershipNrSoundRecordings';
import * as featureFlags from 'src/utils/features';
import * as routeUtils from 'src/utils/route';
import CatalogPage from '../catalogPage';

const testSoundRecording: CatalogOwnershipNrSoundRecording = {
    id: '48b8c55d-0f6e-4f8b-a850-6b6f75707492',
    instancesCount: 1,
    isrc: 'FRZ139680090',
    lastModifiedAt: '2023-08-02T10:54:15.864Z',
    primaryArtists: [
        {
            id: 'd82f2e72-3f26-4b66-ae10-591ef5f0f1f2',
            name: 'Uliana Kot',
        },
    ],
    recordingTitle: 'UKRAINE: Oh, thou with the curly locks, do not leave me',
    srNameVersion: 'UKRAINE: Oh, thou with the curly locks, do not leave me',
    version: null,
    tracks: [
        {
            id: '892a331f-e98b-44c5-a34b-1d23427f3564',
            title: 'UKRAINE: Oh, thou with the curly locks, do not leave me',
            recordingType: 'AUDIO' as OwnershipNrTrackRecordingType,
            version: null,
            product: {
                contentType: 'DIGITAL' as OwnershipNrProductContentType,
                format: 'Album',
                upc: 'ABC123456',
            },
            submittedByVendor: {
                name: 'Test',
                owner: 'knr',
            },
            submittedBySubaccountId: 1234,
        },
        {
            id: '892a331f-e98b-44c5-a34b-1d23427f3567',
            title: 'UKRAINE: Oh, thou with the curly locks, do not leave me',
            recordingType: 'AUDIO' as OwnershipNrTrackRecordingType,
            version: 'Live',
            product: {
                contentType: 'DIGITAL' as OwnershipNrProductContentType,
                format: 'Single',
                upc: 'ABC123456',
            },
            submittedByVendor: {
                name: 'Test',
                owner: 'knr',
            },
            submittedBySubaccountId: 1234,
        },
    ],
};

jest.mock('src/utils/identityPermissions', () => ({
    useCrudPermissions: useCrudPermissionsMock,
}));

jest.mock('@theorchard/suite-frontend', () => {
    const actual = jest.requireActual('@theorchard/suite-frontend');
    return {
        ...actual,
        useIdentity: useIdentityMock,
    };
});

describe('<CatalogPage>', () => {
    const renderPage = () =>
        renderInAppContext(
            <div className={MAIN_CONTENT_CLASSNAME}>
                <CatalogPage />
            </div>
        );

    const fetchMore = jest.fn();
    const setParamsSpy = jest.fn();
    const soundRecordingData: OwnershipSoundRecordingsResult = {
        totalCount: 1,
        items: [testSoundRecording],
    };

    const mockQueries = ({
        loading = false,
        data,
    }: {
        loading?: boolean;
        data?: OwnershipSoundRecordingsResult;
    } = {}) => {
        jest.spyOn(
            soundRecordingQuery,
            'useGetOwnershipNrSoundRecordings'
        ).mockReturnValue({
            data,
            loading,
            error: undefined,
            fetchMore,
            fetchingMore: false,
        });
    };

    beforeEach(() => {
        setParamsSpy.mockClear();
        jest.spyOn(React, 'useState')
            .mockReturnValueOnce([0, jest.fn()])
            .mockReturnValueOnce([PAGE_SIZE, jest.fn()]);
        jest.spyOn(featureFlags, 'useOwnershipUpload').mockReturnValue(true);
    });

    describe('on loading and no data', () => {
        beforeEach(() => {
            jest.spyOn(featureFlags, 'useOwnershipPPEnabledFF').mockReturnValue(
                false
            );
            useIdentityMock.mockReturnValue({ id: 'user-4' });
            useCrudPermissionsMock.mockReturnValue({
                checkCreatePermission: () => ({
                    data: true,
                    loading: false,
                    error: null,
                }),
            });
            mockQueries({ loading: true, data: undefined });
        });

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

        test('show page loading indicator', () => {
            const { container } = renderPage();
            const element = container.getElementsByClassName(
                'LoadingPageIndicator'
            );
            expect(element).toHaveLength(1);
        });
    });

    describe('on loading and has cached data', () => {
        beforeEach(() => {
            jest.spyOn(featureFlags, 'useOwnershipPPEnabledFF').mockReturnValue(
                false
            );
            useIdentityMock.mockReturnValue({ id: 'user-4' });
            useCrudPermissionsMock.mockReturnValue({
                checkCreatePermission: () => ({
                    data: true,
                    loading: false,
                    error: null,
                }),
            });
            mockQueries({ loading: true, data: soundRecordingData });
        });

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

        test('does not show page loading indicator', () => {
            const { container } = renderPage();

            const element = container.getElementsByClassName(
                'LoadingPageIndicator'
            );
            expect(element).toHaveLength(0);
        });
    });

    describe('once loaded and has data', () => {
        beforeEach(() => {
            jest.spyOn(featureFlags, 'useOwnershipPPEnabledFF').mockReturnValue(
                false
            );
            useIdentityMock.mockReturnValue({ id: 'user-4' });
            useCrudPermissionsMock.mockReturnValue({
                checkCreatePermission: () => ({
                    data: true,
                    loading: false,
                    error: null,
                }),
            });
            mockQueries({ loading: false, data: soundRecordingData });
        });

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

        test('calls sound recordings request', () => {
            renderPage();

            expect(
                soundRecordingQuery.useGetOwnershipNrSoundRecordings
            ).toHaveBeenCalledWith({
                limit: PAGE_SIZE,
                offset: 0,
                orderBy: OwnershipNrSoundRecordingOrderByField.LAST_MODIFIED,
                orderDir: OrderDir.DESC,
                filters: {
                    reference: true,
                },
            });
        });

        test('renders CatalogTable', () => {
            const { container } = renderPage();
            const catalogTable = container
                .getElementsByClassName('CatalogTable')
                .item(0);

            expect(catalogTable).toBeVisible();
        });
    });

    describe('once loaded and has data and PDP permissions enabled and user has create permission', () => {
        beforeEach(() => {
            jest.spyOn(featureFlags, 'useOwnershipPPEnabledFF').mockReturnValue(
                true
            );
            useIdentityMock.mockReturnValue({ id: 'user-4' });
            useCrudPermissionsMock.mockReturnValue({
                checkCreatePermission: () => ({
                    data: true,
                    loading: false,
                    error: null,
                }),
            });
            mockQueries({ loading: false, data: soundRecordingData });
        });

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

        test('calls sound recordings request', () => {
            renderPage();

            expect(
                soundRecordingQuery.useGetOwnershipNrSoundRecordings
            ).toHaveBeenCalledWith({
                limit: PAGE_SIZE,
                offset: 0,
                orderBy: OwnershipNrSoundRecordingOrderByField.LAST_MODIFIED,
                orderDir: OrderDir.DESC,
                filters: {
                    reference: true,
                },
            });
        });

        test('renders CatalogTable', () => {
            const { container } = renderPage();
            const catalogTable = container
                .getElementsByClassName('CatalogTable')
                .item(0);

            const createButtons = container
                .getElementsByClassName('CatalogPage-buttons')
                .item(0);

            expect(catalogTable).toBeVisible();
            expect(createButtons).toBeVisible();
        });
    });

    describe('once loaded and has data and PDP permissions enabled and user does not have create permission', () => {
        beforeEach(() => {
            jest.spyOn(featureFlags, 'useOwnershipPPEnabledFF').mockReturnValue(
                true
            );
            useIdentityMock.mockReturnValue({ id: 'user-4' });
            useCrudPermissionsMock.mockReturnValue({
                checkCreatePermission: () => ({
                    data: false,
                    loading: false,
                    error: null,
                }),
            });
            mockQueries({ loading: false, data: soundRecordingData });
        });

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

        test('calls sound recordings request', () => {
            renderPage();

            expect(
                soundRecordingQuery.useGetOwnershipNrSoundRecordings
            ).toHaveBeenCalledWith({
                limit: PAGE_SIZE,
                offset: 0,
                orderBy: OwnershipNrSoundRecordingOrderByField.LAST_MODIFIED,
                orderDir: OrderDir.DESC,
                filters: {
                    reference: true,
                },
            });
        });

        test('renders CatalogTable', () => {
            const { container } = renderPage();
            const catalogTable = container
                .getElementsByClassName('CatalogTable')
                .item(0);

            const createButtons = container
                .getElementsByClassName('CatalogPage-create')
                .item(0);

            expect(catalogTable).toBeVisible();
            expect(createButtons).toEqual(null);
        });
    });

    describe('on sorting', () => {
        beforeEach(() => {
            mockQueries({ loading: true, data: soundRecordingData });
            jest.spyOn(routeUtils, 'useRouteParams').mockReturnValue([
                { orderBy: 'test' },
                setParamsSpy,
            ]);
        });

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

        test('renders loadingIndicator', () => {
            const { container } = renderPage();
            expect(
                container.querySelector('.LoadingSpinner.show')
            ).toBeVisible();
        });
    });

    describe('on disabling create new', () => {
        beforeEach(() => {
            jest.spyOn(featureFlags, 'useOwnershipUpload').mockReturnValue(
                false
            );
            jest.spyOn(featureFlags, 'useOwnershipPPEnabledFF').mockReturnValue(
                false
            );
            useIdentityMock.mockReturnValue({ id: 'user-4' });
            useCrudPermissionsMock.mockReturnValue({
                checkCreatePermission: () => ({
                    data: true,
                    loading: false,
                    error: null,
                }),
            });
        });

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

        test('renders button', () => {
            const { container } = renderPage();
            expect(container.getElementsByTagName('button')[1]).toBeDisabled();
        });
    });
});
