/**
 * Tests for LassoGeometryToolbarUI — type toggle, rename popover (Enter/blur
 * commit, no-op on empty/unchanged), lock toggle, delete, and the locked
 * read-only behavior (every action but unlock disabled).
 */
import { describe, it, expect, vi } from 'vitest'
import { render, fireEvent, screen } from '@testing-library/react'
import { LassoGeometryToolbarUI } from './geometry-toolbar'

function setup(
  props: Partial<Parameters<typeof LassoGeometryToolbarUI>[0]> = {},
) {
  const handlers = {
    onToggleType: vi.fn(),
    onRename: vi.fn(),
    onToggleLock: vi.fn(),
    onDelete: vi.fn(),
  }
  render(
    <LassoGeometryToolbarUI
      type='mask'
      label='Mask 1'
      {...handlers}
      {...props}
    />,
  )
  return handlers
}

describe('LassoGeometryToolbarUI', () => {
  it('toggles mask -> draw', () => {
    const { onToggleType } = setup({ type: 'mask' })
    fireEvent.click(screen.getByRole('button', { name: 'Switch to drawing' }))
    expect(onToggleType).toHaveBeenCalledWith('draw')
  })

  it('toggles draw -> mask', () => {
    const { onToggleType } = setup({ type: 'draw' })
    fireEvent.click(screen.getByRole('button', { name: 'Switch to mask' }))
    expect(onToggleType).toHaveBeenCalledWith('mask')
  })

  it('marks the mask button pressed when type is mask', () => {
    setup({ type: 'mask' })
    expect(
      screen
        .getByRole('button', { name: 'Switch to drawing' })
        .getAttribute('aria-pressed'),
    ).toBe('true')
  })

  it('marks the mask button not-pressed when type is draw', () => {
    setup({ type: 'draw' })
    expect(
      screen
        .getByRole('button', { name: 'Switch to mask' })
        .getAttribute('aria-pressed'),
    ).toBe('false')
  })

  it('marks the lock button pressed when locked', () => {
    setup({ locked: true })
    expect(
      screen
        .getByRole('button', { name: 'Unlock' })
        .getAttribute('aria-pressed'),
    ).toBe('true')
  })

  it('commits a new label on Enter', () => {
    const { onRename } = setup({ label: 'Mask 1' })
    fireEvent.click(screen.getByRole('button', { name: 'Rename' }))
    const input = screen.getByRole('textbox')
    fireEvent.change(input, { target: { value: 'Downtown' } })
    fireEvent.keyDown(input, { key: 'Enter' })
    expect(onRename).toHaveBeenCalledWith('Downtown')
  })

  it('does not call onRename when the label is unchanged', () => {
    const { onRename } = setup({ label: 'Mask 1' })
    fireEvent.click(screen.getByRole('button', { name: 'Rename' }))
    const input = screen.getByRole('textbox')
    fireEvent.keyDown(input, { key: 'Enter' })
    expect(onRename).not.toHaveBeenCalled()
  })

  it('commits the rename only once (blur after Enter does not double-fire)', () => {
    const { onRename } = setup({ label: 'Mask 1' })
    fireEvent.click(screen.getByRole('button', { name: 'Rename' }))
    const input = screen.getByRole('textbox')
    fireEvent.change(input, { target: { value: 'Downtown' } })
    fireEvent.keyDown(input, { key: 'Enter' })
    fireEvent.blur(input)
    expect(onRename).toHaveBeenCalledTimes(1)
  })

  it('discards the rename on Escape (does not call onRename)', () => {
    const { onRename } = setup({ label: 'Mask 1' })
    fireEvent.click(screen.getByRole('button', { name: 'Rename' }))
    const input = screen.getByRole('textbox')
    fireEvent.change(input, { target: { value: 'Downtown' } })
    fireEvent.keyDown(input, { key: 'Escape' })
    fireEvent.blur(input)
    expect(onRename).not.toHaveBeenCalled()
  })

  it('locks an unlocked geometry', () => {
    const { onToggleLock } = setup({ locked: false })
    fireEvent.click(screen.getByRole('button', { name: 'Lock' }))
    expect(onToggleLock).toHaveBeenCalledWith(true)
  })

  it('unlocks a locked geometry', () => {
    const { onToggleLock } = setup({ locked: true })
    fireEvent.click(screen.getByRole('button', { name: 'Unlock' }))
    expect(onToggleLock).toHaveBeenCalledWith(false)
  })

  it('deletes the geometry', () => {
    const { onDelete } = setup()
    fireEvent.click(screen.getByRole('button', { name: 'Delete' }))
    expect(onDelete).toHaveBeenCalledTimes(1)
  })

  it('disables every action but unlock when locked', () => {
    const handlers = setup({ locked: true })
    const disabled = (name: string) =>
      screen.getByRole('button', { name }).hasAttribute('disabled')
    expect(disabled('Switch to drawing')).toBe(true)
    expect(disabled('Rename')).toBe(true)
    expect(disabled('Delete')).toBe(true)
    // Unlock stays enabled.
    const unlock = screen.getByRole('button', { name: 'Unlock' })
    expect(unlock.hasAttribute('disabled')).toBe(false)
    fireEvent.click(unlock)
    expect(handlers.onToggleLock).toHaveBeenCalledWith(false)
  })
})
