import React, { useEffect } from 'react'
import { ToolbarItemBridge } from './item-bridge'
import { NavigationBar } from '../navigation-bar'
import { render } from '../__utils/test-utils'
import { LogoProjectPlace } from '../logos'
import { ToolbarSectionLeft } from '../section'
import { ToolbarButtonEmpty } from '../button'
import userEvent from '@testing-library/user-event'

function renderWithNavigationBar(component: React.ReactElement) {
    return render(component, {
        wrapper({ children }) {
            return (
                <NavigationBar logo={<LogoProjectPlace url="/" />}>
                    <ToolbarSectionLeft>
                        {children}
                        <ToolbarButtonEmpty>Sample button</ToolbarButtonEmpty>
                    </ToolbarSectionLeft>
                </NavigationBar>
            )
        },
    })
}

function ToolbarItemBridgeWithRefButton() {
    const ref = React.useRef<HTMLDivElement>(null)

    useEffect(() => {
        if (ref.current) {
            const button = document.createElement('button')
            button.tabIndex = -1
            button.innerHTML = 'Notifications'
            ref.current.appendChild(button)
        }
    })

    return <ToolbarItemBridge ref={ref} />
}

function ToolbarItemBridgeWithNestedButton() {
    return (
        <ToolbarItemBridge>
            <button tabIndex={-1}>Notifications</button>
        </ToolbarItemBridge>
    )
}

describe('ToolbarItemBridge', () => {
    describe.each([
        ['When using ref', ToolbarItemBridgeWithRefButton],
        ['When using nested button', ToolbarItemBridgeWithNestedButton],
    ])('%s', (_, Component) => {
        it('should participate in keyboard navigation one event is received', async () => {
            const { getByRole } = renderWithNavigationBar(<Component />)

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

            expect(getByRole('button', { name: 'Sample button' })).toHaveFocus()

            await userEvent.keyboard('{ArrowLeft}')

            expect(getByRole('button', { name: 'Notifications' })).toHaveFocus()
        })

        it('should focus the button when the div is focused', async () => {
            const { getByRole } = renderWithNavigationBar(<Component />)

            /* Due to how react-roving-tabindex works, it will be focusable but not the first item */
            const wrapperDiv = getByRole('button', {
                name: 'Notifications',
            }).parentElement!

            await userEvent.click(wrapperDiv)

            expect(getByRole('button', { name: 'Notifications' })).toHaveFocus()
        })
    })
})
