import { expect, it, vi } from 'vitest'
import { getTransactionIdentity, type PostgresTransaction } from '../index.js'
import { createNeonServerlessClient } from './neon-serverless.js'

const mocks = vi.hoisted(() => ({
  drizzle: vi.fn(),
  pool: vi.fn(),
}))

vi.mock('@neondatabase/serverless', () => ({
  Pool: class {
    constructor(options: unknown) {
      mocks.pool(options)
    }
  },
}))

vi.mock('drizzle-orm/neon-serverless', () => ({ drizzle: mocks.drizzle }))

it('wraps Neon serverless transactions with normalized callback capabilities', async () => {
  const raw = {
    execute: vi.fn(async () => ({ rows: [{ value: 1 }] })),
  }
  mocks.drizzle.mockReturnValue({
    transaction: async <T>(callback: (tx: typeof raw) => Promise<T>) => callback(raw),
  })

  const db = createNeonServerlessClient({ connectionString: 'postgres://test' })
  let escaped: PostgresTransaction<Record<string, unknown>> | undefined

  await db.transaction(async (tx) => {
    escaped = tx
    expect(getTransactionIdentity(tx)).toBe(getTransactionIdentity(tx))
    await expect(tx.execute<{ value: number }>({} as never)).resolves.toEqual([
      { value: 1 },
    ])
  })

  await expect(escaped!.execute({} as never)).rejects.toEqual(
    expect.objectContaining({ code: 'transaction-capability', reason: 'inactive' }),
  )
})
