import React from 'react';
import { ApolloError } from '@apollo/client';
import { screen } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { ABACUS_PROFILE, USER_FEATURES } from 'src/constants';
import { accountingRunDetail } from 'src/__fixtures__/graphql/accounting-run';
import { ledgerAccountingRunBalance } from 'src/__fixtures__/graphql/ledger-accounting-run-balance-response';
import { GetLedgerAccountingRunBalanceQuery } from 'src/apollo/queries/__generated__/ledger-accounting-run-balance';
import * as accountingRunQuery from 'src/apollo/queries/accounting-run';
import * as ledgerAccRunBalanceQuery from 'src/apollo/queries/ledger-accounting-run-balance';
import RunSummaryItemList from 'src/components/run-summary-item/run-summary-item-list';

jest.mock('react-router-dom', () => ({
    ...jest.requireActual('react-router-dom'),
    useParams: () => ({ accountingRunId: '1' }),
}));

describe('<RunSummaryItemList>', () => {
    let ledgerAccountingRunBalanceQuerySpy: jest.SpyInstance<{
        data: GetLedgerAccountingRunBalanceQuery | undefined;
        loading: boolean;
        error: ApolloError | undefined;
    }>;

    const mockIdentity = {
        id: 'Jane User',
        profileType: ABACUS_PROFILE,
        features: {
            [USER_FEATURES.ABACUS_CONTRACT_MECHANICAL_DEDUCTIONS_CALC]: false,
        },
    };

    beforeEach(() => {
        jest.spyOn(
            accountingRunQuery,
            'useAbacusAccountingRunFragment'
        ).mockReturnValue(accountingRunDetail.abacusAccountingRun);

        ledgerAccountingRunBalanceQuerySpy = jest
            .spyOn(ledgerAccRunBalanceQuery, 'useLedgerAccountingRunBalance')
            .mockReturnValue({
                data: ledgerAccountingRunBalance,
                loading: false,
                error: undefined,
            });
    });

    afterEach(jest.restoreAllMocks);

    const render = (identity = mockIdentity) =>
        renderInAppContext(<RunSummaryItemList />, { identity });

    it('renders the expected table headers', () => {
        render();
        expect(screen.getAllByText('Account')).toBeDefined();
        expect(screen.getAllByText('Account ID')).toBeDefined();
        expect(screen.getAllByText('Contract')).toBeDefined();
        expect(screen.getAllByText('Contract ID')).toBeDefined();
        expect(screen.getAllByText('Payment Currency')).toBeDefined();
        expect(screen.getAllByText('Gross Revenue')).toBeDefined();
        expect(screen.getAllByText('Dist. Fee')).toBeDefined();
        expect(screen.getAllByText('Net Revenue')).toBeDefined();
        expect(screen.getAllByText('Mech Deduction')).toBeDefined();
        expect(screen.getAllByText('Mech Admin Fee Deduction')).toBeDefined();
    });

    it('fetches a page of summary items on render', () => {
        render();
        expect(ledgerAccountingRunBalanceQuerySpy).toHaveBeenCalled();
    });

    it('renders a list of run summary items', () => {
        render();
        const grid = screen.getByTestId('GridTable');
        expect(grid.textContent).toEqual(
            '1 - 2 of 2AccountAccount IDContractContract IDPayment CurrencyGross RevenueDist. FeeNet RevenueMech DeductionMech Admin Fee DeductionAccountAccount IDContractContract IDPayment CurrencyGross RevenueDist. FeeNet RevenueMech DeductionMech Admin Fee Deductionaccount test 11contract test 11USD4,565.00100.00454.00965.0078,456.00account test 22contract test 22USD4,565.00100.00456.00123.0098,412.00'
        );
    });

    it('renders links to account page > accounting tab', () => {
        render();
        const accountingTabLink = screen.getAllByTestId(
            'accountingTabLink-1'
        ) as HTMLLinkElement[];
        expect(accountingTabLink[0].href).toContain(
            '/account/1/?selectTab=accounting'
        );
    });

    it('renders links to the contract detail page', () => {
        render();
        const contractLink = screen.getAllByTestId(
            'contractDetailLink-1'
        ) as HTMLLinkElement[];
        expect(contractLink[0].href).toContain('/contract/1');
    });

    it('renders the expected table headers for neighbouring rights accounting period', () => {
        jest.spyOn(
            accountingRunQuery,
            'useAbacusAccountingRunFragment'
        ).mockReturnValue({
            ...accountingRunDetail.abacusAccountingRun,
            accountingPeriod: {
                ...accountingRunDetail.abacusAccountingRun.accountingPeriod,
                contractType: 'neighbouring_rights',
            },
        });
        const mockIdentity = {
            id: 'Jane User',
            profileType: ABACUS_PROFILE,
            features: {
                [USER_FEATURES.ABACUS_CONTRACT_MECHANICAL_DEDUCTIONS_CALC]: true,
            },
        };
        render(mockIdentity);
        expect(screen.getAllByText('Account')).toBeDefined();
        expect(screen.getAllByText('Account ID')).toBeDefined();
        expect(screen.getAllByText('Contract')).toBeDefined();
        expect(screen.getAllByText('Contract ID')).toBeDefined();
        expect(screen.getAllByText('Payment Currency')).toBeDefined();
        expect(screen.getAllByText('Gross Revenue')).toBeDefined();
        expect(screen.getAllByText('Dist. Fee')).toBeDefined();
        expect(screen.getAllByText('Net Revenue')).toBeDefined();
        expect(screen.queryAllByText('Mech Deduction')).toHaveLength(0);
        expect(screen.queryAllByText('Mech Admin Fee Deduction')).toHaveLength(
            0
        );
    });
});
