import { ApolloClient, InMemoryCache } from '@apollo/client';
import * as identity from '@orchard/frontend-identity';
import { formatMessage } from '@orchard/frontend-localization';
import { render } from '@testing-library/react';
import React from 'react';
import * as apolloClient from 'src/apollo/client';
import * as accountQueries from 'src/apollo/queries/account';
import ErrorPage from 'src/pages/error';
import HomePage from 'src/pages/home';
import SplashPage from 'src/pages/splash';
import { AppConfiguration } from 'src/types';
import { App } from '../index';

describe('<App>', () => {
    const appConfig = {
        graphqlUrl: 'somewhere'
    } as AppConfiguration;

    const renderApp = ({ user, error }: {
        user?: identity.ApplicationUser,
        error?: identity.AuthError
    }) => {
        jest.spyOn(identity, 'useAuthFlow').mockReturnValue({
            client: {} as identity.AuthClient,
            user,
            error
        });

        return render(<App config={appConfig} />);
    };

    describe('when loading', () => {
        test('renders loading indicator', () => {
            const { getByText } = renderApp({ user: undefined });

            const loaderElement = getByText(
                formatMessage(SplashPage.TERM_LOADING),
                { selector: `.${SplashPage.CLASSNAME} > h4` }
            );
            expect(loaderElement).toBeVisible();
        });
    });

    describe('when an auth error occurred', () => {
        test('renders error page', () => {
            const message = 'ERROR';
            const { getByText } = renderApp({ error: { code: 'RED', message } });

            const errorMessageElement = getByText(
                message,
                { selector: `.${ErrorPage.CLASSNAME} > .h3` }
            );
            expect(errorMessageElement).toBeVisible();
        });
    });

    describe('when user is authenticated', () => {
        test('renders home page', () => {
            jest.spyOn(apolloClient, 'createApolloClient').mockReturnValue(
                new ApolloClient({ cache: new InMemoryCache() })
            );
            jest.spyOn(accountQueries, 'useAccountQuery').mockReturnValue({
                data: { features: [] },
                loading: false,
                error: undefined
            });

            const user = new identity.AppUser({ name: 'TEST USER' });
            const { getByText } = renderApp({ user });

            const homePageElement = getByText(
                formatMessage(HomePage.TERM_TITLE),
                { selector: `.${HomePage.CLASSNAME} > h2` }
            );
            expect(homePageElement).toBeVisible();
        });
    });
});

describe('window.initFrontend', () => {
    test('is registered', () => {
        expect(window.initFrontend).toBeDefined();
    });
});
