import React from 'react';
import { fireEvent } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { ordersData } from 'lib/test/mockPhysicalDeliveryOrdersData';
import { MAIN_CONTENT_CLASSNAME } from 'src/constants';
import { OrderDir, PhysicalDeliveryOrderBy } from 'src/data/globalTypes';
import { OrdersResult } from 'src/data/queries';
import * as ordersQuery from 'src/data/queries/physicalDeliveryOrders/physicalDeliveryOrders';
import * as routeUtils from 'src/utils/routes';
import { PAGE_SIZE } from '../../constants';
import { MonitorRouteParams } from '../../types';
import Orders, { CLASSNAME } from '../orders';

describe('<Orders>', () => {
    const setParamsSpy = jest.fn();
    const params = {
        showBy: '',
        selectedOrder: '',
        selectedStore: '1705',
        deliveryType: '',
        orderBy: 'createdAt',
        orderDir: 'desc',
    } as MonitorRouteParams;

    const renderPage = () =>
        renderInAppContext(
            <div className={MAIN_CONTENT_CLASSNAME}>
                <Orders params={params} handleParams={setParamsSpy} />
            </div>
        );

    const mockQueries = ({
        loading = false,
        data,
    }: {
        loading?: boolean;
        data?: OrdersResult;
    } = {}) => {
        jest.spyOn(ordersQuery, 'useGetPhysicalOrdersQuery').mockReturnValue({
            data,
            loading,
            error: undefined,
        });
    };

    describe('on loading and no data', () => {
        beforeEach(() => {
            mockQueries({ loading: true, data: undefined });
        });

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

        test('show page loading indicator', () => {
            const { container } = renderPage();
            const element =
                container.getElementsByClassName('LoadingIndicator');
            expect(element).toHaveLength(1);
        });

        test('does not show table spinner', () => {
            const { container } = renderPage();
            expect(container.querySelector('.LoadingSpinner.show')).toBeNull();
        });
    });

    describe('on loading and has cached data', () => {
        beforeEach(() => {
            mockQueries({ loading: true, data: ordersData });
        });

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

        test('does not show page loading indicator', () => {
            const { container } = renderPage();

            const element = container.getElementsByClassName(
                'PageLoadingIndicator'
            );
            expect(element).toHaveLength(0);
        });
    });

    describe('once loaded and has data', () => {
        beforeEach(() => {
            mockQueries({ loading: false, data: ordersData });
        });

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

        test('renders default component', () => {
            const { container } = renderPage();
            const classname = container
                .getElementsByClassName(CLASSNAME)
                .item(0);

            expect(classname).toBeVisible();
        });

        test('calls orders query', () => {
            renderPage();

            expect(ordersQuery.useGetPhysicalOrdersQuery).toHaveBeenCalledWith({
                limit: PAGE_SIZE,
                deliveryTypes: null,
                orderBy: PhysicalDeliveryOrderBy.CREATED_AT,
                orderDir: OrderDir.DESC,
                orderIds: null,
                storeIds: ['1705'],
                offset: 0,
            });
        });

        test('renders OrdersTable', () => {
            const { container } = renderPage();
            const ordersTable = container
                .getElementsByClassName('OrdersTable')
                .item(0);

            expect(ordersTable).toBeVisible();
        });

        test('renders filters', () => {
            const { getByTestId } = renderPage();
            const orderIdDropdown = getByTestId(
                'Dropdown_orderIdSearchDropdown'
            );
            const storesDropdown = getByTestId('Dropdown_storesDropdown');
            const deliveryTypeDropdown = getByTestId(
                'Dropdown_deliveryTypeDropdown'
            );

            expect(orderIdDropdown).toBeVisible();
            expect(storesDropdown).toBeVisible();
            expect(deliveryTypeDropdown).toBeVisible();
        });
    });

    describe('when Delivery Type dropdown selected', () => {
        beforeEach(() => {
            mockQueries({ loading: false, data: ordersData });
            jest.spyOn(routeUtils, 'useRouteParams').mockReturnValue([
                { deliveryType: 'TAKEDOWN' },
                setParamsSpy,
            ]);
        });

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

        test('calls setParams handler and useNrDeliveryStoresQuery with selected type', () => {
            const { container, getByText } = renderPage();
            const input = container
                .querySelectorAll(
                    '[ data-testid="Dropdown_deliveryTypeDropdown"]'
                )
                .item(0)
                .querySelector('input');

            if (input)
                fireEvent.change(input, { target: { value: 'TAKEDOWN' } });
            fireEvent.click(getByText('TAKEDOWN'));

            expect(setParamsSpy).toHaveBeenCalledWith({
                deliveryType: 'TAKEDOWN',
                tab: 'physical',
            });
            expect(ordersQuery.useGetPhysicalOrdersQuery).toHaveBeenCalled();
        });
    });

    describe('on sorting', () => {
        beforeEach(() => {
            mockQueries({ loading: true, data: ordersData });
            jest.spyOn(routeUtils, 'useRouteParams').mockReturnValue([
                { orderBy: 'test' },
                setParamsSpy,
            ]);
        });

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

        test('renders table spinner', () => {
            const { container } = renderPage();
            expect(
                container.querySelector('.LoadingSpinner.show')
            ).toBeVisible();
        });
    });
});
