// Copyright (c) 2021 Red Hat, Inc.
// Copyright Contributors to the Open Cluster Management project
import React from 'react'
import { Router } from 'react-router-dom'
import { createBrowserHistory } from 'history'
import { render, screen, waitFor } from '@testing-library/react'
import { MockedProvider } from '@apollo/client/testing'
import { GraphQLError } from 'graphql'
import { wait } from '../../../lib/test-helper'
import SearchResults from './SearchResults'
import {
    SearchResultItemsDocument,
    SearchResultRelatedCountDocument,
    SearchResultRelatedItemsDocument,
} from '../../../search-sdk/search-sdk'

describe('SearchResults Page', () => {
    it('should render page with correct data from search WITH keyword', async () => {
        const mocks = [
            {
                request: {
                    query: SearchResultItemsDocument,
                    variables: {
                        input: [
                            {
                                keywords: ['testCluster'],
                                filters: [
                                    {
                                        property: 'kind',
                                        values: ['pod'],
                                    },
                                ],
                                limit: 10000,
                            },
                        ],
                    },
                },
                result: {
                    data: {
                        searchResult: [
                            {
                                items: [
                                    {
                                        apiversion: 'v1',
                                        cluster: 'testCluster',
                                        container: 'installer',
                                        created: '2021-01-04T14:53:52Z',
                                        hostIP: '10.0.128.203',
                                        kind: 'pod',
                                        name: 'testPod',
                                        namespace: 'testNamespace',
                                        podIP: '10.129.0.40',
                                        restarts: 0,
                                        startedAt: '2021-01-04T14:53:52Z',
                                        status: 'Completed',
                                        _uid: 'testing-search-results-pod',
                                    },
                                ],
                                __typename: 'SearchResult',
                            },
                        ],
                    },
                },
            },
        ]
        render(
            <Router history={createBrowserHistory()}>
                <MockedProvider mocks={mocks}>
                    <SearchResults currentQuery={'kind:pod testCluster'} preSelectedRelatedResources={[]} />
                </MockedProvider>
            </Router>
        )
        // Test the loading state while apollo query finishes
        expect(screen.getByText('Loading')).toBeInTheDocument()
        // This wait pauses till apollo query is returning data
        await wait()
        // Test that the component has rendered correctly with data
        await waitFor(() => expect(screen.queryByText('Pod (1)')).toBeTruthy())
    })

    it('should render page with correct data from search WITHOUT keyword', async () => {
        const mocks = [
            {
                request: {
                    query: SearchResultRelatedCountDocument,
                    variables: {
                        input: [
                            {
                                keywords: [],
                                filters: [
                                    {
                                        property: 'kind',
                                        values: ['pod'],
                                    },
                                ],
                                limit: 10000,
                            },
                        ],
                    },
                },
                result: {
                    data: {
                        searchResult: [
                            {
                                related: [
                                    {
                                        kind: 'cluster',
                                        count: 1,
                                        __typename: 'SearchRelatedResult',
                                    },
                                    {
                                        kind: 'node',
                                        count: 6,
                                        __typename: 'SearchRelatedResult',
                                    },
                                    {
                                        kind: 'secret',
                                        count: 203,
                                        __typename: 'SearchRelatedResult',
                                    },
                                ],
                                __typename: 'SearchResult',
                            },
                        ],
                    },
                },
            },
            {
                request: {
                    query: SearchResultRelatedCountDocument,
                    variables: {
                        input: [
                            {
                                keywords: [],
                                filters: [
                                    {
                                        property: 'kind',
                                        values: ['pod'],
                                    },
                                ],
                                limit: 10000,
                            },
                        ],
                    },
                },
                result: {
                    data: {
                        searchResult: [
                            {
                                related: [
                                    {
                                        kind: 'cluster',
                                        count: 1,
                                        __typename: 'SearchRelatedResult',
                                    },
                                    {
                                        kind: 'node',
                                        count: 6,
                                        __typename: 'SearchRelatedResult',
                                    },
                                    {
                                        kind: 'secret',
                                        count: 203,
                                        __typename: 'SearchRelatedResult',
                                    },
                                ],
                                __typename: 'SearchResult',
                            },
                        ],
                    },
                },
            },
            {
                request: {
                    query: SearchResultItemsDocument,
                    variables: {
                        input: [
                            {
                                keywords: [],
                                filters: [
                                    {
                                        property: 'kind',
                                        values: ['pod'],
                                    },
                                ],
                                limit: 10000,
                            },
                        ],
                    },
                },
                result: {
                    data: {
                        searchResult: [
                            {
                                items: [
                                    {
                                        apiversion: 'v1',
                                        cluster: 'testCluster',
                                        container: 'installer',
                                        created: '2021-01-04T14:53:52Z',
                                        hostIP: '10.0.128.203',
                                        kind: 'pod',
                                        name: 'testPod',
                                        namespace: 'testNamespace',
                                        podIP: '10.129.0.40',
                                        restarts: 0,
                                        startedAt: '2021-01-04T14:53:52Z',
                                        status: 'Completed',
                                        _uid: 'testing-search-results-pod',
                                    },
                                ],
                                __typename: 'SearchResult',
                            },
                        ],
                    },
                },
            },
        ]
        render(
            <Router history={createBrowserHistory()}>
                <MockedProvider mocks={mocks}>
                    <SearchResults currentQuery={'kind:pod'} preSelectedRelatedResources={[]} />
                </MockedProvider>
            </Router>
        )
        // Test the loading state while apollo query finishes
        expect(screen.getByText('Loading')).toBeInTheDocument()
        // This wait pauses till apollo query is returning data
        await wait()
        // Test that the component has rendered correctly with data
        await waitFor(() => expect(screen.queryByText('Pod (1)')).toBeTruthy())
        await waitFor(() => expect(screen.queryByText('Show all (3)')).toBeTruthy())
    })

    it('should render page with correct data from search WITHOUT keyword & preselected related resources', async () => {
        const mocks = [
            {
                request: {
                    query: SearchResultRelatedCountDocument,
                    variables: {
                        input: [
                            {
                                keywords: [],
                                filters: [
                                    {
                                        property: 'kind',
                                        values: ['pod'],
                                    },
                                ],
                                limit: 10000,
                            },
                        ],
                    },
                },
                result: {
                    data: {
                        searchResult: [
                            {
                                related: [
                                    {
                                        kind: 'cluster',
                                        count: 1,
                                        __typename: 'SearchRelatedResult',
                                    },
                                    {
                                        kind: 'node',
                                        count: 6,
                                        __typename: 'SearchRelatedResult',
                                    },
                                    {
                                        kind: 'secret',
                                        count: 203,
                                        __typename: 'SearchRelatedResult',
                                    },
                                ],
                                __typename: 'SearchResult',
                            },
                        ],
                    },
                },
            },
            {
                request: {
                    query: SearchResultRelatedCountDocument,
                    variables: {
                        input: [
                            {
                                keywords: [],
                                filters: [
                                    {
                                        property: 'kind',
                                        values: ['pod'],
                                    },
                                ],
                                limit: 10000,
                            },
                        ],
                    },
                },
                result: {
                    data: {
                        searchResult: [
                            {
                                related: [
                                    {
                                        kind: 'cluster',
                                        count: 1,
                                        __typename: 'SearchRelatedResult',
                                    },
                                    {
                                        kind: 'node',
                                        count: 6,
                                        __typename: 'SearchRelatedResult',
                                    },
                                    {
                                        kind: 'secret',
                                        count: 203,
                                        __typename: 'SearchRelatedResult',
                                    },
                                ],
                                __typename: 'SearchResult',
                            },
                        ],
                    },
                },
            },
            {
                request: {
                    query: SearchResultRelatedItemsDocument,
                    variables: {
                        input: [
                            {
                                keywords: [],
                                filters: [
                                    {
                                        property: 'kind',
                                        values: ['pod'],
                                    },
                                ],
                                relatedKinds: ['node'],
                                limit: 10000,
                            },
                        ],
                    },
                },
                result: {
                    data: {
                        searchResult: [
                            {
                                related: [
                                    {
                                        kind: 'node',
                                        items: [
                                            {
                                                apiversion: 'v1',
                                                architecture: 'amd64',
                                                cluster: 'testCluster',
                                                cpu: 4,
                                                created: '2021-01-04T14:42:49Z',
                                                kind: 'node',
                                                name: 'testNode',
                                                osImage: 'Red Hat Enterprise Linux CoreOS 45.82.202008290529-0 (Ootpa)',
                                                role: 'master',
                                                _uid: 'testing-search-related-results-node',
                                            },
                                        ],
                                        __typename: 'SearchRelatedResult',
                                    },
                                ],
                                __typename: 'SearchResult',
                            },
                        ],
                    },
                },
            },
            {
                request: {
                    query: SearchResultItemsDocument,
                    variables: {
                        input: [
                            {
                                keywords: [],
                                filters: [
                                    {
                                        property: 'kind',
                                        values: ['pod'],
                                    },
                                ],
                                limit: 10000,
                            },
                        ],
                    },
                },
                result: {
                    data: {
                        searchResult: [
                            {
                                items: [
                                    {
                                        apiversion: 'v1',
                                        cluster: 'testCluster',
                                        container: 'installer',
                                        created: '2021-01-04T14:53:52Z',
                                        hostIP: '10.0.128.203',
                                        kind: 'pod',
                                        name: 'testPod',
                                        namespace: 'testNamespace',
                                        podIP: '10.129.0.40',
                                        restarts: 0,
                                        startedAt: '2021-01-04T14:53:52Z',
                                        status: 'Completed',
                                        _uid: 'testing-search-results-pod',
                                    },
                                ],
                                __typename: 'SearchResult',
                            },
                        ],
                    },
                },
            },
        ]
        render(
            <Router history={createBrowserHistory()}>
                <MockedProvider mocks={mocks}>
                    <SearchResults currentQuery={'kind:pod'} preSelectedRelatedResources={['node']} />
                </MockedProvider>
            </Router>
        )
        // Test the loading state while apollo query finishes
        expect(screen.getAllByText('Loading')).toBeTruthy()
        // This wait pauses till apollo query is returning data
        await wait()
        // Test that the component has rendered correctly with data
        await waitFor(() => expect(screen.queryByText('Pod (1)')).toBeTruthy())
        await waitFor(() => expect(screen.queryByText('Show all (3)')).toBeTruthy())
        await waitFor(() => expect(screen.queryByText('Related Node (1)')).toBeTruthy())
    })

    it('should render page with errors', async () => {
        const mocks = [
            {
                request: {
                    query: SearchResultRelatedCountDocument,
                    variables: {
                        input: [
                            {
                                keywords: [],
                                filters: [
                                    {
                                        property: 'kind',
                                        values: ['pod'],
                                    },
                                ],
                                limit: 10000,
                            },
                        ],
                    },
                },
                result: {
                    data: {},
                    errors: [new GraphQLError('Error getting related count data')],
                },
            },
            {
                request: {
                    query: SearchResultRelatedItemsDocument,
                    variables: {
                        input: [
                            {
                                keywords: [],
                                filters: [
                                    {
                                        property: 'kind',
                                        values: ['pod'],
                                    },
                                ],
                                relatedKinds: ['node'],
                                limit: 10000,
                            },
                        ],
                    },
                },
                result: {
                    data: {},
                    errors: [new GraphQLError('Error getting related items data')],
                },
            },
            {
                request: {
                    query: SearchResultItemsDocument,
                    variables: {
                        input: [
                            {
                                keywords: [],
                                filters: [
                                    {
                                        property: 'kind',
                                        values: ['pod'],
                                    },
                                ],
                                limit: 10000,
                            },
                        ],
                    },
                },
                result: {
                    data: {},
                    errors: [new GraphQLError('Error getting search data')],
                },
            },
        ]
        render(
            <Router history={createBrowserHistory()}>
                <MockedProvider mocks={mocks}>
                    <SearchResults currentQuery={'kind:pod'} preSelectedRelatedResources={['node']} />
                </MockedProvider>
            </Router>
        )
        // Test the loading state while apollo query finishes
        expect(screen.getAllByText('Loading')).toBeTruthy()
        // This wait pauses till apollo query is returning data
        await wait()
        // Test that the component has rendered correctly with data
        await waitFor(() => expect(screen.queryByText('Error getting related count data')).toBeTruthy())
        await waitFor(() => expect(screen.queryByText('Error getting related items data')).toBeTruthy())
        await waitFor(() => expect(screen.queryByText('Error getting search data')).toBeTruthy())
    })
})
