import React, { createRef } from 'react';
import { renderHook } from '@testing-library/react';
import { TestData } from 'lib/test-utils/table';
import { TableProps } from '../../types';
import { useTableApi } from '../index';

describe('useTableApi', () => {
    const wrapperRef = createRef() as React.MutableRefObject<HTMLDivElement | null>;

    beforeEach(() => {
        wrapperRef.current = null;
    });

    test('returns api object from table props', () => {
        const props: TableProps<TestData> = {
            data: [],
        };

        const result = renderHook(() => useTableApi(props, wrapperRef));

        expect(result.result.current).toMatchInlineSnapshot(`
          {
            "columns": [],
            "initialProps": {
              "columnDefs": [],
              "data": [],
              "name": "table",
            },
            "layoutInfo": {
              "overflowX": 0,
              "overflowed": false,
              "overflowing": false,
            },
            "props": {
              "columnDefs": [],
              "data": [],
              "name": "table",
            },
            "refresh": [Function],
            "rows": [],
            "setRowFlags": [Function],
            "setSortedColumn": [Function],
            "toggleTableClassName": [Function],
            "visibleColumns": [],
            "wrapperRef": {
              "current": null,
            },
          }
        `);
    });

    const row1 = { name: 'test', value: 1 };
    const row2 = { key: 'r2', name: 'test2', value: 2 };
    const colDef1 = { name: 'name' };
    const colDef2 = { name: 'value' };

    describe.each([
        ['no column defs', {}],
        ['columnDefs', { columnDefs: [colDef1, colDef2] }],
        [
            'react children',
            {
                children: [
                    React.createElement('div', colDef1),
                    React.createElement('div', colDef2),
                ],
            },
        ],
    ])('with "%s"', (_, defs) => {
        test('returns column and row instances', () => {
            const props: TableProps<TestData> = {
                data: [row1, row2],
                ...defs,
            };

            const result = renderHook(() => useTableApi(props, wrapperRef));

            const { columns, rows } = result.result.current;

            expect(columns).toEqual([
                {
                    index: 0,
                    definition: colDef1,
                    sortConfig: undefined,
                    hasSeparator: true,
                    display: 'visible',
                },
                {
                    index: 1,
                    definition: colDef2,
                    sortConfig: undefined,
                    hasSeparator: true,
                    display: 'visible',
                },
            ]);

            expect(rows).toEqual([
                {
                    index: 1,
                    data: row1,
                    key: 'test_1',
                    expandedContent: undefined,
                    isClickable: false,
                },
                {
                    index: 2,
                    data: row2,
                    key: row2.key,
                    expandedContent: undefined,
                    isClickable: false,
                },
            ]);
        });
    });

    describe('visibleColumns', () => {
        test('only includes columns that should be shown', () => {
            const props: TableProps<TestData> = {
                data: [row1, row2],
                columnDefs: [
                    colDef1,
                    { name: 'hidden', visibility: 'hidden' },
                    { name: 'hidden', visibility: 'collapse' },
                    colDef2,
                ],
            };

            const {
                result: {
                    current: { visibleColumns },
                },
            } = renderHook(() => useTableApi(props, wrapperRef));

            expect(visibleColumns).toEqual([
                {
                    index: 0,
                    definition: colDef1,
                    sortConfig: undefined,
                    hasSeparator: false,
                    display: 'visible',
                },
                {
                    index: 3,
                    definition: colDef2,
                    sortConfig: undefined,
                    hasSeparator: true,
                    display: 'visible',
                },
            ]);
        });
    });

    describe('toggleTableClassName', () => {
        test('adds / removes class names on the wrapper element', () => {
            const className = 'test-class';
            const wrapperElement = document.createElement('div');
            const classList = wrapperElement.classList;
            wrapperRef.current = wrapperElement;

            const {
                result: { current: result },
            } = renderHook(() => useTableApi({}, wrapperRef));

            result.toggleTableClassName(className, true);

            expect(classList.contains(className)).toEqual(true);

            result.toggleTableClassName(className, false);

            expect(classList.contains(className)).toEqual(false);
        });
    });
});
