import { describe, expect, it } from 'vitest'
import { decideRedemption } from './decide.js'

const AT = new Date('2026-06-20T12:00:00.000Z')
const FUTURE = new Date('2026-07-01T00:00:00.000Z')
const PAST = new Date('2026-06-01T00:00:00.000Z')

describe('decideRedemption (pure)', () => {
  it('UNREDEEMED within expiry and vendor match → ok:true', () => {
    const decision = decideRedemption('UNREDEEMED', {
      at: AT,
      scanningVendorId: 'vendor-a',
      expiresAt: FUTURE,
      vendorId: 'vendor-a',
    })
    expect(decision).toEqual({ ok: true })
  })

  it('NULL vendor_id accepts any scanning vendor → ok:true', () => {
    const decision = decideRedemption('UNREDEEMED', {
      at: AT,
      scanningVendorId: 'any-vendor',
      expiresAt: FUTURE,
      vendorId: null,
    })
    expect(decision).toEqual({ ok: true })
  })

  it('REDEEMED → ALREADY_REDEEMED', () => {
    const decision = decideRedemption('REDEEMED', {
      at: AT,
      scanningVendorId: 'vendor-a',
      expiresAt: FUTURE,
      vendorId: 'vendor-a',
    })
    expect(decision).toEqual({ ok: false, reason: 'ALREADY_REDEEMED' })
  })

  it('past expiry → EXPIRED', () => {
    const decision = decideRedemption('UNREDEEMED', {
      at: AT,
      scanningVendorId: 'vendor-a',
      expiresAt: PAST,
      vendorId: 'vendor-a',
    })
    expect(decision).toEqual({ ok: false, reason: 'EXPIRED' })
  })

  it('EXPIRED state in snapshot → EXPIRED', () => {
    const decision = decideRedemption('EXPIRED', {
      currentState: 'EXPIRED',
      at: AT,
      scanningVendorId: 'vendor-a',
      expiresAt: FUTURE,
      vendorId: 'vendor-a',
    })
    expect(decision).toEqual({ ok: false, reason: 'EXPIRED' })
  })

  it('vendor mismatch → WRONG_VENDOR', () => {
    const decision = decideRedemption('UNREDEEMED', {
      at: AT,
      scanningVendorId: 'vendor-b',
      expiresAt: FUTURE,
      vendorId: 'vendor-a',
    })
    expect(decision).toEqual({ ok: false, reason: 'WRONG_VENDOR' })
  })

  it('CANCELLED → INVALID', () => {
    const decision = decideRedemption('CANCELLED', {
      at: AT,
      scanningVendorId: 'vendor-a',
      expiresAt: FUTURE,
      vendorId: 'vendor-a',
    })
    expect(decision).toEqual({ ok: false, reason: 'INVALID' })
  })
})
