import { describe, expect, it } from 'vitest'
import { checkoutReducer, initialState } from './context.js'

describe('checkoutReducer', () => {
  it('SUBMIT_START from awaiting_payment clears orderId and clientSecret', () => {
    const s = {
      ...initialState,
      phase: 'awaiting_payment' as const,
      orderId: 'o1',
      clientSecret: 'cs_1',
    }
    const next = checkoutReducer(s, { type: 'SUBMIT_START' })
    expect(next.phase).toBe('starting')
    expect(next.orderId).toBeNull()
    expect(next.clientSecret).toBeNull()
  })

  it('STALE from awaiting_payment clears orderId and clientSecret', () => {
    const s = {
      ...initialState,
      phase: 'awaiting_payment' as const,
      orderId: 'o1',
      clientSecret: 'cs_1',
    }
    const stale = { removed: [], updated: [] }
    const next = checkoutReducer(s, { type: 'STALE', stale })
    expect(next.phase).toBe('stale')
    expect(next.orderId).toBeNull()
    expect(next.clientSecret).toBeNull()
    expect(next.stale).toBe(stale)
  })

  it('SETTLING is a no-op from cart_changed after CART_CHANGED during confirming', () => {
    const confirming = { ...initialState, phase: 'confirming' as const, orderId: 'o1', clientSecret: 'cs_1' }
    const cartChanged = checkoutReducer(confirming, { type: 'CART_CHANGED' })
    expect(cartChanged.phase).toBe('cart_changed')
    const afterSettling = checkoutReducer(cartChanged, { type: 'SETTLING', orderId: 'o1' })
    expect(afterSettling.phase).toBe('cart_changed')
    expect(afterSettling.orderId).toBeNull()
  })

  it('SETTLING permits settle_timeout → settling (R4 retry path)', () => {
    const s = { ...initialState, phase: 'settle_timeout' as const, orderId: 'o1' }
    const next = checkoutReducer(s, { type: 'SETTLING', orderId: 'o1' })
    expect(next.phase).toBe('settling')
    expect(next.orderId).toBe('o1')
  })

  it('FAILED from cart_changed is a no-op (R1 sibling — post-await confirm must not overwrite)', () => {
    const s = { ...initialState, phase: 'cart_changed' as const }
    const next = checkoutReducer(s, { type: 'FAILED', error: null })
    expect(next.phase).toBe('cart_changed')
  })

  it('FAILED from confirming → failed', () => {
    const s = { ...initialState, phase: 'confirming' as const, orderId: 'o1', clientSecret: 'cs_1' }
    const next = checkoutReducer(s, { type: 'FAILED', error: null })
    expect(next.phase).toBe('failed')
  })

  it('FAILED from starting → failed', () => {
    const s = { ...initialState, phase: 'starting' as const }
    const next = checkoutReducer(s, { type: 'FAILED', error: null })
    expect(next.phase).toBe('failed')
  })

  it('FAILED from settling → failed', () => {
    const s = { ...initialState, phase: 'settling' as const, orderId: 'o1' }
    const next = checkoutReducer(s, { type: 'FAILED', error: null })
    expect(next.phase).toBe('failed')
  })

  it('AWAIT_PAYMENT from idle is a no-op (attempt-epoch backstop)', () => {
    const s = { ...initialState, phase: 'idle' as const }
    const next = checkoutReducer(s, { type: 'AWAIT_PAYMENT', orderId: 'o1', clientSecret: 'cs_1' })
    expect(next.phase).toBe('idle')
    expect(next.clientSecret).toBeNull()
  })

  it('AWAIT_PAYMENT from starting → awaiting_payment', () => {
    const s = { ...initialState, phase: 'starting' as const, mintCartVersion: 'v1' }
    const next = checkoutReducer(s, { type: 'AWAIT_PAYMENT', orderId: 'o1', clientSecret: 'cs_1' })
    expect(next.phase).toBe('awaiting_payment')
    expect(next.clientSecret).toBe('cs_1')
    expect(next.mintCartVersion).toBe('v1')
  })

  it('AWAIT_PAYMENT from cart_changed is a no-op', () => {
    const s = { ...initialState, phase: 'cart_changed' as const }
    const next = checkoutReducer(s, { type: 'AWAIT_PAYMENT', orderId: 'o1', clientSecret: 'cs_1' })
    expect(next.phase).toBe('cart_changed')
    expect(next.clientSecret).toBeNull()
  })
})