import { describe, expect, it } from 'vitest'
import { reviveReview, reviveReviewPage, reviveRatingAggregate } from './revive.js'
import { isReviewWireError } from './errors.js'

const wire = (o = {}) => ({
  id: 'r1', productId: 'p1', vendorId: null, rating: 5, body: 'great',
  status: 'approved', vendorReply: null,
  createdAt: '2026-06-25T10:00:00.000Z', updatedAt: '2026-06-25T10:00:00.000Z', ...o,
})

describe('reviveReview', () => {
  it('revives a full wire review; dates → Date', () => {
    const r = reviveReview(wire())
    expect(r.createdAt).toBeInstanceOf(Date)
    expect(r.rating).toBe(5)
  })
  it('tolerates absent userId (public list PII strip, §1.3)', () => {
    expect(() => reviveReview(wire())).not.toThrow()
    expect(reviveReview(wire({ userId: 'u9' })).userId).toBe('u9')
  })
  it('rejects bad rating', () => {
    try { reviveReview(wire({ rating: 7 })); throw new Error('no throw') }
    catch (e) { expect(isReviewWireError(e)).toBe(true) }
  })
  it('rejects bad status', () => {
    try { reviveReview(wire({ status: 'live' })); throw new Error('no throw') }
    catch (e) { expect(isReviewWireError(e)).toBe(true) }
  })
  it('rejects non-Date/unparseable createdAt', () => {
    try { reviveReview(wire({ createdAt: 'not-a-date' })); throw new Error('no throw') }
    catch (e) { expect(isReviewWireError(e)).toBe(true) }
  })
})

describe('reviveReviewPage', () => {
  it('revives items + nextCursor', () => {
    const p = reviveReviewPage({ items: [wire()], nextCursor: 'c1' })
    expect(p.items[0]!.id).toBe('r1')
    expect(p.nextCursor).toBe('c1')
  })
})

describe('reviveRatingAggregate', () => {
  it('accepts a dense distribution', () => {
    const a = reviveRatingAggregate({ productId: 'p1', avg: 4.2, count: 10,
      distribution: { 1: 0, 2: 1, 3: 1, 4: 2, 5: 6 } })
    expect(a.count).toBe(10)
  })
  it('rejects a sparse distribution (missing key)', () => {
    try { reviveRatingAggregate({ productId: 'p1', avg: 0, count: 0, distribution: { 1: 0 } }); throw new Error('no throw') }
    catch (e) { expect(isReviewWireError(e)).toBe(true) }
  })
})
