import React from 'react';
import { render, RenderResult } from '@testing-library/react';
import { getVisibleColumns } from '../../src/components/table/base/api/columns';
import { TableContext } from '../../src/components/table/base/context';
import {
    ColumnInstance,
    RowInstance,
    TableApi,
    TableProps,
} from '../../src/components/table/base/types';

export interface TestData {
    value?: string | number | boolean | object | null;
    name?: string;
}

export const createColumnInstance = (
    column: Partial<ColumnInstance<TestData>> = {}
): ColumnInstance<TestData> => ({
    index: 0,
    sortConfig: undefined,
    definition: { name: 'name', maxWidth: '200px' },
    display: 'visible',
    ...column,
});

export const createRowInstance = (
    row: Partial<RowInstance<TestData>> = {}
): RowInstance<TestData> => ({
    index: 1,
    key: 'test1',
    Content: undefined,
    isClickable: false,
    data: { value: 'test1' },
    flags: {},
    ...row,
});

export const createTableApi = (
    api: Partial<TableApi<TestData>> = {},
    props: Partial<TableProps<TestData>> = {}
): TableApi<TestData> => ({
    rows: [],
    setSortedColumn: vi.fn(),
    columns: [],
    visibleColumns:
        api.visibleColumns ?? getVisibleColumns(api.columns ?? [], props.hideColumnSeparators),
    layoutInfo: { overflowing: false, overflowed: false, overflowX: 0 },
    setRowFlags: vi.fn(),
    refresh: vi.fn(),
    toggleTableClassName: vi.fn(),
    props: { name: 'table', data: [], columnDefs: [], ...props },
    initialProps: { name: 'table', data: [], columnDefs: [], ...props },
    wrapperRef: React.createRef(),
    ...api,
});

export type PartialTableProps = Partial<TableProps<TestData>>;

export type PartialTableContext = Omit<Partial<TableApi<TestData>>, 'props'> & {
    props?: PartialTableProps;
};

export const createTableContextWrapper = (context: PartialTableContext = {}) => {
    const api = createTableApi();

    return ({ children }: { children: React.ReactNode }) => (
        <TableContext.Provider
            value={{
                ...api,
                ...context,
                visibleColumns:
                    context.visibleColumns ??
                    getVisibleColumns(context.columns ?? [], context.props?.hideColumnSeparators),
                props: {
                    ...api.props,
                    ...context.props,
                },
            }}
        >
            {children}
        </TableContext.Provider>
    );
};

export const renderInTableContext = (
    Component: React.ComponentType,
    context: PartialTableContext = {}
): RenderResult =>
    render(<Component />, {
        wrapper: createTableContextWrapper(context),
    });

export const createTableRenderFunction =
    (Component: React.ComponentType, defaultContext: PartialTableContext = {}) =>
    (context: PartialTableContext = {}): RenderResult =>
        renderInTableContext(Component, {
            ...defaultContext,
            ...context,
            props: {
                ...defaultContext.props,
                ...context.props,
            },
        });
