import { describe, expect, it } from 'vitest'
import { createPgliteClient } from '@platform-modules/db/pglite'
import { createOrder } from './create-order.js'
import { isOrderValidationError } from './errors.js'
import { getOrderById } from './get-order-by-id.js'
import { pushSchema } from './migrate.js'
import { ordersSchema } from './schema.js'
import { recordStep } from './record-step.js'
import type { Actor, NewOrder } from './types.js'

const VARIANT_A = '11111111-1111-4111-8111-111111111111'
const BUYER_A = '33333333-3333-4333-8333-333333333333'
const BUYER_B = '44444444-4444-4444-8444-444444444444'
const ADMIN_ACTOR: Actor = { isAdmin: true }
const VENDOR_A = 'vendor-a'
const NON_EXISTENT_ORDER = 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa'

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

function baseOrder(buyerId: string, vendorId: string | null = null): NewOrder {
  return {
    idempotencyKey: crypto.randomUUID(),
    buyerRef: { userId: buyerId },
    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,
      },
    ],
    splits: [{ vendorId, amount: 1100n, funder: vendorId ? 'vendor' : 'platform' }],
  }
}

describe('getOrderById', () => {
  it('returns a buyer-owned order with lines, splits, and projected steps', async () => {
    const db = await freshDb()
    const created = await db.transaction((tx) => createOrder(tx, baseOrder(BUYER_A, VENDOR_A)))
    await db.transaction((tx) =>
      recordStep(tx, created.id, 'grant-license', { granted: true }),
    )

    const result = await getOrderById(db, created.id, { userId: BUYER_A })

    expect(result).not.toBeNull()
    expect(result!.id).toBe(created.id)
    expect(result!.lines).toHaveLength(1)
    expect(result!.lines[0]?.vendorId).toBe(VENDOR_A)
    expect(result!.splits).toHaveLength(1)
    expect(result!.fulfillmentState.steps).toEqual({ 'grant-license': { granted: true } })
  })

  it('returns null for a different buyer (A5 — no existence oracle)', async () => {
    const db = await freshDb()
    const created = await db.transaction((tx) => createOrder(tx, baseOrder(BUYER_A)))

    const result = await getOrderById(db, created.id, { userId: BUYER_B })
    expect(result).toBeNull()
  })

  it('returns null for a non-existent id (indistinguishable from not-owned)', async () => {
    const db = await freshDb()

    const notOwned = await getOrderById(db, NON_EXISTENT_ORDER, { userId: BUYER_A })
    expect(notOwned).toBeNull()
  })

  it('lets admin read any order', async () => {
    const db = await freshDb()
    const created = await db.transaction((tx) => createOrder(tx, baseOrder(BUYER_A)))

    const result = await getOrderById(db, created.id, ADMIN_ACTOR)
    expect(result?.id).toBe(created.id)
  })

  it('lets a vendor read an order that contains its line', async () => {
    const db = await freshDb()
    const created = await db.transaction((tx) => createOrder(tx, baseOrder(BUYER_A, VENDOR_A)))

    const result = await getOrderById(db, created.id, { vendorId: VENDOR_A })
    expect(result?.id).toBe(created.id)
  })

  it('returns null when vendor has no line on the order', async () => {
    const db = await freshDb()
    const created = await db.transaction((tx) => createOrder(tx, baseOrder(BUYER_A, 'other-vendor')))

    const result = await getOrderById(db, created.id, { vendorId: VENDOR_A })
    expect(result).toBeNull()
  })

  it('rejects malformed id with OrderValidationError', async () => {
    const db = await freshDb()

    await expect(getOrderById(db, 'not-a-uuid', { userId: BUYER_A })).rejects.toSatisfy((e) =>
      isOrderValidationError(e),
    )
  })
})
