import React from 'react';
import { screen, waitFor } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { EntityBulkEditFileInfo } from '../entity-bulk-edit-file-info';
import { EntityBulkEditTable } from 'src/components/contract-bulk-edit/common/entity-bulk-edit-table';
import EntityBulkEditProcessingStatus from 'src/components/contract-bulk-edit/common/entity-bulk-edit-processing-status';

// mock file parsing
jest.mock('xlsx', () => ({
    __esModule: true,
    read: () => ({
        SheetNames: ['Sheet1'],
        Sheets: {
            Sheet1: {
                '!ref': 'A1:B1',
                A1: { v: 'contract_term_id' },
                B1: { v: 'attachments.set' },
            },
        },
    }),
    utils: {
        decode_range: () => ({
            s: { r: 0, c: 0 },
            e: { r: 0, c: 1 },
        }),
        encode_cell: (cell: { r: number; c: number }) => {
            const col = String.fromCharCode(65 + cell.c);
            return `${col}${cell.r + 1}`;
        },
        sheet_to_json: () => [
            {
                contract_term_id: '1234567890',
                'attachments.set': '111',
            },
        ],
    },
}));

jest.mock(
    'src/components/contract-bulk-edit/common/entity-bulk-edit-processing-status',
    () => ({
        __esModule: true,
        default: jest.fn(() => null),
    })
);

jest.mock(
    'src/components/contract-bulk-edit/common/entity-bulk-edit-table',
    () => ({
        __esModule: true,
        CONTRACT_TERM_TABLE_HEADERS: [],
        EntityBulkEditTable: jest.fn(() => null),
    })
);

jest.mock(
    'src/components/contract-bulk-edit/common/edit-schema/contract-term-bulk-edit-schema',
    () => ({
        contractTermsSchema: {
            displayName: 'Contract Terms',
            columns: [],
            expectedFileColumns: [
                { name: 'contract_term_id' },
                { name: 'attachments.set' },
            ],
            toEntries: jest.fn(async () => [
                {
                    contractTermId: '1234567890',
                    contractTermName: 'Test name',
                    currentAttachments: [],
                    contractName: 'Test Contract name',
                    contractId: 123,
                    attachmentsToAppend: [],
                    attachmentsToSet: '111',
                    calculatedAttachments: [],
                },
            ]),
            apply: jest.fn(),
        },
    })
);

const makeFile = (name = 'bulk.xlsx'): File => {
    return {
        name,
        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        arrayBuffer: jest.fn(async () => new ArrayBuffer(8)),
        lastModified: 0,
        size: 0,
    } as unknown as File;
};

describe('<EntityBulkEditFileInfo>', () => {
    const props = {
        bulkEditFile: makeFile(),
    } as const;

    const renderComponent = (p: typeof props) =>
        renderInAppContext(<EntityBulkEditFileInfo {...p} />);

    it('renders the section body and Apply button', async () => {
        renderComponent(props);

        await waitFor(() => {
            expect(screen.getByText('Apply')).toBeDefined();
            expect(
                screen.getAllByTestId('entityBulkEditFileInfoBody').length
            ).toBeGreaterThan(0);
        });
    });

    it('passes expected partial props to EntityBulkEditProcessingStatus', async () => {
        renderComponent(props);

        await waitFor(() => {
            expect(EntityBulkEditProcessingStatus).toHaveBeenCalled();

            const calls = (EntityBulkEditProcessingStatus as jest.Mock).mock
                .calls;
            const lastCallProps = calls[calls.length - 1][0];

            expect(lastCallProps).toEqual(
                expect.objectContaining({
                    success: [],
                    failed: [],
                    all: expect.arrayContaining([
                        expect.objectContaining({
                            contractTermId: '1234567890',
                        }),
                    ]),
                })
            );
        });
    });

    it('passes expected props to EntityBulkEditTable', async () => {
        renderComponent(props);

        await waitFor(() => {
            const calls = (EntityBulkEditTable as jest.Mock).mock.calls;
            expect(calls.length).toBeGreaterThan(0);

            const lastCallProps = calls[calls.length - 1][0];
            expect(lastCallProps).toEqual(
                expect.objectContaining({
                    bulkEditEntriesList: expect.arrayContaining([
                        expect.objectContaining({
                            contractTermId: '1234567890',
                        }),
                    ]),
                    entityName: 'Contract Terms',
                    isLoading: false,
                    page: 0,
                    pageSize: 20,
                })
            );
        });
    });
});
