import React from 'react';
import { InMemoryCache } from '@apollo/client';
import * as apollo from '@apollo/client';
import { MockedProvider, MockedResponse } from '@apollo/client/testing';
import { fireEvent, waitFor } from '@testing-library/react';
import { createHref, Segment } from '@theorchard/suite-frontend';
import { renderInAppContext } from '@theorchard/suite-testing';
import { createMemoryHistory, MemoryHistory } from 'history';
import {
    getMockProductTrack,
    getProductMetadata,
    getProductValidationData,
} from 'lib/mockProductData';
import { getMockReviewQueueItemData } from 'lib/test/mocks/mockreviewQueueItemData';
import {
    getMockEscalationGroupsQuery,
    mockProductPricingQuery,
    mockProductValidationQuery,
} from 'lib/test/mocks/queries';
import { Router } from 'react-router-dom';
import * as FullscreenModalReviewModule from 'src/components/fullscreenModalReview';
import {
    ProductValidationErrorCode,
    TrackValidationErrorCode,
    TrackValidationWarningCode,
} from 'src/constants';
import * as upsertTracksAudioAttributesEdits from 'src/data/mutations/upsertTracksAudioAttributesEdits/upsertTracksAudioAttributesEdits';
import * as upsertTracksRightsAttributesEdits from 'src/data/mutations/upsertTracksRightsAttributesEdits/upsertTracksRightsAttributesEdits';
import * as productQuery from 'src/data/queries/product/product';
import * as reviewQueueItemQuery from 'src/data/queries/reviewQueueItem/reviewQueueItem';
import { typePolicies } from 'src/data/typePolicies';
import ProductModal from 'src/pages/productModal';
import * as features from 'src/utils/features';
import type { Product } from 'src/data/queries/product/types';

const baseMockProviderRequests = [
    getMockEscalationGroupsQuery(),
    mockProductPricingQuery,
    mockProductValidationQuery,
    mockProductValidationQuery,
];

const defaultProduct = getProductMetadata({
    productId: 33,
    productName: 'ABC',
});

let history: MemoryHistory | null = null;
const upsertAudioAttributesEditsMock = jest.fn();
const upsertRightsAttributesEditsMock = jest.fn();

