import React from 'react';
import { ApolloError } from '@apollo/client';
import { fireEvent, screen } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';

import { downloadFileResponse } from 'src/__fixtures__/graphql/abacus-download-response';
import {
    AbacusDownloadType,
    AbacusStatementPeriodAdjustmentFileErrorType,
} from 'src/apollo/definitions/globalTypes';
import * as abacusDownloadQuery from 'src/apollo/queries/abacus-download';
import {
    AdjustmentsContext,
    AdjustmentsContextProps,
} from 'src/contexts/adjustments-context';
import { AdjustmentsUploadContentErrorScreen } from '../adjustments-upload-content-error-screen';

import type { DownloadFileQuery } from 'src/apollo/queries/__generated__/abacus-download';
import type { AdjustmentFile } from 'src/types/adjustment-file';

describe('<AdjustmentsUploadContentErrorScreen>', () => {
    const mockAdjustmentFileObj: AdjustmentFile = {
        actionStates: null,
        errorType: AbacusStatementPeriodAdjustmentFileErrorType.CONTENT_ERROR,
        fileName: 'test.xlsx',
        invalidFileLocation: null,
        invalidRowCount: 5,
        md5sum: null,
        statementPeriodAdjustmentFileId: 999,
        statementPeriodId: '123',
        totalFileAmountMulticurrency: null,
        totalRoundedAmountMulticurrency: null,
        validFileLocation: null,
        validRowCount: 10,
    };

    const defaultContext: Partial<AdjustmentsContextProps> = {
        adjustmentFile: mockAdjustmentFileObj,
        resetToInitialState: jest.fn(),
    };

    const renderComponent = (
        contextValues: Partial<AdjustmentsContextProps> = {}
    ) => {
        const adjustmentsContext = {
            ...defaultContext,
            ...contextValues,
        } as AdjustmentsContextProps;

        return renderInAppContext(
            <AdjustmentsContext.Provider value={adjustmentsContext}>
                <AdjustmentsUploadContentErrorScreen />
            </AdjustmentsContext.Provider>
        );
    };

    const getDownloadFile = jest.fn();

    let downloadTemplateRequestSpy: jest.SpyInstance<
        {
            data: DownloadFileQuery | undefined;
            error: ApolloError | undefined;
            loading: boolean;
        },
        [downloadType: any, downloadId: string]
    >;

    const mockDownloadFile: DownloadFileQuery = downloadFileResponse;

    beforeEach(() => {
        downloadTemplateRequestSpy = jest
            .spyOn(abacusDownloadQuery, 'useAbacusDownloadFile')
            .mockReturnValue({
                data: mockDownloadFile,
                error: undefined,
                loading: false,
                getDownloadFile,
            });
    });

    it('renders the title', () => {
        renderComponent();

        const title = screen.getByText('Invalid Data');
        expect(title).toBeDefined();
    });

    it('renders the alert', () => {
        renderComponent();

        const alertArea = screen.getByTestId('AdjustmentsContentErrorsAlert');
        expect(alertArea).toBeDefined();
    });

    it('renders the number of valid rows', () => {
        renderComponent();

        const validRowsText = screen.getByText('Valid Rows');
        expect(validRowsText).toBeDefined();

        const validRowsTag = screen.getByTestId('ValidRowsTag');
        expect(validRowsTag).toHaveTextContent('10');
    });

    it('renders the number of invalid rows', () => {
        renderComponent();

        const invalidRowsText = screen.getByText('Invalid Rows');
        expect(invalidRowsText).toBeDefined();

        const invalidRowsTag = screen.getByTestId('InvalidRowsTag');
        expect(invalidRowsTag).toHaveTextContent('5');
    });

    it('renders a button to download the error report', () => {
        renderComponent();

        const downloadErrorReportButton = screen.getByText(
            'DOWNLOAD ERROR REPORT'
        );

        expect(downloadErrorReportButton).toBeDefined();

        expect(downloadTemplateRequestSpy).toHaveBeenCalledWith(
            AbacusDownloadType.ADJUSTMENTS_FILE_ERROR_REPORT,
            '999'
        );

        fireEvent.click(downloadErrorReportButton);
        expect(getDownloadFile).toHaveBeenCalled();
    });

    it('renders a button to reset to inital state when clicked', () => {
        renderComponent();

        const reUploadFileButton = screen.getByText('RE-UPLOAD FILE');
        fireEvent.click(reUploadFileButton);
        expect(defaultContext.resetToInitialState).toHaveBeenCalled();
    });
});
