import { describe, expect, it } from 'vitest'
import { InventoryValidationError, isInventoryValidationError, isOversoldError } from './errors.js'
import { postIssue } from './post-issue.js'
import { postReceipt } from './post-receipt.js'
import {
  AVG_ITEM_ID,
  LOCATION_A,
  NOW,
  TENANT_ID,
  freshDb,
  seedItem,
  seedLocation,
} from './test-helpers.js'

describe('postIssue', () => {
  it('uses stored item.method as authoritative and throws on mismatch', async () => {
    const db = await freshDb()
    await seedLocation(db, LOCATION_A)
    await seedItem(db, AVG_ITEM_ID, 'weighted_average')

    await expect(
      postIssue(db, {
        tenantId: TENANT_ID,
        itemId: AVG_ITEM_ID,
        locationId: LOCATION_A,
        qty: 1,
        holderRef: 'issue-1',
        occurredAt: NOW,
        method: 'fifo',
        allowNegative: true,
      }),
    ).rejects.toBeInstanceOf(InventoryValidationError)
  })

  it('posts a real issue movement and can reject oversell when allowNegative=false', async () => {
    const db = await freshDb()
    await seedLocation(db, LOCATION_A)
    await seedItem(db, AVG_ITEM_ID, 'weighted_average')

    await postReceipt(db, {
      tenantId: TENANT_ID,
      itemId: AVG_ITEM_ID,
      locationId: LOCATION_A,
      qty: 2,
      unitCost: 5,
      occurredAt: NOW,
    })

    const issued = await postIssue(db, {
      tenantId: TENANT_ID,
      itemId: AVG_ITEM_ID,
      locationId: LOCATION_A,
      qty: 1,
      holderRef: 'issue-2',
      occurredAt: NOW,
      method: 'weighted_average',
      allowNegative: false,
    })
    expect(Number(issued.movement.cogsAmount)).toBe(5)

    await expect(
      postIssue(db, {
        tenantId: TENANT_ID,
        itemId: AVG_ITEM_ID,
        locationId: LOCATION_A,
        qty: 2,
        holderRef: 'issue-3',
        occurredAt: NOW,
        method: 'weighted_average',
        allowNegative: false,
      }),
    ).rejects.toSatisfy((error) => isOversoldError(error) || isInventoryValidationError(error))
  })

  it('defaults to allowNegative=true and records pending cost', async () => {
    const db = await freshDb()
    await seedLocation(db, LOCATION_A)
    await seedItem(db, AVG_ITEM_ID, 'weighted_average')

    const issued = await postIssue(db, {
      tenantId: TENANT_ID,
      itemId: AVG_ITEM_ID,
      locationId: LOCATION_A,
      qty: 2,
      holderRef: 'issue-default-negative',
      occurredAt: NOW,
      method: 'weighted_average',
    })
    expect(issued.movement.pendingCost).toBe(true)
    expect(Number(issued.movement.qtyDelta)).toBe(-2)
  })
})