describe('<ProductModal>', () => {
    const render = (
        product: Product = defaultProduct,
        mockProviderRequests: readonly MockedResponse[] = baseMockProviderRequests,
        nextReviewQueueItemId: number | null = 222,
        isLoading = false,
        initialHistory: MemoryHistory | null = null
    ) => {
        history =
            initialHistory ??
            createMemoryHistory({
                initialEntries: ['/review-queue/33'],
            });
        jest.spyOn(productQuery, 'useProductQuery').mockImplementation(() => ({
            loading: isLoading,
            error: undefined,
            data: product,
            refetch: jest.fn(),
        }));

        jest.spyOn(
            reviewQueueItemQuery,
            'useReviewQueueItemQuery'
        ).mockImplementation(() => ({
            loading: false,
            error: undefined,
            data: getMockReviewQueueItemData(),
        }));

        jest.spyOn(
            upsertTracksAudioAttributesEdits,
            'useUpsertTracksAudioAttributesEditsMutation'
        ).mockReturnValue([
            upsertAudioAttributesEditsMock,
            {} as apollo.MutationResult,
        ]);

        jest.spyOn(
            upsertTracksRightsAttributesEdits,
            'useUpsertTracksRightsAttributesEditsMutation'
        ).mockReturnValue([
            upsertRightsAttributesEditsMock,
            {} as apollo.MutationResult,
        ]);

        const renderProductModal = (
            currentReviewQueueItemId: number
        ): React.ReactElement => {
            if (!history)
                throw new Error('history is null, this should not happen');

            return (
                <Router history={history}>
                    <MockedProvider
                        cache={
                            new InMemoryCache({
                                typePolicies,
                            })
                        }
                        mocks={mockProviderRequests}
                    >
                        <ProductModal
                            reviewQueueItems={[
                                { productId: 33 },
                                { productId: 222 },
                            ]}
                            submissionType="new"
                            currentReviewQueueItemId={currentReviewQueueItemId}
                            nextReviewQueueItemId={nextReviewQueueItemId}
                            productId={product.productId}
                            queueName="initial"
                            reviewQueueItemQueryError={undefined}
                            isReviewQueueItemLocked
                            productTargetGroup={{
                                displayName: 'name',
                                id: '1',
                            }}
                            submittedByUserLanguage={null}
                            lockedByUserName={undefined}
                            wasExistingLockDetected
                        />
                    </MockedProvider>
                </Router>
            );
        };

        const renderResult = renderInAppContext(renderProductModal(33));

        return {
            ...renderResult,
            renderNextReviewQueueItem: () =>
                renderResult.rerender(renderProductModal(222)),
        };
    };

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

    test('renders loading skeleton', () => {
        const { getByTestId } = render(
            defaultProduct,
            baseMockProviderRequests,
            222,
            true
        );

        expect(getByTestId('skip-button')).toBeInTheDocument();
        expect(getByTestId('end-session-button')).toBeInTheDocument();
        expect(getByTestId('ProductModalHeaderV2')).toBeInTheDocument();
        expect(getByTestId('ProductModalBodyLoading')).toBeInTheDocument();
        expect(getByTestId('ProductModalHeaderLoading')).toBeInTheDocument();
        expect(getByTestId('ImgThumbLoading')).toBeInTheDocument();
    });

    test('looks good', () => {
        const { queryByTestId, getByTestId } = render();

        expect(getByTestId('skip-button')).toBeInTheDocument();
        expect(getByTestId('end-session-button')).toBeInTheDocument();
        expect(getByTestId('ProductModalHeaderV2')).toBeInTheDocument();
        expect(getByTestId('queue-move-action-button')).toBeInTheDocument();
        expect(getByTestId('reject-button')).toBeInTheDocument();
        expect(getByTestId('approve-button')).toBeInTheDocument();
        expect(
            queryByTestId('ProductModalBodyLoading')
        ).not.toBeInTheDocument();
        expect(
            queryByTestId('ProductModalHeaderLoading')
        ).not.toBeInTheDocument();
    });

    test('replicates attributes only for tracks missing edits on initial load', async () => {
        const trackWithEdits = getMockProductTrack({
            tuid: '111',
            audioAttributesEdits: [
                { attribute: { id: '5', description: 'Remaster' } },
            ],
            rightsAttributesEdits: [
                { attribute: { id: '1', description: 'Public Domain' } },
            ],
        });

        const trackWithoutEdits = getMockProductTrack({
            tuid: '222',
            audioAttributes: [
                { attribute: { id: '5', description: 'Remaster' } },
            ],
            audioAttributesEdits: [],
            suggestedAudioAttributes: [],
            rightsAttributes: [
                { attribute: { id: '1', description: 'Public Domain' } },
            ],
            rightsAttributesEdits: [],
            suggestedRightsAttributes: [],
        });

        render(
            getProductMetadata({ tracks: [trackWithEdits, trackWithoutEdits] })
        );

        await waitFor(() => {
            expect(upsertAudioAttributesEditsMock).toHaveBeenCalledWith({
                variables: {
                    input: [{ tuid: '222', audioAttributeIds: ['5'] }],
                },
            });
        });

        await waitFor(() => {
            expect(upsertRightsAttributesEditsMock).toHaveBeenCalledWith({
                variables: {
                    input: [{ tuid: '222', rightsAttributeIds: ['1'] }],
                },
            });
        });
    });

    // eslint-disable-next-line jest/no-disabled-tests
    test.skip('renders new FullscreenModal', () => {
        const { getByTestId } = render(
            defaultProduct,
            baseMockProviderRequests,
            null,
            false
        );
        expect(getByTestId('InsightsAppIcon')).toBeVisible();
    });

    test('on skip, navigates to next product', async () => {
        const { getByTestId, queryByTestId } = render();
        const approveButton = getByTestId('approve-button');
        expect(queryByTestId('ProductModalBodyLoading')).toBeNull();
        expect(approveButton).toBeVisible();
        await waitFor(() => {
            expect(approveButton).toBeEnabled();
        });
        expect(history!.location.pathname).toBe('/review-queue/33');

        fireEvent.click(getByTestId('skip-button'));

        expect(history!.location.pathname).toBe('/review-queue/222');
        expect(upsertAudioAttributesEditsMock).toHaveBeenCalledWith({
            variables: { input: [{ audioAttributeIds: [], tuid: '123456' }] },
        });
        expect(upsertRightsAttributesEditsMock).toHaveBeenCalledWith({
            variables: { input: [{ rightsAttributeIds: [], tuid: '123456' }] },
        });
    });

    test('clicking end session results in navigation to review queue page', async () => {
        const { getByTestId, queryByTestId, unmount } = render();

        const productModalWrapper = getByTestId('ProductModal-Wrapper');

        await waitFor(() => {
            expect(history!.location.pathname).toBe('/review-queue/33');
        });
        expect(productModalWrapper).toBeVisible();

        fireEvent.click(getByTestId('end-session-button'));
        unmount();

        await waitFor(() => {
            expect(history!.location.pathname).toBe('/review-queue');
        });

        await waitFor(() => {
            expect(queryByTestId('ProductModal-Wrapper')).toBeNull();
        });

        expect(upsertAudioAttributesEditsMock).toHaveBeenCalledWith({
            variables: { input: [{ audioAttributeIds: [], tuid: '123456' }] },
        });
        expect(upsertRightsAttributesEditsMock).toHaveBeenCalledWith({
            variables: { input: [{ rightsAttributeIds: [], tuid: '123456' }] },
        });
    });

    test('product errors block approval but not rejection', async () => {
        jest.spyOn(
            features,
            'usePreventApprovalWithBlockersFF'
        ).mockReturnValue(true);
        const mockProductRequests = [
            getMockEscalationGroupsQuery(),
            mockProductPricingQuery,
            {
                ...mockProductValidationQuery,
                result: {
                    ...mockProductValidationQuery.result,
                    data: {
                        ...mockProductValidationQuery.result.data,
                        product: getProductValidationData({
                            productErrors: [
                                {
                                    code: ProductValidationErrorCode.ARTWORK,
                                    reason: 'some reason',
                                },
                            ],
                        }),
                    },
                },
            },
        ];
        const { getByTestId } = render(defaultProduct, mockProductRequests);

        await waitFor(() => {
            expect(getByTestId('reject-button')).toBeEnabled();
        });

        await waitFor(() => {
            expect(getByTestId('approve-button')).toBeDisabled();
        });
    });

    test('track errors block approval but not rejection', async () => {
        jest.spyOn(
            features,
            'usePreventApprovalWithBlockersFF'
        ).mockReturnValue(true);
        const mockProductRequests = [
            mockProductPricingQuery,
            {
                ...mockProductValidationQuery,
                result: {
                    ...mockProductValidationQuery.result,
                    data: {
                        ...mockProductValidationQuery.result.data,
                        product: getProductValidationData({
                            trackErrors: [
                                {
                                    code: TrackValidationErrorCode.MISSING_AUDIO_FILE,
                                    reason: 'some reason',
                                },
                            ],
                        }),
                    },
                },
            },
        ];
        const { getByTestId } = render(defaultProduct, mockProductRequests);

        await waitFor(() => {
            expect(getByTestId('reject-button')).toBeEnabled();
        });

        await waitFor(() => {
            expect(getByTestId('approve-button')).toBeDisabled();
        });
    });

    test('AI_GENERATED_AUDIO blocks approval when AI blocker FF is on', async () => {
        jest.spyOn(
            features,
            'usePreventApprovalWithBlockersFF'
        ).mockReturnValue(true);
        jest.spyOn(features, 'useAiGeneratedAudioBlockerFF').mockReturnValue(
            true
        );
        const mockProductRequests = [
            mockProductPricingQuery,
            {
                ...mockProductValidationQuery,
                result: {
                    ...mockProductValidationQuery.result,
                    data: {
                        ...mockProductValidationQuery.result.data,
                        product: getProductValidationData({
                            trackWarnings: [
                                {
                                    code: TrackValidationWarningCode.AI_GENERATED_AUDIO,
                                    reason: 'some reason',
                                },
                            ],
                        }),
                    },
                },
            },
        ];
        const { getByTestId } = render(defaultProduct, mockProductRequests);

        await waitFor(() => {
            expect(getByTestId('reject-button')).toBeEnabled();
        });

        await waitFor(() => {
            expect(getByTestId('approve-button')).toBeDisabled();
        });
    });

    test('AI_GENERATED_AUDIO stays a warning when AI blocker FF is off', async () => {
        jest.spyOn(
            features,
            'usePreventApprovalWithBlockersFF'
        ).mockReturnValue(true);
        jest.spyOn(features, 'useAiGeneratedAudioBlockerFF').mockReturnValue(
            false
        );
        const mockProductRequests = [
            mockProductPricingQuery,
            {
                ...mockProductValidationQuery,
                result: {
                    ...mockProductValidationQuery.result,
                    data: {
                        ...mockProductValidationQuery.result.data,
                        product: getProductValidationData({
                            trackWarnings: [
                                {
                                    code: TrackValidationWarningCode.AI_GENERATED_AUDIO,
                                    reason: 'some reason',
                                },
                            ],
                        }),
                    },
                },
            },
        ];
        const { getByTestId } = render(defaultProduct, mockProductRequests);

        await waitFor(() => {
            expect(getByTestId('approve-button')).toBeEnabled();
        });
    });

    test('after review complete success, navigates to next review queue item', async () => {
        jest.spyOn(FullscreenModalReviewModule, 'default').mockImplementation(
            capturedProps => (
                <div>
                    <button
                        data-testid="trigger-review-complete"
                        onClick={() => capturedProps.onReviewCompleted('ok')}
                    >
                        Test Click Me
                    </button>
                </div>
            )
        );
        const { getByTestId, queryByTestId } = render();

        await waitFor(() => {
            expect(queryByTestId('ProductModalBodyLoading')).toBeNull();
        });
        expect(history!.location.pathname).toBe('/review-queue/33');

        fireEvent.click(getByTestId('trigger-review-complete'));

        await waitFor(() => {
            expect(history!.location.pathname).toBe('/review-queue/222');
        });
    });

    test('after review complete success and no next item, navigates to review queue page', async () => {
        jest.spyOn(FullscreenModalReviewModule, 'default').mockImplementation(
            capturedProps => (
                <div>
                    <button
                        data-testid="trigger-review-complete"
                        onClick={() => capturedProps.onReviewCompleted('ok')}
                    >
                        Test Click Me
                    </button>
                </div>
            )
        );
        const { getByTestId, queryByTestId } = render(
            defaultProduct,
            baseMockProviderRequests,
            null
        );

        await waitFor(() => {
            expect(queryByTestId('ProductModalBodyLoading')).toBeNull();
        });
        expect(history!.location.pathname).toBe('/review-queue/33');

        fireEvent.click(getByTestId('trigger-review-complete'));

        await waitFor(() => {
            expect(history!.location.pathname).toBe('/review-queue');
        });
    });

    // eslint-disable-next-line jest/no-disabled-tests
    test.skip('after review complete failure, displays error message and stays on page', async () => {
        jest.spyOn(FullscreenModalReviewModule, 'default').mockImplementation(
            capturedProps => (
                <div>
                    <button
                        data-testid="trigger-review-complete"
                        onClick={() => capturedProps.onReviewCompleted('error')}
                    >
                        Test Click Me
                    </button>
                </div>
            )
        );
        const { getByTestId, getByText, queryByTestId } = render();

        await waitFor(() => {
            expect(queryByTestId('ProductModalBodyLoading')).toBeNull();
        });

        fireEvent.click(getByTestId('trigger-review-complete'));

        // TO-DO: debug isFailedReviewCompletion state update

        await waitFor(() => {
            expect(
                getByText(
                    'We were unable to save your review. Please contact ProductSupport@sonymusic-pde.com'
                )
            ).toBeVisible();
        });
    });

    test('after clicking skip button - keep search params', () => {
        const currentPageParams = {
            q: 'Fusion',
            accountId: ['28476:0', '28323:31439'],
            assignedTo: ['2903'],
            metaLang: ['ENG', 'ITA'],
            notice: [],
            serviceTierUuid: [],
            submissionType: ['New', 'Re-Submission'],
            queueName: 'initial',
            orderBy: 'saleStartDate',
            orderDir: 'ASC',
        };

        const mockHistory = createMemoryHistory({
            initialEntries: [createHref('/review-queue/33', currentPageParams)],
        });

        const { getByTestId } = render(
            defaultProduct,
            baseMockProviderRequests,
            34,
            false,
            mockHistory
        );

        expect(getByTestId('skip-button')).toBeVisible();
        expect(getByTestId('skip-button')).toBeEnabled();
        expect(history!.location.pathname).toBe('/review-queue/33');
        expect(history!.location.search).toBe(
            '?q=Fusion&accountId=28476%3A0%2C28323%3A31439&assignedTo=2903&metaLang=ENG%2CITA&submissionType=New%2CRe-Submission&queueName=initial&orderBy=saleStartDate&orderDir=ASC'
        );

        fireEvent.click(getByTestId('skip-button'));

        expect(history!.location.pathname).toBe('/review-queue/34');
        expect(history!.location.search).toBe(
            '?accountId=28476%3A0%2C28323%3A31439&assignedTo=2903&metaLang=ENG%2CITA&orderBy=saleStartDate&orderDir=ASC&q=Fusion&queueName=initial&submissionType=New%2CRe-Submission'
        );

        expect(upsertAudioAttributesEditsMock).toHaveBeenCalledWith({
            variables: { input: [{ audioAttributeIds: [], tuid: '123456' }] },
        });
        expect(upsertRightsAttributesEditsMock).toHaveBeenCalledWith({
            variables: { input: [{ rightsAttributeIds: [], tuid: '123456' }] },
        });
    });

    test('after clicking end session - keep search params', async () => {
        const currentPageParams = {
            q: 'Fusion',
            accountId: ['28476:0', '28323:31439'],
            assignedTo: ['2903'],
            metaLang: ['ENG', 'ITA'],
            notice: [],
            serviceTierUuid: [],
            submissionType: ['New', 'Re-Submission'],
            queueName: 'initial',
            orderBy: 'saleStartDate',
            orderDir: 'ASC',
        };

        const mockHistory = createMemoryHistory({
            initialEntries: [createHref('/review-queue/33', currentPageParams)],
        });

        const { getByTestId, queryByTestId, unmount } = render(
            defaultProduct,
            baseMockProviderRequests,
            222,
            false,
            mockHistory
        );

        expect(history!.location.pathname).toBe('/review-queue/33');
        expect(history!.location.search).toBe(
            '?q=Fusion&accountId=28476%3A0%2C28323%3A31439&assignedTo=2903&metaLang=ENG%2CITA&submissionType=New%2CRe-Submission&queueName=initial&orderBy=saleStartDate&orderDir=ASC'
        );

        const endSessionButton = getByTestId('end-session-button');
        expect(endSessionButton).toBeVisible();
        expect(endSessionButton).toBeEnabled();
        expect(getByTestId('ProductModal-Wrapper')).toBeInTheDocument();

        fireEvent.click(endSessionButton);
        unmount();

        await waitFor(() => {
            expect(history!.location.pathname).toBe('/review-queue');
        });

        await waitFor(() => {
            expect(history!.location.search).toBe(
                '?accountId=28476%3A0%2C28323%3A31439&assignedTo=2903&metaLang=ENG%2CITA&orderBy=saleStartDate&orderDir=ASC&q=Fusion&queueName=initial&submissionType=New%2CRe-Submission'
            );
        });

        expect(queryByTestId('ProductModal-Wrapper')).toBeNull();

        expect(upsertAudioAttributesEditsMock).toHaveBeenCalledWith({
            variables: {
                input: [{ audioAttributeIds: [], tuid: '123456' }],
            },
        });
        expect(upsertRightsAttributesEditsMock).toHaveBeenCalledWith({
            variables: {
                input: [{ rightsAttributeIds: [], tuid: '123456' }],
            },
        });
    });

    describe('<FullscreenModalReview> receives isApprovalNoteRequired prop', () => {
        beforeEach(() => {
            jest.spyOn(FullscreenModalReviewModule, 'default');
        });

        test('without potential audio infringement, isApprovalNoteRequired is false', async () => {
            render();
            await waitFor(() => {
                expect(
                    FullscreenModalReviewModule.default as jest.Mock
                ).toHaveBeenCalledWith(
                    expect.objectContaining({
                        isApprovalNoteRequired: false,
                    }),
                    expect.anything()
                );
            });
        });

        test('with POTENTIAL_AUDIO_INFRINGEMENT, isApprovalNoteRequired is true', async () => {
            const mockProductRequests = [
                getMockEscalationGroupsQuery(),
                mockProductPricingQuery,
                {
                    ...mockProductValidationQuery,
                    result: {
                        data: {
                            product: {
                                validation: {
                                    errors: [],
                                    warnings: [],
                                },
                                tracks: [
                                    {
                                        tuid: 12345,
                                        validation: {
                                            errors: [],
                                            warnings: [
                                                {
                                                    code: TrackValidationWarningCode.POTENTIAL_AUDIO_INFRINGEMENT,
                                                    reason: '{"asset_final_id": 1, "matches": [{"artists": ["Focus Sounds"], "title": "Pink Noise 1", "label": "Reseda Garage", "songwhip_url": "https://songwhip.com/focussounds/pink-noise-1"}, {"artists": ["Vibrant Noise"], "title": "Pink Noise For Insomnia", "label": "Vibrant Noise", "songwhip_url": "https://songwhip.com/vibrantnoise/pink-noise-for-insomnia"}]}',
                                                    severity: 'warn',
                                                },
                                            ],
                                        },
                                    },
                                ],
                            },
                        },
                    },
                },
            ];
            render(defaultProduct, mockProductRequests);
            await waitFor(() => {
                expect(
                    FullscreenModalReviewModule.default
                ).toHaveBeenCalledWith(
                    expect.objectContaining({
                        isApprovalNoteRequired: true,
                    }),
                    expect.anything()
                );
            });
        });

        test('with CROSS_ACCOUNT_OSR_CONFLICT, isApprovalNoteRequired is true', async () => {
            const mockProductRequests = [
                getMockEscalationGroupsQuery(),
                mockProductPricingQuery,
                {
                    ...mockProductValidationQuery,
                    result: {
                        ...mockProductValidationQuery.result,
                        data: {
                            ...mockProductValidationQuery.result.data,
                            product: {
                                validation: {
                                    errors: [],
                                    warnings: [],
                                },
                                tracks: [
                                    {
                                        tuid: 12345,
                                        validation: {
                                            errors: [],
                                            warnings: [
                                                {
                                                    code: TrackValidationWarningCode.CROSS_ACCOUNT_OSR_CONFLICT,
                                                    reason: JSON.stringify({
                                                        matches: [
                                                            {
                                                                tuid: 12345,
                                                                product_id: 33,
                                                                upc: 'abc',
                                                                vendor_id: 1,
                                                                isrc: 'WXY111',
                                                            },
                                                        ],
                                                    }),
                                                    severity: 'warn',
                                                },
                                            ],
                                        },
                                    },
                                ],
                            },
                        },
                    },
                },
            ];
            render(defaultProduct, mockProductRequests);
            await waitFor(() => {
                expect(
                    FullscreenModalReviewModule.default
                ).toHaveBeenCalledWith(
                    expect.objectContaining({
                        isApprovalNoteRequired: true,
                    }),
                    expect.anything()
                );
            });
        });
    });

    describe('Tracks review mode duration using Segment', () => {
        let trackEventSpy: jest.SpyInstance;

        beforeEach(() => {
            jest.useFakeTimers();
            jest.spyOn(FullscreenModalReviewModule, 'default');
            trackEventSpy = jest.spyOn(Segment, 'trackEvent');
        });

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

        test('tracks duration with "End Session" event type when end session button is clicked', async () => {
            jest.setSystemTime(100000000);
            const { getByTestId, unmount } = render();
            jest.setSystemTime(100025000);

            fireEvent.click(getByTestId('end-session-button'));
            unmount();

            await waitFor(() => {
                expect(trackEventSpy.mock.calls[1]).toEqual([
                    'Review Mode Duration',
                    {
                        category: 'Content Review Digital Audio',
                        label: 'End Session',
                        accountId: 123,
                        subaccountId: 333,
                        productId: 33,
                        reviewQueueId: 33,
                        sessionStartTime: 100000000,
                        sessionEndTime: 100025000,
                        totalDurationSeconds: 25,
                        value: 25,
                    },
                    'End Session',
                ]);
            });
        });

        test('tracks duration with "Skip Product" event type when skip button is clicked', async () => {
            jest.setSystemTime(100000000);
            const { getByTestId, unmount } = render();
            jest.setSystemTime(100025000);

            fireEvent.click(getByTestId('skip-button'));
            unmount();

            await waitFor(() => {
                expect(trackEventSpy.mock.calls[1]).toEqual([
                    'Review Mode Duration',
                    {
                        category: 'Content Review Digital Audio',
                        label: 'Skip Product',
                        accountId: 123,
                        subaccountId: 333,
                        productId: 33,
                        reviewQueueId: 33,
                        sessionStartTime: 100000000,
                        sessionEndTime: 100025000,
                        totalDurationSeconds: 25,
                        value: 25,
                    },
                    'Skip Product',
                ]);
            });
        });

        describe('review mode duration tracking on <FullscreenModalReview> prop callback', () => {
            beforeEach(() => {
                jest.spyOn(
                    FullscreenModalReviewModule,
                    'default'
                ).mockImplementation(capturedProps => (
                    <div data-testid="fullscreen-modal-review">
                        <button
                            data-testid="trigger-approval"
                            onClick={() =>
                                capturedProps.onReviewCompleted(
                                    'ok',
                                    'Approval'
                                )
                            }
                        >
                            Event Type - Approval
                        </button>
                        <button
                            data-testid="trigger-rejection"
                            onClick={() =>
                                capturedProps.onReviewCompleted(
                                    'ok',
                                    'Rejection'
                                )
                            }
                        >
                            Event Type - Rejection
                        </button>
                        <button
                            data-testid="trigger-queue-move"
                            onClick={() => capturedProps.onQueueMove('initial')}
                        >
                            Event Type of Change Queue
                        </button>
                    </div>
                ));
            });

            test('tracks duration after approval event with "Complete Review"', async () => {
                jest.setSystemTime(100000000);
                const { getByTestId, unmount } = render();
                jest.setSystemTime(100025000);

                fireEvent.click(getByTestId('trigger-approval'));
                unmount();

                await waitFor(() => {
                    expect(trackEventSpy.mock.calls[0]).toEqual([
                        'Review Mode Duration',
                        {
                            category: 'Content Review Digital Audio',
                            label: 'Complete Review',
                            accountId: 123,
                            subaccountId: 333,
                            productId: 33,
                            reviewQueueId: 33,
                            sessionStartTime: 100000000,
                            sessionEndTime: 100025000,
                            totalDurationSeconds: 25,
                            value: 25,
                        },
                        'Complete Review',
                    ]);
                });
            });

            test('tracks duration after rejection event with "Complete Review"', async () => {
                jest.setSystemTime(100000000);
                const { getByTestId, unmount } = render();
                jest.setSystemTime(100025000);

                fireEvent.click(getByTestId('trigger-rejection'));
                unmount();

                await waitFor(() => {
                    expect(trackEventSpy.mock.calls[0]).toEqual([
                        'Review Mode Duration',
                        {
                            category: 'Content Review Digital Audio',
                            label: 'Complete Review',
                            accountId: 123,
                            subaccountId: 333,
                            productId: 33,
                            reviewQueueId: 33,
                            sessionStartTime: 100000000,
                            sessionEndTime: 100025000,
                            totalDurationSeconds: 25,
                            value: 25,
                        },
                        'Complete Review',
                    ]);
                });
            });

            test('tracks duration with "Change Queue" event type', async () => {
                jest.setSystemTime(100000000);
                const { getByTestId, unmount } = render();
                jest.setSystemTime(100025000);

                fireEvent.click(getByTestId('trigger-queue-move'));
                unmount();

                await waitFor(() => {
                    expect(trackEventSpy.mock.calls[1]).toEqual([
                        'Review Mode Duration',
                        {
                            category: 'Content Review Digital Audio',
                            label: 'Change Queue To initial',
                            accountId: 123,
                            subaccountId: 333,
                            productId: 33,
                            reviewQueueId: 33,
                            sessionStartTime: 100000000,
                            sessionEndTime: 100025000,
                            totalDurationSeconds: 25,
                            value: 25,
                        },
                        'Change Queue To initial',
                    ]);
                });
            });
        });
    });
});
