import React from 'react';
import { screen } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import {
    getInputDisplayValue,
    getOption,
    openSelect,
    searchSelectOptions,
    selectOption,
} from 'lib/test-utils/select';
import * as compositionsQuery from 'src/data/queries/compositions/compositions';
import * as compositionsSearchQuery from 'src/data/queries/compositionSearch/compositionSearch';
import CompositionSearchDropdown from '../compositionSearchDropdown';

describe('<CompositionSearchDropdown>', () => {
    const TEST_ID = 'testId';
    const onChange = jest.fn();
    const renderComponent = (
        disabled = false,
        placeholder = 'placeholder text',
        compositionId = undefined
    ) => {
        return renderInAppContext(
            <CompositionSearchDropdown
                compositionId={compositionId}
                disabled={disabled}
                onChange={onChange}
                placeholder={placeholder}
                testId={TEST_ID}
            />
        );
    };

    const queryData = [
        {
            id: 'uuid-1',
            title: 'Composition A',
            pubSongId: 123,
            vendorName: 'Vendor A',
        },
        {
            id: 'uuid-2',
            title: 'Composition B',
            pubSongId: 321,
            vendorName: 'Vendor B',
        },
    ];

    const querySearchData = [
        {
            id: 'uuid-3',
            title: 'Test Composition One',
            pubSongId: 77,
            vendorName: 'Test Vendor One',
        },
        {
            id: 'uuid-4',
            title: 'Test Composition Two',
            pubSongId: 88,
            vendorName: 'Test Vendor Two',
        },
    ];

    const mockQueries = () => {
        jest.spyOn(compositionsQuery, 'useCompositionsQuery').mockReturnValue({
            data: queryData,
            loading: false,
            error: undefined,
        });

        jest.spyOn(
            compositionsSearchQuery,
            'useCompositionsSearchQuery'
        ).mockReturnValue([
            jest.fn().mockResolvedValue(querySearchData),
            {
                data: querySearchData,
                loading: false,
                error: undefined,
            },
        ]);
    };

    beforeEach(() => {
        mockQueries();
        window.HTMLElement.prototype.scrollTo = jest.fn();
    });

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

    describe('render dropdown', () => {
        test('should render dropdown and is enable', () => {
            const { container } = renderComponent();
            expect(container).toBeInTheDocument();
            expect(
                container.querySelector('.CompositionSearchDropdown')
            ).toHaveTextContent('placeholder text');
            expect(screen.getByTestId('testId')).not.toHaveClass('disabled');
        });

        test('should render dropdown and is disabled', () => {
            renderComponent(true);
            expect(screen.getByTestId('SuiteSelectInput')).toHaveClass(
                'disabled'
            );
        });
    });

    describe('initial composition options', () => {
        test('can see dropdown with options', async () => {
            renderComponent();

            await openSelect(TEST_ID);

            expect(getOption('Composition A')).toBeInTheDocument();
            expect(getOption('Composition B')).toBeInTheDocument();
        });

        test('can select option from dropdown', async () => {
            renderComponent();

            await openSelect(TEST_ID);
            selectOption('Composition A');

            expect(onChange).toHaveBeenCalledWith(queryData[0]);
            expect(getInputDisplayValue(TEST_ID)).toBe('Composition A');
        });
    });

    describe('search data load in dropdown', () => {
        test('can search by title for option from dropdown', async () => {
            renderComponent();

            await openSelect(TEST_ID);
            await searchSelectOptions(
                'Test Composition',
                'Test Composition One',
                TEST_ID
            );

            expect(getOption('Test Composition One')).toBeInTheDocument();
            expect(getOption('Test Composition Two')).toBeInTheDocument();
        });

        test('can search and select for option from dropdown', async () => {
            renderComponent();

            await openSelect(TEST_ID);
            await searchSelectOptions('Test', 'Test Composition Two', TEST_ID);
            selectOption('Test Composition Two');

            expect(getInputDisplayValue(TEST_ID)).toBe('Test Composition Two');
        });
    });
});
