import React from 'react';
import { fireEvent, waitFor } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { mockDeliveryProducts } from 'lib/test/mockPhysicalDeliveryOrdersData';
import { MAIN_CONTENT_CLASSNAME } from 'src/constants';
import * as createOrderMutation from 'src/data/mutations/createDeliveryOrder/createDeliveryOrder';
import * as physicalProductsQuery from 'src/data/queries/physicalProductsForDelivery/physicalProductsForDelivery';
import CreateOrder from '../createOrder';

const mockMutation = () => {
    jest.spyOn(
        createOrderMutation,
        'useCreateDeliveryOrderMutation'
    ).mockReturnValue({
        createPhysicalDeliveryOrder: jest.fn(),
        createdData: { id: '12345' },
        createdLoading: false,
        createdError: undefined,
    });
};

const mockProducts = () => {
    jest.spyOn(
        physicalProductsQuery,
        'useGetPhysicalProductsForDelivery'
    ).mockReturnValue({
        data: { products: mockDeliveryProducts, totalCount: 100 },
        loading: false,
        error: undefined,
    });
};

describe('<CreateOrder>', () => {
    const renderPage = () =>
        renderInAppContext(
            <div className={MAIN_CONTENT_CLASSNAME}>
                <CreateOrder />
            </div>
        );

    describe('on load', () => {
        test('show page with relevant sections', () => {
            const { container, getByTestId, getByText } = renderPage();
            expect(getByTestId('select-service')).toBeTruthy();
            expect(getByTestId('delivery-type')).toBeTruthy();
            expect(getByTestId('view-products')).toBeTruthy();
            expect(
                container.getElementsByClassName('form-check-input')
            ).toBeTruthy();
            expect(getByText('Select Store')).toBeVisible();
        });
    });

    describe('on select view products', () => {
        test('it returns some selectable products', () => {
            mockProducts();
            const { container, getByTestId, getByText } = renderPage();
            const selectStore =
                getByTestId('select-service').querySelector('input');
            if (selectStore) {
                fireEvent.change(selectStore, {
                    target: { value: 'Altafonte (Iberia)' },
                });
                fireEvent.click(getByText('Altafonte (Iberia)'));
            }
            const viewButton = getByTestId('view-products');
            fireEvent.click(viewButton);
            expect(getByText('Ben Rubin')).toBeVisible();
            const checkAll = container.querySelectorAll(
                "input[type='checkbox']"
            )[0] as HTMLInputElement;
            expect(checkAll).toBeVisible();
            fireEvent.click(checkAll);
            expect(checkAll.checked).toBeTruthy();
        });
    });

    describe('on generate order', () => {
        test('I can generate an order', async () => {
            mockProducts();
            mockMutation();
            const { container, getByTestId, getByText, findByTestId } =
                renderPage();
            const selectStore =
                getByTestId('select-service').querySelector('input');
            if (selectStore) {
                fireEvent.change(selectStore, {
                    target: { value: 'Altafonte (Iberia)' },
                });
                fireEvent.click(getByText('Altafonte (Iberia)'));
            }
            const viewButton = getByTestId('view-products');
            fireEvent.click(viewButton);
            const checkbox = container.querySelectorAll(
                "input[type='checkbox']"
            )[0] as HTMLInputElement;
            fireEvent.click(checkbox);
            const generateButton = getByTestId('generate-button');
            fireEvent.click(generateButton);

            expect(await findByTestId('successMessage')).toBeTruthy();
            await waitFor(() =>
                expect(
                    getByText(
                        'Your Associated Order ID is 12345. You will receive an email with the download link once completed. It is now safe to exit this page or generate more file(s) for another delivery.'
                    )
                ).toBeVisible()
            );
        });

        test('I see the error screen', async () => {
            mockProducts();
            jest.spyOn(
                createOrderMutation,
                'useCreateDeliveryOrderMutation'
            ).mockReturnValue({
                createPhysicalDeliveryOrder: jest.fn(),
                createdData: undefined,
                createdLoading: false,
                createdError: Error('some error'),
            });
            const { container, getByTestId, getByText, findByTestId } =
                renderPage();
            const selectStore =
                getByTestId('select-service').querySelector('input');
            if (selectStore) {
                fireEvent.change(selectStore, {
                    target: { value: 'Altafonte (Iberia)' },
                });
                fireEvent.click(getByText('Altafonte (Iberia)'));
            }
            const viewButton = getByTestId('view-products');
            fireEvent.click(viewButton);
            const checkbox = container.querySelectorAll(
                "input[type='checkbox']"
            )[0] as HTMLInputElement;
            fireEvent.click(checkbox);
            const generateButton = getByTestId('generate-button');
            fireEvent.click(generateButton);
            expect(await findByTestId('errorMessage')).toBeTruthy();
            await waitFor(() =>
                expect(
                    getByText(
                        'Failed to create order. Please check back later.'
                    )
                ).toBeVisible()
            );
        });
    });
});
