import { describe, it, expect } from 'vitest'
import {
  formatBudgetWarningMessage,
  shouldEmitBudgetWarning,
  type BudgetWarningShownState,
} from '../utils/budget.js'

const TODAY = '2026-04-17'
const LIMIT = { dailyLimitUSD: 10 }

describe('shouldEmitBudgetWarning', () => {
  it('returns null when there is no budget', () => {
    expect(shouldEmitBudgetWarning(null, 100, {}, TODAY)).toBeNull()
  })

  it('returns null when under 75%', () => {
    expect(shouldEmitBudgetWarning(LIMIT, 7.4, {}, TODAY)).toBeNull()
  })

  it('returns "warn" first time past 75%', () => {
    expect(shouldEmitBudgetWarning(LIMIT, 7.5, {}, TODAY)).toBe('warn')
  })

  it('returns null for 75% cross if warn already shown today', () => {
    const shown: BudgetWarningShownState = { warn: TODAY }
    expect(shouldEmitBudgetWarning(LIMIT, 8, shown, TODAY)).toBeNull()
  })

  it('returns "over" first time past 100%', () => {
    expect(shouldEmitBudgetWarning(LIMIT, 10, {}, TODAY)).toBe('over')
    expect(shouldEmitBudgetWarning(LIMIT, 15, {}, TODAY)).toBe('over')
  })

  it('returns "over" when crossing directly from under-75% past 100% (no backfill of warn)', () => {
    // Big expensive turn jumped from $5 to $15
    expect(shouldEmitBudgetWarning(LIMIT, 15, {}, TODAY)).toBe('over')
  })

  it('suppresses "warn" if "over" already fired today (avoid regressing)', () => {
    const shown: BudgetWarningShownState = { over: TODAY }
    expect(shouldEmitBudgetWarning(LIMIT, 7.5, shown, TODAY)).toBeNull()
  })

  it('re-emits "warn" after date rollover', () => {
    const shown: BudgetWarningShownState = { warn: '2026-04-16' }
    expect(shouldEmitBudgetWarning(LIMIT, 8, shown, TODAY)).toBe('warn')
  })

  it('re-emits "over" after date rollover', () => {
    const shown: BudgetWarningShownState = { over: '2026-04-16' }
    expect(shouldEmitBudgetWarning(LIMIT, 12, shown, TODAY)).toBe('over')
  })
})

describe('formatBudgetWarningMessage', () => {
  it('renders the approaching variant for "warn"', () => {
    const msg = formatBudgetWarningMessage(LIMIT, 8, 'warn')
    expect(msg).toMatch(/approaching|80%|pause|adjust/i)
    expect(msg).not.toMatch(/exceeded|over budget/i)
  })

  it('renders the exceeded variant for "over"', () => {
    const msg = formatBudgetWarningMessage(LIMIT, 12, 'over')
    expect(msg).toMatch(/exceeded|over/i)
  })

  it('includes actionable /budget command references', () => {
    const warn = formatBudgetWarningMessage(LIMIT, 8, 'warn')
    const over = formatBudgetWarningMessage(LIMIT, 12, 'over')
    expect(warn).toContain('/budget')
    expect(over).toContain('/budget')
  })

  it('includes the spend / limit numbers', () => {
    expect(formatBudgetWarningMessage(LIMIT, 8, 'warn')).toContain('$8')
    expect(formatBudgetWarningMessage(LIMIT, 8, 'warn')).toContain('$10')
  })
})
