import React from 'react';
import { screen, within } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import {
    getInputDisplayValue,
    getOption,
    openSelect,
    selectOption,
    searchSelectOptions,
} from 'lib/test-utils/select';
import PpAccountSearchDropdown from '../ppAccountSearchDropdown';

const queryData = [
    {
        vendorId: 1234,
        name: 'Account A',
        uuid: 'account-uuid-a',
    },
    {
        vendorId: 4321,
        name: 'Account B',
        uuid: 'account-uuid-b',
    },
];

const querySearchData = [
    {
        vendorId: 77,
        name: 'Test Account One',
        uuid: 'account-uuid',
    },
    {
        vendorId: 88,
        name: 'Test Account Two',
        uuid: 'account-uuid2',
    },
];

jest.mock('src/data/queries/accountsXpp', () => ({
    useAccountsXppQuery: () => ({
        data: queryData,
        loading: false,
        error: undefined,
    }),
    useAccountXppSearchQuery: () => [
        jest.fn().mockResolvedValue(querySearchData),
        {
            data: querySearchData,
            loading: false,
            error: undefined,
        },
    ],
}));

const staticOptions = [
    { label: 'Static Account • 999', value: '999' },
    { label: 'Static Account Two • 888', value: '888' },
];

describe('<PpAccountSearchDropdown>', () => {
    const onChange = jest.fn();
    const renderComponent = () =>
        renderInAppContext(
            <PpAccountSearchDropdown
                onSelect={onChange}
                placeholder="placeholder text"
                className="class-name"
            />
        );
    const renderWithStaticOptions = () =>
        renderInAppContext(
            <PpAccountSearchDropdown
                onSelect={onChange}
                placeholder="placeholder text"
                className="class-name"
                options={staticOptions}
            />
        );

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

    describe('render dropdown', () => {
        test('can see placeholder text and dropdown to be enabled', () => {
            const component = renderComponent();
            expect(component.getByTestId('SuiteSelectInput')).toHaveTextContent(
                'placeholder text'
            );
            expect(screen.getByTestId('SuiteSelectInput')).not.toHaveClass(
                'disabled'
            );
        });
    });

    describe('initial data load in dropdown', () => {
        test('filter input is empty on initial open', async () => {
            renderComponent();

            await openSelect();

            const suiteSelect = screen.getByTestId('SuiteSelect');
            const filterInput = within(suiteSelect).getByTestId(
                'SuiteListViewFilterInput'
            ) as HTMLInputElement;
            expect(filterInput.value).toBe('');
        });

        test('can see dropdown with options along with brand logo', async () => {
            renderComponent();

            await openSelect();

            const firstOption = getOption('Account A • 1234');
            const secondOption = getOption('Account B • 4321');

            expect(
                firstOption.querySelector('.OrchardBrandIcon')
            ).toBeInTheDocument();
            expect(
                secondOption.querySelector('.OrchardBrandIcon')
            ).toBeInTheDocument();
        });

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

            await openSelect();
            selectOption('Account A • 1234');

            expect(getInputDisplayValue()).toBe('Account A • 1234');
        });
    });

    describe('search data load in dropdown', () => {
        test('filter input contains search term after typing', async () => {
            renderComponent();

            await openSelect();
            await searchSelectOptions('Test', 'Test Account One • 77');

            const suiteSelect = screen.getByTestId('SuiteSelect');
            const filterInput = within(suiteSelect).getByTestId(
                'SuiteListViewFilterInput'
            ) as HTMLInputElement;
            expect(filterInput.value).toBe('Test');
        });

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

            await openSelect();
            await searchSelectOptions('Test', 'Test Account One • 77');

            const firstOption = getOption('Test Account One • 77');
            const secondOption = getOption('Test Account Two • 88');

            expect(
                firstOption.querySelector('.OrchardBrandIcon')
            ).toBeInTheDocument();
            expect(
                secondOption.querySelector('.OrchardBrandIcon')
            ).toBeInTheDocument();
        });

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

            await openSelect();
            await searchSelectOptions('Test', 'Test Account Two • 88');
            selectOption('Test Account Two • 88');

            expect(getInputDisplayValue()).toBe('Test Account Two • 88');
        });
    });

    describe('with static options', () => {
        test('renders static options instead of XPP query data', async () => {
            renderWithStaticOptions();

            await openSelect();

            expect(getOption('Static Account • 999')).toBeInTheDocument();
            expect(getOption('Static Account Two • 888')).toBeInTheDocument();
        });

        test('does not show XPP query data when static options are provided', async () => {
            renderWithStaticOptions();

            await openSelect();

            expect(
                screen.queryByText('Account A • 1234')
            ).not.toBeInTheDocument();
            expect(
                screen.queryByText('Account B • 4321')
            ).not.toBeInTheDocument();
        });

        test('can select a static option', async () => {
            renderWithStaticOptions();

            await openSelect();
            selectOption('Static Account • 999');

            expect(getInputDisplayValue()).toBe('Static Account • 999');
        });

        test('shows brand icon for static options', async () => {
            renderWithStaticOptions();

            await openSelect();

            const option = getOption('Static Account • 999');
            expect(
                option.querySelector('.OrchardBrandIcon')
            ).toBeInTheDocument();
        });
    });
});
