import { eq } from 'drizzle-orm'
import { describe, expect, it } from 'vitest'
import { createPgliteClient } from '../../db/src/postgres/pglite.js'
import { isReviewNotFoundError } from './errors.js'
import { pushReviewsSchema } from './migrate.js'
import { moderateReview } from './moderate.js'
import { review, reviewsSchema } from './schema.js'

const PRODUCT_ID = 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa'
const USER_ID = 'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb'
const MISSING_REVIEW_ID = 'dddddddd-dddd-4ddd-8ddd-dddddddddddd'

async function freshDb() {
  const db = createPgliteClient({ schema: reviewsSchema })
  await pushReviewsSchema(db)
  return db
}

async function seedPending(db: Awaited<ReturnType<typeof freshDb>>): Promise<string> {
  const now = new Date()
  const [row] = await db
    .insert(review)
    .values({
      productId: PRODUCT_ID,
      userId: USER_ID,
      purchaseId: 'cccccccc-cccc-4ccc-8ccc-cccccccccccc',
      vendorId: 'vendor-a',
      rating: 4,
      body: 'seeded',
      status: 'pending',
      createdAt: now,
      updatedAt: now,
    })
    .returning()
  return row!.id
}

describe('moderateReview', () => {
  it('moderate-approve — pending review transitions to approved', async () => {
    const db = await freshDb()
    const id = await seedPending(db)

    await moderateReview(db, id, 'approve')

    const [row] = await db.select().from(review).where(eq(review.id, id))
    expect(row?.status).toBe('approved')
  })

  it('moderate-reject — pending review transitions to rejected', async () => {
    const db = await freshDb()
    const id = await seedPending(db)

    await moderateReview(db, id, 'reject')

    const [row] = await db.select().from(review).where(eq(review.id, id))
    expect(row?.status).toBe('rejected')
  })

  it('moderate-nonexistent-id — throws ReviewNotFoundError, no row created', async () => {
    const db = await freshDb()

    await expect(moderateReview(db, MISSING_REVIEW_ID, 'approve')).rejects.toSatisfy((e) =>
      isReviewNotFoundError(e),
    )

    const rows = await db.select().from(review)
    expect(rows).toHaveLength(0)
  })
})
