import React from 'react';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import * as adjustmentQuery from 'src/apollo/queries/adjustment';
import AdjustmentsBatchFilters, {
    AdjustmentsBatchFiltersPropTypes,
} from 'src/components/adjustments/adjustments-batch-filters';
import { worksheetAdjustmentsAccounts } from 'src/__fixtures__/graphql/worksheet-adjustments-accounts';
import { worksheetAdjustmentsContracts } from 'src/__fixtures__/graphql/worksheet-adjustments-contracts';
import { ABACUS_PROFILE } from 'src/constants';

describe('<AdjustmentsBatchFilters>', () => {
    const render = (props: AdjustmentsBatchFiltersPropTypes) =>
        renderInAppContext(<AdjustmentsBatchFilters {...props} />, {
            identity: createIdentity({
                profileType: ABACUS_PROFILE,
                id: 'Jane User',
            }),
        });

    const props: AdjustmentsBatchFiltersPropTypes = {
        changeHandler: jest.fn(),
        filters: {},
        areAllFiltersCleared: false,
    };

    describe('Contract Filter', () => {
        beforeEach(() => {
            jest.spyOn(
                adjustmentQuery,
                'useWorksheetAdjustmentsContractsSearch'
            ).mockReturnValue(
                async () => await Promise.resolve(worksheetAdjustmentsContracts)
            );
        });

        it('renders Contract filter', () => {
            render(props);
            expect(screen.getByText('Contract')).toBeDefined();
        });

        it('renders contracts options on search', async () => {
            render(props);

            const expandButtons = await screen.findAllByTestId(
                'SuiteListViewExpandButton'
            );
            fireEvent.click(expandButtons[1]);

            const input = screen.getByTestId('SuiteListViewFilterInput');
            fireEvent.change(input, { target: { value: 'Contract' } });

            await waitFor(() => {
                expect(
                    screen.getByText('Globalnet Contract 64 - 1')
                ).toBeDefined();
                expect(
                    screen.getByText('Tapete Records Contract 109 - 2')
                ).toBeDefined();
            });
        });

        it('renders selected contract on click of Apply button', async () => {
            render(props);
            const expandButtons = await screen.findAllByTestId(
                'SuiteListViewExpandButton'
            );
            fireEvent.click(expandButtons[1]);
            const input = screen.getByTestId('SuiteListViewFilterInput');
            fireEvent.change(input, { target: { value: 'Globalnet' } });

            const selectOption = await screen.findByText(
                'Globalnet Contract 64 - 1'
            );
            fireEvent.click(selectOption);

            const applyButton = await screen.findByText('Apply');
            fireEvent.click(applyButton);

            expect(screen.getByText('Globalnet Contract 64 - 1')).toBeDefined();
            expect(
                screen.queryByText('Tapete Records Contract 109 - 2')
            ).toBeNull();
        });
    });

    describe('Account Filter', () => {
        beforeEach(() => {
            jest.spyOn(
                adjustmentQuery,
                'useWorksheetAdjustmentsAccountsSearch'
            ).mockReturnValue(
                async () => await Promise.resolve(worksheetAdjustmentsAccounts)
            );
        });

        it('renders Account filter', () => {
            render(props);
            expect(screen.getByText('Account')).toBeDefined();
        });

        it('renders accounts options on search', async () => {
            render(props);

            const expandButtons = await screen.findAllByTestId(
                'SuiteListViewExpandButton'
            );
            fireEvent.click(expandButtons[0]);

            const input = screen.getByTestId('SuiteListViewFilterInput');
            fireEvent.change(input, { target: { value: 'Records' } });

            await waitFor(() => {
                expect(
                    screen.getByText('Wrong Planet Records - 1')
                ).toBeDefined();
                expect(
                    screen.getByText('Fake Chapter Records - 2')
                ).toBeDefined();
            });
        });

        it('renders selected account on click of Apply button', async () => {
            render(props);
            const expandButtons = await screen.findAllByTestId(
                'SuiteListViewExpandButton'
            );
            fireEvent.click(expandButtons[0]);
            const input = screen.getByTestId('SuiteListViewFilterInput');
            fireEvent.change(input, { target: { value: 'Planet' } });

            const selectOption = await screen.findByText(
                'Wrong Planet Records - 1'
            );
            fireEvent.click(selectOption);

            const applyButton = await screen.findByText('Apply');
            fireEvent.click(applyButton);

            expect(screen.queryByText('Fake Chapter Records - 2')).toBeNull();
            expect(screen.getByText('Wrong Planet Records - 1')).toBeDefined();
        });
    });

    describe('ApplyToFlowthroughPaymentSelect Filter', () => {
        it('renders apply to flowthrough payment filter', () => {
            render(props);
            expect(
                screen.getByText('Apply To Flowthrough Payment')
            ).toBeDefined();
        });

        it('renders options in dropdown', async () => {
            render(props);

            const expandButton = screen.getAllByTestId(
                'SuiteListViewExpandButton'
            );
            fireEvent.click(expandButton[2]);

            await waitFor(() => {
                expect(screen.getByText('Yes')).toBeDefined();
                expect(screen.getByText('No')).toBeDefined();
                expect(screen.getByText('None')).toBeDefined();
            });
        });

        it('renders selected value on click of Apply button', async () => {
            render({
                ...props,
                filters: { applyToFlowthroughPayment: ['YES'] },
            });

            await waitFor(() => {
                expect(screen.getByText('Yes')).toBeDefined();
                expect(screen.queryByText('None')).toBeNull();
                expect(screen.queryByText('No')).toBeNull();
            });
        });
    });
});
