import { describe, expect, it, vi } from 'vitest'
import {
  getDefaultInventoryLocationId,
  postInventoryReceipt,
  reverseInventorySale,
} from '../../src/queries/inventory-posting'

describe('inventory posting queries', () => {
  it('posts an idempotent tenant-scoped receipt and updates its position', async () => {
    const execute = vi
      .fn()
      .mockResolvedValueOnce({ rows: [{ owned: true, inserted: true }] })
      .mockResolvedValueOnce({ rows: [] })

    await expect(postInventoryReceipt({ execute } as never, {
      tenantId: 'tenant-1',
      itemId: 'item-1',
      locationId: 'location-1',
      qty: 2,
      unitCost: 9,
      holderRef: 'expense:expense-1:line-1',
      occurredAt: new Date('2026-07-05T00:00:00.000Z'),
    })).resolves.toBe(true)

    expect(execute).toHaveBeenCalledTimes(2)
    const queries = JSON.stringify(execute.mock.calls)
    expect(queries).toContain('tenant-1')
    expect(queries).toContain('item-1')
    expect(queries).toContain('location-1')
  })

  it('does not update a position when the receipt holder was already posted', async () => {
    const execute = vi.fn().mockResolvedValue({
      rows: [{ owned: true, inserted: false }],
    })

    await expect(postInventoryReceipt({ execute } as never, {
      tenantId: 'tenant-1',
      itemId: 'item-1',
      locationId: 'location-1',
      qty: 2,
      unitCost: 9,
      holderRef: 'expense:expense-1:line-1',
      occurredAt: new Date('2026-07-05T00:00:00.000Z'),
    })).resolves.toBe(false)

    expect(execute).toHaveBeenCalledTimes(1)
  })

  it('rejects receipts for inventory entities outside the tenant boundary', async () => {
    const execute = vi.fn().mockResolvedValue({
      rows: [{ owned: false, inserted: false }],
    })

    await expect(postInventoryReceipt({ execute } as never, {
      tenantId: 'tenant-1',
      itemId: 'foreign-item',
      locationId: 'foreign-location',
      qty: 2,
      unitCost: 9,
      holderRef: 'expense:expense-1:line-1',
      occurredAt: new Date('2026-07-05T00:00:00.000Z'),
    })).rejects.toThrow('Inventory item or location is outside tenant tenant-1')

    expect(execute).toHaveBeenCalledTimes(1)
  })

  it('reads the tenant default location', async () => {
    const execute = vi.fn().mockResolvedValue({ rows: [{ id: 'location-1' }] })

    await expect(
      getDefaultInventoryLocationId({ execute } as never, 'tenant-1'),
    ).resolves.toBe('location-1')
    expect(JSON.stringify(execute.mock.calls)).toContain('tenant-1')
  })

  it('reverses sold quantity only for the tenant-owned inventory row', async () => {
    const execute = vi.fn().mockResolvedValue({ rows: [{ sku_id: 'item-1' }] })

    await expect(reverseInventorySale({ execute } as never, {
      tenantId: 'tenant-1',
      itemId: 'item-1',
      quantity: 3,
    })).resolves.toBe(true)

    const query = JSON.stringify(execute.mock.calls[0]?.[0])
    expect(query).toContain('tenant-1')
    expect(query).toContain('item-1')
  })
})
