import { afterEach, describe, expect, it, vi } from 'vitest'
import { createDebouncedAsyncTask } from '../src/dimsdk/cli/utils/debounce.ts'

afterEach(() => {
  vi.useRealTimers()
})

describe('debounced async task', () => {
  it('coalesces repeated schedules into one delayed run', async () => {
    vi.useFakeTimers()

    const task = vi.fn(async () => {})
    const debounced = createDebouncedAsyncTask(task, 40)

    debounced.schedule()
    debounced.schedule()
    debounced.schedule()

    await vi.advanceTimersByTimeAsync(39)
    expect(task).not.toHaveBeenCalled()

    await vi.advanceTimersByTimeAsync(1)
    expect(task).toHaveBeenCalledTimes(1)
  })

  it('queues one follow-up run when rescheduled during execution', async () => {
    vi.useFakeTimers()

    let firstRunRelease: (() => void) | null = null
    let callCount = 0
    const task = vi.fn(async () => {
      callCount += 1
      if (callCount !== 1)
        return
      await new Promise<void>((resolve) => {
        firstRunRelease = resolve
      })
    })
    const debounced = createDebouncedAsyncTask(task, 25)

    debounced.schedule()
    await vi.advanceTimersByTimeAsync(25)
    expect(task).toHaveBeenCalledTimes(1)

    debounced.schedule()
    debounced.schedule()
    firstRunRelease?.()
    await Promise.resolve()
    await vi.advanceTimersByTimeAsync(25)

    expect(task).toHaveBeenCalledTimes(2)
  })
})
