import React from 'react';
import { renderHook, waitFor } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import { useGetBulkSessionIngestionsQuery } from '../index';
import getBulkSessionIngestionsQuery from '../GetBulkSessionIngestions.gql';
import type { GetBulkSessionIngestionsQuery } from '../__generated__/GetBulkSessionIngestions';

const mockData: GetBulkSessionIngestionsQuery = {
    getBulkSessionIngestions: {
        total: 2,
        items: [
            {
                id: 'ing-1',
                ingestionStatus: 'success',
                completedOn: null,
                bulkSession: {
                    id: 'sess-1',
                    slug: 'sess-slug-1',
                    downloadLink: null,
                    label: {
                        __typename: 'Subaccount',
                    },
                },
            },
            {
                id: 'ing-2',
                ingestionStatus: 'failed',
                completedOn: null,
                bulkSession: {
                    id: 'sess-2',
                    slug: 'sess-slug-2',
                    downloadLink: null,
                    label: {
                        __typename: 'Subaccount',
                    },
                },
            },
        ],
    },
};

describe('useGetBulkSessionIngestionsQuery', () => {
    const createWrapper =
        () =>
        ({ children }: any) =>
            (
                <MockedProvider
                    mocks={[
                        {
                            request: {
                                query: getBulkSessionIngestionsQuery,
                                variables: { limit: 50, offset: 0 },
                            },
                            result: { data: mockData },
                        },
                    ]}
                >
                    {children}
                </MockedProvider>
            );

    test('returns null data on initial load', () => {
        const { result } = renderHook(
            () =>
                useGetBulkSessionIngestionsQuery({
                    limit: 50,
                    offset: 0,
                }),
            {
                wrapper: createWrapper(),
            }
        );

        expect(result.current.data).toBeNull();
    });

    test('returns loading state', () => {
        const { result } = renderHook(
            () =>
                useGetBulkSessionIngestionsQuery({
                    limit: 50,
                    offset: 0,
                }),
            {
                wrapper: createWrapper(),
            }
        );

        expect(typeof result.current.loading).toBe('boolean');
    });

    test('returns fetchMore function', () => {
        const { result } = renderHook(
            () =>
                useGetBulkSessionIngestionsQuery({
                    limit: 50,
                    offset: 0,
                }),
            {
                wrapper: createWrapper(),
            }
        );

        expect(typeof result.current.fetchMore).toBe('function');
    });

    test('returns networkStatus', () => {
        const { result } = renderHook(
            () =>
                useGetBulkSessionIngestionsQuery({
                    limit: 50,
                    offset: 0,
                }),
            {
                wrapper: createWrapper(),
            }
        );

        expect(typeof result.current.networkStatus).toBe('number');
    });

    test('returns error when query fails', async () => {
        const errorMessage = 'Query failed';
        const errorWrapper =
            () =>
            ({ children }: any) =>
                (
                    <MockedProvider
                        mocks={[
                            {
                                request: {
                                    query: getBulkSessionIngestionsQuery,
                                    variables: { limit: 50, offset: 0 },
                                },
                                error: new Error(errorMessage),
                            },
                        ]}
                    >
                        {children}
                    </MockedProvider>
                );

        const { result } = renderHook(
            () =>
                useGetBulkSessionIngestionsQuery({
                    limit: 50,
                    offset: 0,
                }),
            {
                wrapper: errorWrapper(),
            }
        );

        await waitFor(() => {
            expect(result.current.error).toBeDefined();
        });
    });

    test('returns empty data when response is empty', async () => {
        const emptyWrapper =
            () =>
            ({ children }: any) =>
                (
                    <MockedProvider
                        mocks={[
                            {
                                request: {
                                    query: getBulkSessionIngestionsQuery,
                                    variables: { limit: 50, offset: 0 },
                                },
                                result: {
                                    data: {
                                        getBulkSessionIngestions: {
                                            total: 0,
                                            items: [],
                                        },
                                    },
                                },
                            },
                        ]}
                    >
                        {children}
                    </MockedProvider>
                );

        const { result } = renderHook(
            () =>
                useGetBulkSessionIngestionsQuery({
                    limit: 50,
                    offset: 0,
                }),
            {
                wrapper: emptyWrapper(),
            }
        );

        await waitFor(() => {
            expect(result.current.data).toEqual({
                total: 0,
                items: [],
            });
        });
    });
});
