import { describe, expect, it, vi } from 'vitest'

const mockSetInventory = vi.fn()
const mockCommitStock = vi.fn()
const mockListTrackedInvoiceStockItems = vi.fn()
const mockPostReceipt = vi.fn()

vi.mock('@platform-modules/commerce-inventory', () => ({
  commitStock: (...args: unknown[]) => mockCommitStock(...args),
  consume: vi.fn(),
  getAvailability: vi.fn(),
  release: vi.fn(),
  reserve: vi.fn(),
  setInventory: (...args: unknown[]) => mockSetInventory(...args),
}))

vi.mock('@zync/db/queries', async () => {
  const actual = await vi.importActual<Record<string, unknown>>('@zync/db/queries')
  return {
    ...actual,
    listTrackedInvoiceStockItems: (...args: unknown[]) => mockListTrackedInvoiceStockItems(...args),
  }
})

import {
  inventoryPosting,
  postExpenseReceipts,
  postIssue,
  provisionStockItem,
} from '../src/integrations/platform/inventory'

describe('inventory platform adapter', () => {
  it('provisions an unlimited stock row for the tenant product pair', async () => {
    const tx = {} as never
    mockSetInventory.mockResolvedValue(undefined)

    await expect(
      provisionStockItem(tx, {
        tenantId: 'tenant-1',
        stockItemId: 'stock-1',
      }),
    ).resolves.toBe('stock-1')

    expect(mockSetInventory).toHaveBeenCalledWith(tx, {
      skuId: 'stock-1',
      vendorId: 'tenant-1',
      quantityTotal: null,
    })
  })

  it('posts each tracked invoice line as its own stock commit', async () => {
    const tx = {} as never
    mockListTrackedInvoiceStockItems.mockResolvedValue([
      { stockItemId: '11111111-1111-4111-8111-111111111111', quantity: 2 },
      { stockItemId: '22222222-2222-4222-8222-222222222222', quantity: 1 },
      { stockItemId: '11111111-1111-4111-8111-111111111111', quantity: 3 },
    ])

    await postIssue(tx, { tenantId: 'tenant-1', invoiceId: 'inv-1' })

    expect(mockListTrackedInvoiceStockItems).toHaveBeenCalledWith(tx, 'tenant-1', 'inv-1')
    expect(mockCommitStock).toHaveBeenNthCalledWith(1, tx, '11111111-1111-4111-8111-111111111111', 2)
    expect(mockCommitStock).toHaveBeenNthCalledWith(2, tx, '22222222-2222-4222-8222-222222222222', 1)
    expect(mockCommitStock).toHaveBeenNthCalledWith(3, tx, '11111111-1111-4111-8111-111111111111', 3)
  })

  it('posts one receipt per stock line using net cost', async () => {
    const tx = {} as never
    inventoryPosting.postReceipt = (...args: unknown[]) => mockPostReceipt(...args)
    mockPostReceipt.mockResolvedValue(undefined)

    const count = await postExpenseReceipts(tx, {
      id: 'expense-1',
      tenantId: 'tenant-1',
      sourceMetadata: {
        stockLines: [
          {
            id: 'line-1',
            stockItemId: 'item-1',
            locationId: 'loc-1',
            quantity: 2,
            grossAmount: 23.4,
            vatAmount: 5.4,
          },
          {
            id: 'line-2',
            itemId: 'item-2',
            locationId: 'loc-2',
            qty: 3,
            netAmount: 30,
          },
        ],
      },
      createdAt: '2026-07-05T00:00:00.000Z',
    })

    expect(count).toBe(2)
    expect(mockPostReceipt).toHaveBeenNthCalledWith(1, tx, {
      tenantId: 'tenant-1',
      itemId: 'item-1',
      locationId: 'loc-1',
      qty: 2,
      unitCost: 9,
      holderRef: 'expense:expense-1:stock-line:line-1',
      occurredAt: new Date('2026-07-05T00:00:00.000Z'),
    })
    expect(mockPostReceipt).toHaveBeenNthCalledWith(2, tx, {
      tenantId: 'tenant-1',
      itemId: 'item-2',
      locationId: 'loc-2',
      qty: 3,
      unitCost: 10,
      holderRef: 'expense:expense-1:stock-line:line-2',
      occurredAt: new Date('2026-07-05T00:00:00.000Z'),
    })
  })
})
