import React from 'react';
import { MockedProvider } from '@apollo/client/testing';
import { screen, fireEvent } from '@testing-library/react';
import { ToastProvider } from '@theorchard/suite-components';
import { renderInAppContext } from '@theorchard/suite-testing';
import { MemoryRouter } from 'react-router-dom';
import { useAccountPayeeBankDetailsQuery } from 'src/apollo/queries/account-payee-bank-details';
import { useAccountPayeeTaxFormInfoQuery } from 'src/apollo/queries/account-payee-tax-form-info';
import { PaymentDetailsReview } from '../payment-details-review';
import {
    ABACUS_ACTIONS,
    ABACUS_ACTION_STATUSES,
} from '@theorchard/accounting-apps-shared';

jest.mock('src/apollo/queries/account-payee-bank-details');
jest.mock('src/apollo/queries/account-payee-tax-form-info');

const mockHistoryPush = jest.fn();

jest.mock('react-router-dom', () => ({
    ...jest.requireActual('react-router-dom'),
    useParams: () => ({ accountId: '123' }),
    useHistory: () => ({ push: mockHistoryPush }),
}));

describe('PaymentDetailsReview', () => {
    beforeEach(() => {
        jest.clearAllMocks();
    });

    const render = () =>
        renderInAppContext(
            <MockedProvider>
                <ToastProvider>
                    <MemoryRouter>
                        <PaymentDetailsReview />
                    </MemoryRouter>
                </ToastProvider>
            </MockedProvider>
        );

    it('renders loading state', async () => {
        (useAccountPayeeBankDetailsQuery as jest.Mock).mockReturnValue({
            data: null,
            loading: true,
        });
        (useAccountPayeeTaxFormInfoQuery as jest.Mock).mockReturnValue({
            data: null,
            loading: true,
        });

        render();

        expect(await screen.findByTestId('LoadingSpinner')).toBeInTheDocument();
    });

    it('renders alert when banking details review is not approved', async () => {
        (useAccountPayeeBankDetailsQuery as jest.Mock).mockReturnValue({
            data: {
                abacusAccount: {
                    accountPayee: {
                        actionStates: [
                            {
                                actionName:
                                    ABACUS_ACTIONS.BANKING_DETAILS_REVIEW,
                                actionStatus: ABACUS_ACTION_STATUSES.RUNNING,
                            },
                        ],
                    },
                },
            },
            loading: false,
        });

        (useAccountPayeeTaxFormInfoQuery as jest.Mock).mockReturnValue({
            data: {},
            loading: false,
        });

        render();

        expect(
            await screen.findByText(
                'Banking Details Review is not "approved" yet'
            )
        ).toBeInTheDocument();
    });

    it('renders alert when payment eligibility is already approved', async () => {
        (useAccountPayeeBankDetailsQuery as jest.Mock).mockReturnValue({
            data: {
                abacusAccount: {
                    accountPayee: {
                        actionStates: [
                            {
                                actionName:
                                    ABACUS_ACTIONS.BANKING_DETAILS_REVIEW,
                                actionStatus: ABACUS_ACTION_STATUSES.APPROVED,
                            },
                            {
                                actionName: ABACUS_ACTIONS.PAYMENT_ELIGIBILITY,
                                actionStatus: ABACUS_ACTION_STATUSES.APPROVED,
                            },
                        ],
                    },
                },
            },
            loading: false,
        });

        (useAccountPayeeTaxFormInfoQuery as jest.Mock).mockReturnValue({
            data: {},
            loading: false,
        });

        render();

        expect(
            await screen.findByText('Payment eligibility is already "approved"')
        ).toBeInTheDocument();
    });

    it('renders alert when payment eligibility is already rejected', async () => {
        (useAccountPayeeBankDetailsQuery as jest.Mock).mockReturnValue({
            data: {
                abacusAccount: {
                    accountPayee: {
                        actionStates: [
                            {
                                actionName:
                                    ABACUS_ACTIONS.BANKING_DETAILS_REVIEW,
                                actionStatus: ABACUS_ACTION_STATUSES.APPROVED,
                            },
                            {
                                actionName: ABACUS_ACTIONS.PAYMENT_ELIGIBILITY,
                                actionStatus: ABACUS_ACTION_STATUSES.REJECTED,
                            },
                        ],
                    },
                },
            },
            loading: false,
        });

        (useAccountPayeeTaxFormInfoQuery as jest.Mock).mockReturnValue({
            data: {},
            loading: false,
        });

        render();

        expect(
            await screen.findByText('Payment eligibility is already "rejected"')
        ).toBeInTheDocument();
    });

    it('renders payment details when all conditions are met', async () => {
        (useAccountPayeeBankDetailsQuery as jest.Mock).mockReturnValue({
            data: {
                abacusAccount: {
                    accountId: '123',
                    accountPayee: {
                        actionStates: [
                            {
                                actionName:
                                    ABACUS_ACTIONS.BANKING_DETAILS_REVIEW,
                                actionStatus: ABACUS_ACTION_STATUSES.APPROVED,
                            },
                            {
                                actionName: ABACUS_ACTIONS.PAYMENT_ELIGIBILITY,
                                actionStatus: ABACUS_ACTION_STATUSES.RUNNING,
                            },
                        ],
                        bankDetails: {
                            payoutMethod: {
                                bankFieldDetails: [
                                    { name: 'AccountName', value: 'John Doe' },
                                ],
                            },
                        },
                    },
                },
            },
            loading: false,
        });

        (useAccountPayeeTaxFormInfoQuery as jest.Mock).mockReturnValue({
            data: {
                abacusAccount: {
                    accountPayee: {
                        accountPayeeTaxFormInfo: { taxName: 'Tax123' },
                    },
                },
            },
            loading: false,
        });

        render();

        expect(screen.getByText('Tax123')).toBeInTheDocument();
    });

    it('calls history.push on cancel button click', () => {
        (useAccountPayeeBankDetailsQuery as jest.Mock).mockReturnValue({
            data: null,
            loading: false,
        });
        (useAccountPayeeTaxFormInfoQuery as jest.Mock).mockReturnValue({
            data: null,
            loading: false,
        });

        render();

        fireEvent.click(screen.getByText('Cancel'));
        expect(mockHistoryPush).toHaveBeenCalledWith(
            '/account/123?selectTab=payment-info'
        );
    });
});
