import React from 'react';
import { screen, render } from '@testing-library/react';
import { GridTable } from '../../../base/table';
import { TableExtensions } from '../../../base/tableExtensions';
import { TableProps } from '../../../base/types';
import { TableColumnSpanExtension } from '../tableColumnSpanExtension';

TableExtensions.addExtension(TableColumnSpanExtension);

interface Data {
    id: string;
    group: number;
    name: string;
    value: string;
    num: number;
}

describe('tableColumnSpanExtension', () => {
    const data: Data[] = [
        { id: 'a', group: 1, name: 'group1a', value: 'a', num: 1 },
        { id: 'b', group: 1, name: 'group1b', value: 'c', num: 1 },
        { id: 'c', group: 2, name: 'group2a', value: 'b', num: 1 },
        { id: 'd', group: 2, name: 'group2b', value: 'e', num: 2 },
        { id: 'e', group: 3, name: 'group3a', value: 'd', num: 2 },
    ];

    const defaultProps: TableProps<Data> = {
        columnDefs: [{ name: 'name' }, { name: 'value' }, { name: 'num' }],
        data,
    };

    const renderTable = (props: Partial<TableProps<Data>> = {}) =>
        render(<GridTable {...defaultProps} {...props} />);

    test('correctly spans column across adjacent rows', () => {
        renderTable({
            columnSpan: {
                spanKey: (data) => data.group,
                columns: ['name'],
            },
        });

        expect(screen.getByText('group1a')).toBeVisible();
        expect(screen.queryByText('group1b')).toBeNull();
        expect(screen.getByText('group2a')).toBeVisible();
        expect(screen.queryByText('group2b')).toBeNull();
        expect(screen.getByText('group3a')).toBeVisible();

        expect(screen.getAllByText('1')).toHaveLength(3);
        expect(screen.getAllByText('2')).toHaveLength(2);
    });

    test('can span multiple columns', () => {
        renderTable({
            columnSpan: {
                spanKey: (data) => data.group,
                columns: ['name', 'num'],
            },
        });

        expect(screen.getByText('group1a')).toBeVisible();
        expect(screen.queryByText('group1b')).toBeNull();
        expect(screen.getByText('group2a')).toBeVisible();
        expect(screen.queryByText('group2b')).toBeNull();
        expect(screen.getByText('group3a')).toBeVisible();

        expect(screen.getAllByText('1')).toHaveLength(2);
        expect(screen.getAllByText('2')).toHaveLength(1);
    });

    test('does not span columns if spanned keys are not adjacent', () => {
        renderTable({
            columnSpan: {
                spanKey: (data) => data.group,
                columns: ['name'],
            },
            sortBy: { direction: 'desc', key: 'value' },
        });

        expect(screen.getByText('group1a')).toBeVisible();
        expect(screen.getByText('group1b')).toBeVisible();
        expect(screen.getByText('group2a')).toBeVisible();
        expect(screen.getByText('group2b')).toBeVisible();
        expect(screen.getByText('group3a')).toBeVisible();
    });

    test('does nothing if there are no rows', () => {
        expect(() =>
            renderTable({
                columnSpan: {
                    spanKey: (data) => data.group,
                    columns: ['name'],
                },
                data: [],
            })
        ).not.toThrow();
    });
});
