import { fireEvent, render, screen } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import { ActionsMenu } from './ActionsMenu'

function renderMenu() {
  const inspect = vi.fn()
  const abandon = vi.fn()
  render(
    <div>
      <ActionsMenu
        items={[
          { label: 'Inspect gate log', onSelect: inspect },
          {
            label: 'Abandon (soft delete)',
            onSelect: abandon,
            tone: 'danger',
            dividerAbove: true,
            icon: <svg aria-hidden="true" style={{ width: 96, height: 96 }} />,
          },
        ]}
      />
      <button type="button">Outside</button>
    </div>,
  )
  return { inspect, abandon }
}

describe('ActionsMenu', () => {
  it('opens the menu, renders a divider, selects an item, and closes', async () => {
    const { abandon, inspect } = renderMenu()
    const trigger = screen.getByRole('button', { name: 'Actions' })

    fireEvent.click(trigger)

    const items = screen.getAllByRole('menuitem')
    expect(items).toHaveLength(2)
    expect(items[0]).toHaveTextContent('Inspect gate log')
    expect(items[1]).toHaveTextContent('Abandon (soft delete)')
    expect(screen.getByRole('separator')).toBeInTheDocument()

    fireEvent.click(items[0]!)
    expect(inspect).toHaveBeenCalledTimes(1)
    expect(screen.queryByRole('menu')).not.toBeInTheDocument()

    // astryx guards re-open clicks within 50ms of a close (iOS light-dismiss
    // protection); allow the guard window to expire before re-opening.
    await new Promise((resolve) => setTimeout(resolve, 60))
    fireEvent.click(trigger)
    fireEvent.click(screen.getByRole('menuitem', { name: 'Abandon (soft delete)' }))
    expect(abandon).toHaveBeenCalledTimes(1)
    expect(screen.queryByRole('menu')).not.toBeInTheDocument()
  })

  it('supports an accessible icon trigger', () => {
    render(
      <ActionsMenu
        label="Incident tools"
        triggerIcon={<svg data-testid="tools-icon" aria-hidden="true" />}
        items={[{ label: 'Stop work', onSelect: vi.fn() }]}
      />,
    )

    const trigger = screen.getByRole('button', { name: 'Incident tools' })
    expect(screen.getByTestId('tools-icon')).toBeInTheDocument()
    expect(trigger).not.toHaveTextContent('Incident tools')
  })

  it('closes on Escape and outside pointer interaction', () => {
    renderMenu()
    const trigger = screen.getByRole('button', { name: 'Actions' })

    fireEvent.click(trigger)
    fireEvent.keyDown(screen.getByRole('menu'), { key: 'Escape' })
    expect(screen.queryByRole('menu')).not.toBeInTheDocument()
    expect(trigger).toHaveFocus()

    fireEvent.click(trigger)
    fireEvent.pointerDown(screen.getByRole('button', { name: 'Outside' }))
    expect(screen.queryByRole('menu')).not.toBeInTheDocument()
  })
})