import React from 'react'
import { render } from '../../utils/test-utils'
import type { GridEditorComboboxTreeProps } from './single'
import { GridEditorComboboxTree } from './single'
import type { ComboboxTreeOption } from '@planview/pv-uikit'
import type { UseGridReturn } from '../../hooks'
import { createGrid } from '../../hooks'
import { GridProvider } from '../../context/grid-context'
import userEvent from '@testing-library/user-event'

const options: ComboboxTreeOption[] = [
    {
        value: 1,
        label: 'One',
    },
    {
        value: 2,
        label: 'Two',
    },
    {
        value: 3,
        label: 'Three',
    },
    {
        value: 4,
        label: 'Four',
    },
]

const baseProps = {
    rowId: '1',
    mode: 'editing' as GridEditorComboboxTreeProps<any>['mode'],
    tabIndex: 0,
    label: '',
    value: { value: 1, label: 'One' },
    columnId: 'name',
}

describe('GridEditorCombobox', () => {
    let onConfirm: jest.Mock
    let onCancel: jest.Mock
    let grid: UseGridReturn

    beforeEach(() => {
        onConfirm = jest.fn()
        onCancel = jest.fn()
        grid = createGrid()
    })

    function renderEditor(
        props: Partial<GridEditorComboboxTreeProps<any>> = {}
    ) {
        return render(
            <GridProvider {...grid}>
                <GridEditorComboboxTree
                    {...baseProps}
                    onCancel={onCancel}
                    onConfirm={onConfirm}
                    options={options}
                    {...props}
                />
            </GridProvider>
        )
    }

    it('should render', async () => {
        const { findByRole } = renderEditor()
        expect(await findByRole('combobox')).toBeInTheDocument()
    })

    it('should support editing (continue with Tab)', async () => {
        renderEditor()

        await userEvent.keyboard('{Tab}2{Tab}')

        expect(onConfirm).toHaveBeenCalledWith(
            { value: 1, label: 'One' },
            {
                continueEditing: 'next',
            }
        )
    })

    it('should support editing (continue with Shift+Tab)', async () => {
        renderEditor()

        await userEvent.keyboard('{Tab}2{Shift>}{Tab}{/Shift}')

        expect(onConfirm).toHaveBeenCalledWith(
            { value: 1, label: 'One' },
            {
                continueEditing: 'previous',
            }
        )
    })

    it('should support editing (selection of item)', async () => {
        const { findByRole } = renderEditor()

        await userEvent.keyboard('{Tab}')

        await userEvent.click(await findByRole('treeitem', { name: 'Two' }))

        expect(onConfirm).toHaveBeenCalledWith({ value: 2, label: 'Two' })
    })

    it('should support cancelling an edit with Esc', async () => {
        renderEditor()

        await userEvent.keyboard('{Tab}2{Escape}')

        expect(onConfirm).not.toHaveBeenCalled()
        expect(onCancel).toHaveBeenCalled()
    })
})
