import { afterEach, describe, expect, test } from 'bun:test'
import {
  hasPermissionCallback,
  processMailboxPermissionResponse,
  registerPermissionCallback,
  clearAllPendingCallbacks,
  unregisterPermissionCallback,
} from '../../hooks/useSwarmPermissionPoller.js'

afterEach(() => {
  clearAllPendingCallbacks()
})

describe('swarm permission poller registry', () => {
  test('register and unregister callback', () => {
    registerPermissionCallback({
      requestId: 'req-1',
      toolUseId: 'tool-1',
      onAllow: () => {},
      onReject: () => {},
    })
    expect(hasPermissionCallback('req-1')).toBe(true)
    unregisterPermissionCallback('req-1')
    expect(hasPermissionCallback('req-1')).toBe(false)
  })

  test('processMailboxPermissionResponse removes callback on approve', () => {
    let approved = false
    registerPermissionCallback({
      requestId: 'req-2',
      toolUseId: 'tool-2',
      onAllow: () => {
        approved = true
      },
      onReject: () => {},
    })
    const result = processMailboxPermissionResponse({
      requestId: 'req-2',
      decision: 'approved',
    })
    expect(result).toBe(true)
    expect(approved).toBe(true)
    // Callback is removed after processing
    expect(hasPermissionCallback('req-2')).toBe(false)
  })

  test('processMailboxPermissionResponse removes callback on reject', () => {
    let rejected = false
    registerPermissionCallback({
      requestId: 'req-3',
      toolUseId: 'tool-3',
      onAllow: () => {},
      onReject: () => {
        rejected = true
      },
    })
    const result = processMailboxPermissionResponse({
      requestId: 'req-3',
      decision: 'rejected',
      feedback: 'denied',
    })
    expect(result).toBe(true)
    expect(rejected).toBe(true)
    expect(hasPermissionCallback('req-3')).toBe(false)
  })

  test('processMailboxPermissionResponse returns false for unknown request', () => {
    const result = processMailboxPermissionResponse({
      requestId: 'unknown',
      decision: 'approved',
    })
    expect(result).toBe(false)
  })

  test('resetPermissionCallbacks clears all callbacks', () => {
    registerPermissionCallback({
      requestId: 'req-a',
      toolUseId: 'tool-a',
      onAllow: () => {},
      onReject: () => {},
    })
    registerPermissionCallback({
      requestId: 'req-b',
      toolUseId: 'tool-b',
      onAllow: () => {},
      onReject: () => {},
    })
    clearAllPendingCallbacks()
    expect(hasPermissionCallback('req-a')).toBe(false)
    expect(hasPermissionCallback('req-b')).toBe(false)
  })

  test('callback is removed BEFORE invoking handler (prevents re-entrant leak)', () => {
    const order: string[] = []
    registerPermissionCallback({
      requestId: 'req-order',
      toolUseId: 'tool-order',
      onAllow: () => {
        // During callback execution, the callback should already be removed
        order.push('callback')
        order.push(`has:${hasPermissionCallback('req-order')}`)
      },
      onReject: () => {},
    })
    processMailboxPermissionResponse({
      requestId: 'req-order',
      decision: 'approved',
    })
    expect(order).toEqual(['callback', 'has:false'])
  })
})
