import React from 'react';
import { render } from '@testing-library/react';
import { formatMessage } from '@theorchard/suite-i18n';
import { TestData } from 'lib/test-utils/table';
import { GridTable } from '../../../base/table';
import { TableExtensions } from '../../../base/tableExtensions';
import { TableProps } from '../../../base/types';
import { TableTotalsRowExtension } from '../tableTotalsRowExtension';

TableExtensions.addExtension(TableTotalsRowExtension);

describe('TableTotalRowExtension', () => {
    const data: TestData[] = [
        { name: 'row-1', value: 1 },
        { name: 'row-2', value: 2 },
        { name: 'row-3', value: 3 },
        { name: 'row-4', value: 4 },
    ];

    const defaultProps = {
        rowKey: 'name',
        data,
        columnDefs: [{ name: 'name' }, { name: 'value' }, { name: 'text' }],
        showTotals: true,
    };

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

    test('renders total row', () => {
        const { getAllByText } = renderTable();

        const totalCells = getAllByText(formatMessage('table_total'));

        expect(totalCells).toHaveLength(1);

        const [cell] = totalCells;

        const row = cell.closest('.GridTable-row');

        expect(row).toHaveClass('totals');
    });

    test('does not render custom Cells for totals', () => {
        const { queryByText } = renderTable({
            columnDefs: [
                { name: 'name' },
                {
                    name: 'value',
                    Cell: (data) => <div>custom: {data.value}</div>,
                },
                { name: 'text' },
            ],
        });

        expect(queryByText('custom: 10')).toBeNull();
    });

    test('renders total cell in the first column', () => {
        const { getAllByText } = renderTable();

        const totalCells = getAllByText(formatMessage('table_total'));
        const [cellText] = totalCells;

        const cell = cellText.closest('.GridTable-cell');
        const row = cell?.closest('.GridTable-row');

        expect(row?.children[0]).toBe(cell);
        expect(cell).toHaveClass('col-totals-title');
        expect(row?.children[1]).not.toHaveClass('col-totals-title');
    });

    test('renders computed totals', () => {
        const { getAllByText } = renderTable();

        const [totalCell] = getAllByText(formatMessage('table_total'));
        const row = totalCell.closest('.GridTable-row') as HTMLDivElement;

        const valueCell = row.querySelector('.cell-value');
        const textCell = row.querySelector('.cell-text');

        expect(valueCell).toHaveTextContent('10');
        expect(textCell).toHaveTextContent('');
    });

    describe('if the first column name is "table-selection"', () => {
        test('renders total cell in the second column', () => {
            const { getAllByText } = renderTable({
                columnDefs: [{ name: 'table-selection' }, ...defaultProps.columnDefs],
            });

            const totalCells = getAllByText(formatMessage('table_total'));
            const [cellText] = totalCells;

            const cell = cellText.closest('.GridTable-cell');
            const row = cell?.closest('.GridTable-row');

            expect(cell).toHaveClass('col-totals-title');
            expect(row?.children[1]).toBe(cell);
            expect(row?.children[0]).not.toHaveClass('col-totals-title');
        });
    });

    describe('with "customTotals"', () => {
        test('renders custom totals', () => {
            const { container } = renderTable({
                customTotals: {
                    name: 'My totals',
                    value: '11B',
                },
            });

            expect(container.querySelector('.GridTable-row.totals')).toMatchSnapshot();
        });
    });

    describe('with "TotalCell" in column defs', () => {
        test('renders defined cells', () => {
            const { getByText } = renderTable({
                columnDefs: [
                    { name: 'name' },
                    {
                        name: 'value',
                        TotalCell: (data) => <div>custom: {data.value}</div>,
                    },
                    { name: 'text' },
                ],
            });

            expect(getByText('custom: 10')).toBeInTheDocument();
        });
    });

    describe('with "totalsPosition" set to "sticky-top"', () => {
        test('renders sticky total row', () => {
            const { getAllByText } = renderTable({
                totalsPlacement: 'sticky-top',
            });

            const totalCells = getAllByText(formatMessage('table_total'));

            expect(totalCells).toHaveLength(2);

            const [cell1, cell2] = totalCells;

            const stickyRow = cell1.closest('.GridTable-row');
            const fixedRow = cell2.closest('.GridTable-row');

            expect(stickyRow).toHaveClass('totals sticky');
            expect(fixedRow).toHaveClass('totals fixed');
        });
    });
});
