import { afterEach, describe, expect, it, vi } from 'vitest'
import {
  createUpgradeMessageReporter,
  resolveBackgroundUpgradeCheckIntervalMs,
  startBackgroundUpgradeChecks,
} from '../src/dimsdk/cli/upgrade-loop.ts'

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

describe('upgrade loop helpers', () => {
  it('normalizes the background interval env with clamp and disable semantics', () => {
    expect(resolveBackgroundUpgradeCheckIntervalMs({})).toBe(60 * 60 * 1000)
    expect(
      resolveBackgroundUpgradeCheckIntervalMs({
        DIMCODE_UPGRADE_CHECK_INTERVAL_MS: '1500',
      }),
    ).toBe(60 * 1000)
    expect(
      resolveBackgroundUpgradeCheckIntervalMs({
        DIMCODE_UPGRADE_CHECK_INTERVAL_MS: '0',
      }),
    ).toBe(0)
  })

  it('dedupes upgrade messages after trimming', () => {
    const notify = vi.fn()
    const report = createUpgradeMessageReporter(notify)

    report('  New version available  ')
    report('New version available')
    report('')

    expect(notify).toHaveBeenCalledTimes(1)
    expect(notify).toHaveBeenCalledWith('New version available')
  })

  it('avoids overlapping checks and stops polling after cleanup', async () => {
    vi.useFakeTimers()

    let resolveCheck: ((value: string | null) => void) | null = null
    const checkUpgrade = vi.fn(
      () =>
        new Promise<string | null>((resolve) => {
          resolveCheck = resolve
        }),
    )
    const onMessage = vi.fn()

    const stop = startBackgroundUpgradeChecks({
      intervalMs: 1000,
      checkUpgrade,
      onMessage,
    })

    await vi.advanceTimersByTimeAsync(4000)
    expect(checkUpgrade).toHaveBeenCalledTimes(1)

    resolveCheck?.('Upgrade ready')
    await Promise.resolve()

    expect(onMessage).toHaveBeenCalledWith('Upgrade ready')

    await vi.advanceTimersByTimeAsync(1000)
    expect(checkUpgrade).toHaveBeenCalledTimes(2)

    stop()
    await vi.advanceTimersByTimeAsync(3000)
    expect(checkUpgrade).toHaveBeenCalledTimes(2)
  })
})
