import React from 'react';
import { fireEvent, 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 { TableSelectionExtension } from '../tableSelectionExtension';

TableExtensions.addExtension(TableSelectionExtension);

describe('TableSelectionExtension', () => {
    const row1 = { name: 'test1', value: 1 };
    const row2 = { name: 'test2', value: 2 };

    const data: TestData[] = [row1, row2];

    const renderTable = (props: Partial<TableProps<TestData>> = {}) =>
        render(<GridTable rowKey="name" data={data} {...props} />);

    describe('with "selectable" true', () => {
        test('renders checkboxes', () => {
            const { getAllByRole } = renderTable({
                selectable: true,
            });

            const checkboxes = getAllByRole('checkbox');
            expect(checkboxes).toHaveLength(data.length + 1);
        });

        test('marks rows when selected', () => {
            const { getAllByRole } = renderTable({
                selectable: true,
            });

            const [, checkbox] = getAllByRole('checkbox');

            const row = checkbox.parentElement?.parentElement?.parentElement;

            expect(row).not.toHaveClass('selected');

            fireEvent.click(checkbox);

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

        test('adds table "table-selection-row-highlight" class', () => {
            const { getByTestId } = renderTable({
                selectable: true,
            });

            const table = getByTestId('GridTable');
            expect(table).toHaveClass('table-selection-row-highlight');
        });

        describe('with "highlightSelectedRows" false', () => {
            test('does not add table "table-selection-row-highlight" class', () => {
                const { getByTestId } = renderTable({
                    selectable: true,
                    highlightSelectedRows: false,
                });

                const table = getByTestId('GridTable');
                expect(table).not.toHaveClass('table-selection-row-highlight');
            });
        });
    });

    describe('with "selectable" false', () => {
        test('does not render checkboxes', () => {
            const { queryAllByRole } = renderTable({
                selectable: false,
            });

            const checkboxes = queryAllByRole('checkbox');
            expect(checkboxes).toHaveLength(0);
        });
    });

    describe('with "showSelectOnlyLinks" true', () => {
        test('renders "Only" buttons in the main column cells', () => {
            const { getAllByText } = renderTable({
                selectable: true,
                showSelectOnlyLinks: true,
            });

            const buttons = getAllByText(formatMessage('table_only'));

            expect(buttons).toHaveLength(data.length);
        });

        test('checks single row when "Only" button is clicked', () => {
            const { getAllByText, getAllByRole } = renderTable({
                selectable: true,
                showSelectOnlyLinks: true,
                selectedRowKeys: [row1.name, row2.name],
            });

            const [mainCheckbox, firstRowCheckbox, secondRowCheckbox] = getAllByRole('checkbox');

            const [firstRowOnlyButton] = getAllByText(formatMessage('table_only'));

            const row = firstRowOnlyButton.parentElement?.parentElement?.parentElement;

            expect(row).toHaveClass('selected');
            expect(mainCheckbox).toBeChecked();
            expect(mainCheckbox).not.toBePartiallyChecked();
            expect(firstRowCheckbox).toBeChecked();
            expect(secondRowCheckbox).toBeChecked();

            fireEvent.click(firstRowOnlyButton);

            expect(row).toHaveClass('selected');
            expect(mainCheckbox).not.toBeChecked();
            expect(mainCheckbox).toBePartiallyChecked();
            expect(firstRowCheckbox).toBeChecked();
            expect(secondRowCheckbox).not.toBeChecked();
        });

        test('makes main column sticky', () => {
            const { getByText } = renderTable({
                selectable: true,
                showSelectOnlyLinks: true,
            });

            const mainCell = getByText(row1.name).parentElement?.parentElement;
            expect(mainCell).toHaveClass('fixed');
            expect(mainCell).toHaveStyle('left:36px');
        });
    });

    describe('with "showSelectOnlyLinks" false', () => {
        test('does not render "Only" buttons in the main column cells', () => {
            const { queryAllByText } = renderTable({
                selectable: true,
                showSelectOnlyLinks: false,
            });

            const buttons = queryAllByText(formatMessage('table_only'));

            expect(buttons).toHaveLength(0);
        });
    });

    describe('with "loading" true', () => {
        test('renders SkeletonLoader', () => {
            const { container, getAllByTestId } = renderTable({
                selectable: true,
                loading: true,
                columnDefs: [
                    {
                        name: 'test',
                    },
                ],
                data: [],
                loadingRows: 5,
            });

            const loaders = getAllByTestId('SkeletonLoader');
            expect(loaders).toHaveLength(12);

            expect(container.getElementsByClassName('SkeletonLoader-square')).toHaveLength(6);
        });
    });
});
