import React from 'react';
import { MockedProvider } from '@apollo/client/testing';
import { renderHook, act } from '@testing-library/react-hooks';
import getBulkSessionAssetFileStatusQuery from '../GetBulkSessionAssetFileStatus.gql';
import useAssetFileStatus, { TERMINAL_STATUSES } from '../index';

const mockBulkSessionId = 'session-123';
const mockAssets = [{ id: 'asset-1' }, { id: 'asset-2' }];

const responseMock = (status: string) => ({
    request: {
        query: getBulkSessionAssetFileStatusQuery,
        variables: {
            bulkSessionId: mockBulkSessionId,
            bulkSessionAssetFileIds: mockAssets.map(a => a.id),
        },
    },
    result: {
        data: {
            getBulkSessionAssetFileStatus: {
                status,
            },
        },
    },
});

describe('useAssetFileStatus', () => {
    test('should set status to GraphQL return value when assets are set and returned from query', async () => {
        const status = 'validating';
        const wrapper = ({ children }: any) => (
            <MockedProvider mocks={[responseMock(status)]} addTypename={false}>
                {children}
            </MockedProvider>
        );
        const { result, waitForNextUpdate } = renderHook(
            () =>
                useAssetFileStatus({
                    bulkSessionId: mockBulkSessionId,
                    setAssetUploadInProgress: () => null,
                }),
            { wrapper }
        );
        act(() => {
            result.current.setAssets(mockAssets);
        });
        await waitForNextUpdate();
        expect(result.current.status).toBe(status);
    });

    test.each(TERMINAL_STATUSES)(
        'should update status and clear assets when %s status is received',
        async status => {
            const wrapper = ({ children }: any) => (
                <MockedProvider
                    mocks={[responseMock(status)]}
                    addTypename={false}
                >
                    {children}
                </MockedProvider>
            );
            const { result, waitForNextUpdate } = renderHook(
                () =>
                    useAssetFileStatus({
                        bulkSessionId: mockBulkSessionId,
                        setAssetUploadInProgress: () => null,
                    }),
                { wrapper }
            );
            act(() => {
                result.current.setAssets(mockAssets);
            });
            await waitForNextUpdate();
            expect(result.current.status).toBe(status);
            expect(result.current.setAssets).toBeDefined();
        }
    );

    test('should not poll if bulkSessionId is null', () => {
        const wrapper = ({ children }: any) => (
            <MockedProvider mocks={[]} addTypename={false}>
                {children}
            </MockedProvider>
        );
        const { result } = renderHook(
            () =>
                useAssetFileStatus({
                    bulkSessionId: null,
                    setAssetUploadInProgress: () => null,
                }),
            { wrapper }
        );
        expect(result.current.status).toBeNull();
    });
});
