import { eq } from 'drizzle-orm'
import { describe, expect, it } from 'vitest'
import { createPgliteClient } from '../../db/src/postgres/pglite.js'
import { getRatingAggregate } from './aggregate.js'
import { pushReviewsSchema } from './migrate.js'
import { review, reviewsSchema } from './schema.js'
import { submitReview } from './submit.js'
import {
  createFakeVerifiedPurchasePort,
  noOpAutoApproveModerationAdapter,
} from './testing/index.js'

const PRODUCT_ID = 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa'
const USER_ID = 'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb'
const PURCHASE_ID = 'cccccccc-cccc-4ccc-8ccc-cccccccccccc'

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

async function submitApproved(
  db: Awaited<ReturnType<typeof freshDb>>,
  overrides: {
    productId?: string
    userId?: string
    purchaseId?: string
    rating?: number
    body?: string | null
    vendorId?: string | null
  } = {},
) {
  return submitReview(
    db,
    {
      productId: overrides.productId ?? PRODUCT_ID,
      userId: overrides.userId ?? USER_ID,
      purchaseId: overrides.purchaseId ?? PURCHASE_ID,
      vendorId: overrides.vendorId ?? null,
      rating: overrides.rating ?? 5,
      body: overrides.body ?? 'great',
    },
    {
      verifiedPurchase: createFakeVerifiedPurchasePort({ purchased: true }),
      moderation: noOpAutoApproveModerationAdapter,
    },
  )
}

describe('getRatingAggregate', () => {
  it('aggregate-correct — mixed ratings, only approved counted', async () => {
    const db = await freshDb()

    await submitApproved(db, { userId: 'user-1', rating: 5 })
    await submitApproved(db, { userId: 'user-2', rating: 4 })
    await submitApproved(db, { userId: 'user-3', rating: 5 })
    await submitApproved(db, { userId: 'user-4', rating: 3 })

    await db.update(review).set({ status: 'pending' }).where(eq(review.userId, 'user-4'))

    const aggregate = await getRatingAggregate(db, PRODUCT_ID)

    expect(aggregate.count).toBe(3)
    expect(aggregate.avg).toBeCloseTo(14 / 3)
    expect(aggregate.distribution).toEqual({ 1: 0, 2: 0, 3: 0, 4: 1, 5: 2 })
  })

  it('aggregate-zero-safe — zero approved returns zero-filled aggregate', async () => {
    const db = await freshDb()

    const aggregate = await getRatingAggregate(db, 'product-with-no-reviews')

    expect(aggregate).toEqual({
      productId: 'product-with-no-reviews',
      avg: 0,
      count: 0,
      distribution: { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 },
    })
  })
})
