import React from 'react';
import * as apollo from '@apollo/client';
import { act, fireEvent, screen } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { labelsMock } from 'lib/test/mocks/labels';
import { Props } from 'src/components/headerLabelPicker/labelSearchDropdown';
import LabelSearchDropdown from 'src/components/labelSearchDropdown';
import { INTL_CLASSNAME } from 'src/components/labelSearchDropdown/labelSearchDropdown';
import * as orchardLabel from 'src/data/queries/orchardLabel/orchardLabelById';
import * as orchardLabels from 'src/data/queries/orchardLabels/orchardLabels';
import * as orchardLabelSearch from 'src/data/queries/orchardLabelSearch/orchardLabelSearch';

let labelSearchSpy: jest.SpyInstance;

describe('<LabelSearchDropdown>', () => {
    const defaultProps: Props = {
        // eslint-disable-next-line @typescript-eslint/no-empty-function
        onChange: () => {},
    };

    const renderComponent = (customProps: Partial<Props> = {}) => {
        const props = {
            ...defaultProps,
            ...customProps,
        };

        return renderInAppContext(<LabelSearchDropdown {...props} />);
    };

    beforeEach(() => {
        jest.spyOn(apollo, 'useApolloClient').mockReturnValue(
            {} as apollo.ApolloClient<object>
        );

        jest.spyOn(orchardLabels, 'useOrchardLabels').mockReturnValue(
            labelsMock
        );
        labelSearchSpy = jest
            .spyOn(orchardLabelSearch, 'getPromisedLabelSearch')
            .mockReturnValue(Promise.resolve(labelsMock.data));
    });

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

    test('renders full list of default labels', () => {
        const { container } = renderComponent();

        fireEvent.mouseDown(
            screen.getByText(
                $t(`${INTL_CLASSNAME}.placeholders.searchForLabel`)
            )
        );
        expect(
            container.querySelectorAll('.Select__menu .Select__option')
        ).toHaveLength(labelsMock.data.length);

        expect(screen.getAllByText(labelsMock.data[0].name)).toHaveLength(1);
        expect(screen.getAllByText(labelsMock.data[1].name)).toHaveLength(1);
    });

    test('renders selected label', () => {
        const labelByIdSpy = jest
            .spyOn(orchardLabel, 'useOrchardLabelByIdQuery')
            .mockReturnValue({
                data: labelsMock.data[1],
                loading: false,
                error: undefined,
            });

        renderComponent({
            vendorId: labelsMock.data[1].id.vendorId,
        });

        expect(labelByIdSpy).toHaveBeenCalledWith({
            id: {
                subaccountId: 0,
                vendorId: labelsMock.data[1].id.vendorId,
            },
        });

        expect(screen.getAllByText(labelsMock.data[1].name)).toHaveLength(1);

        expect(
            screen.getAllByText(labelsMock.data[1].id.vendorId)
        ).toHaveLength(1);
    });

    test('searches for label by name', async () => {
        const { container } = renderComponent();

        const searchInput = container.querySelector(
            '.LabelSearchDropdown input'
        );
        if (!searchInput)
            throw new Error('Could not find .LabelSearchDropdown input');

        fireEvent.mouseDown(searchInput);
        fireEvent.change(searchInput, {
            target: { value: labelsMock.data[0].name },
        });

        await act(async () => {
            await new Promise(r => setTimeout(r, 300));
            expect(labelSearchSpy).toHaveBeenCalledWith(
                labelsMock.data[0].name,
                {}
            );
        });
    });
});
