import { describe, expect, it } from 'vitest'
import {
  FraudHoldError,
  InsufficientBalanceError,
  isFraudHoldError,
  isInsufficientBalanceError,
} from './errors.js'

describe('InsufficientBalanceError', () => {
  it('carries rich bucket detail for payout guard failures', () => {
    const e = new InsufficientBalanceError('payout exceeds matured', {
      requiredMinor: 100n,
      availableMinor: 50n,
      bucket: 'matured',
    })
    expect(e.code).toBe('INSUFFICIENT_BALANCE')
    expect(e.detail?.bucket).toBe('matured')
    expect(e.detail?.requiredMinor).toBe(100n)
  })
})

describe('isInsufficientBalanceError', () => {
  it('matches a brand, not the prototype', () => {
    const e = new InsufficientBalanceError('insufficient', {
      requiredMinor: 100n,
      availableMinor: 50n,
      bucket: 'matured',
    })
    expect(isInsufficientBalanceError(e)).toBe(true)
    expect(isInsufficientBalanceError({ _affiliateError: 'InsufficientBalanceError' })).toBe(true)
    expect(isInsufficientBalanceError(new Error('x'))).toBe(false)
    expect(isInsufficientBalanceError(null)).toBe(false)
  })
})

describe('FraudHoldError', () => {
  it('carries decision-point detail for EARN fail-closed holds', () => {
    const e = new FraudHoldError('earn held', { point: 'EARN', reason: 'adapter_error' })
    expect(e.code).toBe('FRAUD_HOLD')
    expect(e.detail?.point).toBe('EARN')
    expect(e.detail?.reason).toBe('adapter_error')
  })
})

describe('isFraudHoldError', () => {
  it('matches the brand, not instanceof', () => {
    expect(isFraudHoldError(new FraudHoldError('held'))).toBe(true)
    expect(isFraudHoldError({ _affiliateError: 'FraudHoldError' })).toBe(true)
    expect(isFraudHoldError(new Error('x'))).toBe(false)
    expect(isFraudHoldError(undefined)).toBe(false)
  })
})
