import { describe, expect, it } from 'vitest'
import { consumeFifo, type CostLayer } from './fifo.js'

const LAYERS: readonly CostLayer[] = [
  { id: 'layer-1', quantityRemaining: 5, unitCost: 10 },
  { id: 'layer-2', quantityRemaining: 3, unitCost: 12.5 },
  { id: 'layer-3', quantityRemaining: 4, unitCost: 15 },
]

describe('fifo valuation', () => {
  it('fully consumes a single layer', () => {
    expect(consumeFifo([{ id: 'layer-1', quantityRemaining: 5, unitCost: 10 }], 5)).toEqual({
      cogs: 50,
      updatedLayers: [{ id: 'layer-1', quantityRemaining: 0, unitCost: 10 }],
    })
  })

  it('consumes across multiple layers oldest-first', () => {
    expect(consumeFifo(LAYERS, 7)).toEqual({
      cogs: 75,
      updatedLayers: [
        { id: 'layer-1', quantityRemaining: 0, unitCost: 10 },
        { id: 'layer-2', quantityRemaining: 1, unitCost: 12.5 },
        { id: 'layer-3', quantityRemaining: 4, unitCost: 15 },
      ],
    })
  })

  it('partially consumes a layer down to exactly zero', () => {
    expect(consumeFifo(LAYERS, 8)).toEqual({
      cogs: 87.5,
      updatedLayers: [
        { id: 'layer-1', quantityRemaining: 0, unitCost: 10 },
        { id: 'layer-2', quantityRemaining: 0, unitCost: 12.5 },
        { id: 'layer-3', quantityRemaining: 4, unitCost: 15 },
      ],
    })
  })

  it('throws when consuming more than available', () => {
    expect(() => consumeFifo(LAYERS, 13)).toThrow(/cannot exceed available quantity/)
  })

  it('returns a no-op when consuming zero', () => {
    expect(consumeFifo(LAYERS, 0)).toEqual({
      cogs: 0,
      updatedLayers: [...LAYERS],
    })
  })
})
