import { sql } from 'drizzle-orm'
import { describe, expect, it } from 'vitest'
import { createPgliteClient } from '@platform-modules/db/pglite'
import { consume } from './consume.js'
import { getAvailability } from './get-availability.js'
import { pushSchema } from './migrate.js'
import { reserve } from './reserve.js'
import { inventorySchema } from './schema.js'
import { setInventory } from './set-inventory.js'
import { sweepStaleReservations } from './sweep.js'

const SKU_ID = 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa'
const NOW = new Date('2026-06-19T12:00:00.000Z')
const PAST_NOW = new Date('2026-06-19T10:00:00.000Z')
const TTL_MS = 15 * 60 * 1000

async function freshDb() {
  const db = createPgliteClient({ schema: inventorySchema })
  await pushSchema(db)
  return db
}

describe('sweepStaleReservations', () => {
  it('releases expired holds, leaves active and consumed untouched, and is idempotent', async () => {
    const db = await freshDb()
    await db.transaction((tx) => setInventory(tx, { skuId: SKU_ID, quantityTotal: 10 }))

    await db.transaction((tx) =>
      reserve(tx, {
        skuId: SKU_ID,
        qty: 2,
        holderRef: 'expired',
        now: PAST_NOW,
        ttlMs: TTL_MS,
      }),
    )

    const { reservationId: activeId } = await db.transaction((tx) =>
      reserve(tx, { skuId: SKU_ID, qty: 1, holderRef: 'active', now: NOW }),
    )

    const { reservationId: consumedId } = await db.transaction((tx) =>
      reserve(tx, { skuId: SKU_ID, qty: 1, holderRef: 'consumed', now: NOW }),
    )
    await db.transaction((tx) => consume(tx, consumedId))

    expect(await getAvailability(db, SKU_ID)).toBe(6)

    const first = await sweepStaleReservations(db, NOW)
    expect(first.released).toBe(1)

    const second = await sweepStaleReservations(db, NOW)
    expect(second.released).toBe(0)

    expect(await getAvailability(db, SKU_ID)).toBe(8)

    const statusRes = await db.execute(sql`
      SELECT holder_ref, released_at IS NOT NULL AS released, consumed_at IS NOT NULL AS consumed
      FROM stock_reservation
      WHERE sku_id = ${SKU_ID}::uuid
      ORDER BY holder_ref
    `)
    const rows = (Array.isArray(statusRes) ? statusRes : statusRes.rows) as Array<{
      holder_ref: string
      released: boolean
      consumed: boolean
    }>

    const byRef = Object.fromEntries(rows.map((r) => [r.holder_ref, r]))
    expect(byRef.active?.released).toBe(false)
    expect(byRef.consumed?.consumed).toBe(true)
    expect(byRef.expired?.released).toBe(true)

    const activeRow = await db.execute(sql`
      SELECT id FROM stock_reservation WHERE id = ${activeId}::uuid AND released_at IS NULL
    `)
    const activeRows = (Array.isArray(activeRow) ? activeRow : activeRow.rows) as unknown[]
    expect(activeRows.length).toBe(1)
  })
})
