import React from 'react';
import { screen, fireEvent, waitFor } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import paymentGroups from 'src/__fixtures__/graphql/payment-group-response.json';
import mockMinimums from 'src/__fixtures__/graphql/payment-minimums-response.json';
import * as runControllerListResponse from 'src/__fixtures__/graphql/run-controller-list-response.json';
import * as paymentGroupQuery from 'src/apollo/queries/payment-group';
import * as paymentMinimumsQuery from 'src/apollo/queries/payment-minimums';
import * as runControllerQuery from 'src/apollo/queries/run-controller';
import { Admin } from 'src/components/admin/admin';
import { ABACUS_PROFILE, USER_FEATURES } from 'src/constants';

describe('<Admin>', () => {
    const mockResponse: any = [];

    const mockFeatures = {
        [USER_FEATURES.ABACUS_ADMIN_PAGES_CONVERT_TO_TSX]: false,
        [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: false,
    };

    const render = (features: { [x: number]: boolean } = mockFeatures) =>
        renderInAppContext(<Admin />, {
            identity: createIdentity({
                features,
                profileType: ABACUS_PROFILE,
                id: 'Jane User',
            }),
        });

    mockMinimums.abacusPaymentMinimums.items.forEach((min: any) => {
        mockResponse[min.paymentMinimumId] = {
            ...min,
            id: min.paymentMinimumId,
        };
    });
    const newRunControllerListResponse = {
        ...runControllerListResponse,
    };
    const newPaymentGroups = {
        ...paymentGroups,
    };
    newRunControllerListResponse.abacusRunControllers.totalCount = 320;
    newPaymentGroups.abacusPaymentGroups.totalCount = 320;

    beforeEach(() => {
        jest.spyOn(paymentMinimumsQuery, 'usePaymentMinimums').mockReturnValue({
            data: mockMinimums,
            error: undefined,
            loading: false,
            refetch: jest.fn(),
        });
        jest.spyOn(runControllerQuery, 'useRunControllerList').mockReturnValue({
            data: newRunControllerListResponse,
            loading: false,
            refetch: jest.fn(),
        });
        jest.spyOn(paymentGroupQuery, 'usePaymentGroupsList').mockReturnValue({
            data: paymentGroups,
            error: undefined,
            loading: false,
            refetch: jest.fn(),
        });
    });

    afterEach(jest.restoreAllMocks);

    it('renders', () => {
        render();

        const statementPeriodsTab = screen.getByTestId(
            'manage-statement-periods'
        );
        expect(statementPeriodsTab.classList.contains('active')).toBe(true);

        const paymentGroupsTab = screen.getByTestId('payment-groups');
        expect(paymentGroupsTab.classList.contains('active')).toBe(false);

        const paymentMinimumsTab = screen.getByTestId('payment-minimums');
        expect(paymentMinimumsTab.classList.contains('active')).toBe(false);

        const runControllersTab = screen.getByTestId('run-controllers');
        expect(runControllersTab.classList.contains('active')).toBe(false);

        const sapProfitCentersTab = screen.queryByTestId('sap-profit-centers');
        expect(sapProfitCentersTab).toBeNull();
    });

    it('renders the <RunControllersList />', async () => {
        render();

        const runControllersTab = screen.getByTestId('run-controllers');
        fireEvent.click(runControllersTab);
        await waitFor(() => {
            expect(screen.getByTestId('RunControllersListTestid')).toBeTruthy();
        });
        fireEvent.click(screen.getByRole('tab', { name: 'Run controllers' }));

        const actionButton = await screen.findByRole('button', {
            name: '+ New Run Controller',
        });
        expect(actionButton).toBeInTheDocument();
        fireEvent.click(actionButton);
    });

    it('renders the <PaymentMinimumsForm />', async () => {
        render();

        const paymentMinimumsTab = screen.getByTestId('payment-minimums');
        fireEvent.click(paymentMinimumsTab);
        await waitFor(() => {
            expect(screen.getByTestId('PaymentMinimumsTestid')).toBeTruthy();
        });
    });

    it('renders the <PaymentMinimumsListAndEdit /> when FF is enabled', () => {
        const updatedMockFeatures = {
            [USER_FEATURES.ABACUS_ADMIN_PAGES_CONVERT_TO_TSX]: true,
        };
        render(updatedMockFeatures);

        const paymentMinimumsTab = screen.getByTestId('payment-minimums');
        fireEvent.click(paymentMinimumsTab);

        expect(screen.getByTestId('PaymentMinimumsGridTable')).toBeDefined();
        expect(screen.queryByTestId('PaymentMinimumsTestid')).toBeNull();
    });

    it('renders the <RunControllerList /> when FF is enabled', async () => {
        const updatedMockFeatures = {
            [USER_FEATURES.ABACUS_ADMIN_PAGES_CONVERT_TO_TSX]: true,
        };
        render(updatedMockFeatures);

        const runControllersTab = screen.getByRole('tab', {
            name: 'Run controllers',
        });
        fireEvent.click(runControllersTab);

        await waitFor(() => {
            expect(screen.getByTestId('RunControllersGridTable')).toBeDefined();
            expect(screen.queryByTestId('RunControllersListTestid')).toBeNull();
        });

        const actionButton = await screen.findByRole('button', {
            name: '+ New Run Controller',
        });
        expect(actionButton).toBeDefined();
        fireEvent.click(actionButton);

        expect(screen.getAllByText('New Run Controller')).toBeDefined();
        expect(screen.getAllByText('Contract Type')).toBeDefined();
        expect(screen.getByText('Name')).toBeDefined();
    });

    it('renders the <PaymentGroupList />', async () => {
        render();

        const paymentGroupsTab = screen.getByTestId('payment-groups');
        fireEvent.click(paymentGroupsTab);
        await waitFor(() => {
            expect(screen.getByTestId('PaymentGroupListTestId')).toBeTruthy();
        });

        fireEvent.click(screen.getByRole('tab', { name: 'Payment Groups' }));

        const actionButton = await screen.findByRole('button', {
            name: '+ Add Payment Group',
        });
        expect(actionButton).toBeInTheDocument();
        fireEvent.click(actionButton);
    });

    it('renders pagination blocks for <RunControllers /> and <PaymentGroupList />', () => {
        render();
        const paginations = screen.getAllByTestId('paginationLinksTestid');
        expect(paginations.length).toEqual(1);
    });

    it('renders the <ReferenceSapProfitCentersList /> when FF is enabled', () => {
        const updatedMockFeatures = {
            [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: true,
        };
        render(updatedMockFeatures);

        fireEvent.click(
            screen.getByRole('tab', { name: 'SAP Profit Centers' })
        );

        expect(
            screen.getByTestId('ReferenceSapProfitCenterGridTable')
        ).toBeDefined();
    });

    it('renders Profit Center button when FF is enabled', async () => {
        const updatedMockFeatures = {
            [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: true,
        };
        render(updatedMockFeatures);

        fireEvent.click(
            screen.getByRole('tab', { name: 'SAP Profit Centers' })
        );

        const actionButton = await screen.findByRole('button', {
            name: '+ Add SAP Profit Center',
        });
        expect(actionButton).toBeInTheDocument();
        fireEvent.click(actionButton);

        expect(screen.getByTestId('ProfitCenterFormSidecar')).toBeDefined();
    });
});
