import { eq, sql } from 'drizzle-orm'
import { drizzle } from 'drizzle-orm/node-postgres'
import pg from 'pg'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import type { TransactionalDatabase } from '@platform-modules/db'
import { createOrder } from './create-order.js'
import { startPg } from './pg-harness.js'
import { order, ordersSchema } from './schema.js'
import type { NewOrder } from './types.js'

const VARIANT_A = '11111111-1111-4111-8111-111111111111'
const BUYER_ID = '33333333-3333-4333-8333-333333333333'
const IDEM_KEY = 'secaudit-create-idempotent-race-key'

function sleep(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms))
}

function baseOrder(): NewOrder {
  return {
    idempotencyKey: IDEM_KEY,
    buyerRef: { userId: BUYER_ID },
    currency: 'USD',
    priceMode: 'exclusive',
    subtotal: 1000n,
    tax: 100n,
    discount: 0n,
    total: 1100n,
    lines: [
      {
        variantId: VARIANT_A,
        kind: 'physical',
        qty: 2,
        unitPrice: 500n,
        lineTotal: 1000n,
        currency: 'USD',
        vendorId: null,
      },
    ],
    splits: [{ vendorId: null, amount: 1100n, funder: 'platform' }],
  }
}

function firstCount(res: unknown): number {
  const rows = (Array.isArray(res) ? res : (res as { rows?: Array<{ count: number }> }).rows) ?? []
  return Number(rows[0]?.count ?? 0)
}

describe('createOrder idempotency concurrency (real Postgres)', () => {
  let db: TransactionalDatabase<typeof ordersSchema>
  let dbB: TransactionalDatabase<typeof ordersSchema>
  let poolB: pg.Pool | undefined
  let stop: (() => Promise<void>) | undefined

  beforeAll(async () => {
    const pgResult = await startPg()
    db = pgResult.db
    const { host, port, user, database } = pgResult.pool.options
    poolB = new pg.Pool({ host, port, user, database, max: 1 })
    dbB = drizzle(poolB, { schema: ordersSchema }) as TransactionalDatabase<typeof ordersSchema>
    stop = pgResult.stop
  }, 120_000)

  afterAll(async () => {
    await poolB?.end().catch(() => undefined)
    await stop?.()
  }, 30_000)

  it('secaudit-orders-create-idempotent-race: 2-connection same-key createOrder → one row, same id', async () => {
    const input = baseOrder()

    let resolveHold!: () => void
    const hold = new Promise<void>((resolve) => {
      resolveHold = resolve
    })

    let txALocked!: () => void
    const txAHasLock = new Promise<void>((resolve) => {
      txALocked = resolve
    })

    const txA = db.transaction(async (txA) => {
      const created = await createOrder(txA, input)
      txALocked()
      await hold
      return created
    })

    await txAHasLock

    const txB = dbB.transaction(async (txB) => {
      return createOrder(txB, input)
    })

    await sleep(200)
    resolveHold()

    const [orderA, orderB] = await Promise.all([txA, txB])
    expect(orderA.id).toBe(orderB.id)

    const orderCount = firstCount(
      await db.execute(sql`SELECT COUNT(*)::int AS count FROM "order"`),
    )
    expect(orderCount).toBe(1)

    const lineCount = firstCount(
      await db.execute(sql`
        SELECT COUNT(*)::int AS count FROM order_line WHERE order_id = ${orderA.id}::uuid
      `),
    )
    expect(lineCount).toBe(1)

    const splitCount = firstCount(
      await db.execute(sql`
        SELECT COUNT(*)::int AS count FROM vendor_split WHERE order_id = ${orderA.id}::uuid
      `),
    )
    expect(splitCount).toBe(1)

    const [row] = await db.select().from(order).where(eq(order.id, orderA.id))
    expect(row?.idempotencyKey).toBe(IDEM_KEY)
  })
})
