import { describe, expect, it } from 'vitest'
import { assertCanModerate, assertCanModify } from './authz.js'
import { CommentAuthzError } from './errors.js'
import type { Actor, CommentAuthor } from './types.js'

const userOwner: CommentAuthor = { kind: 'user', userId: 'u1' }
const guestOwner: CommentAuthor = { kind: 'guest', name: 'Alice' }
const author: Actor = { id: 'u1' }
const moderator: Actor = { id: 'mod', canModerate: true }
const stranger: Actor = { id: 'u2' }

describe('assertCanModify', () => {
  it('allows author on user-owned comment', () => {
    expect(() => assertCanModify(author, 'edit', userOwner, 'c1')).not.toThrow()
  })

  it('allows moderator on user-owned comment', () => {
    expect(() => assertCanModify(moderator, 'edit', userOwner, 'c1')).not.toThrow()
  })

  it('allows moderator on guest-owned comment', () => {
    expect(() => assertCanModify(moderator, 'edit', guestOwner, 'c1')).not.toThrow()
  })

  it('rejects non-author non-moderator on user-owned comment', () => {
    expect(() => assertCanModify(stranger, 'edit', userOwner, 'c1')).toThrow(CommentAuthzError)
  })

  it('rejects non-moderator on guest-owned comment', () => {
    expect(() => assertCanModify(author, 'edit', guestOwner, 'c1')).toThrow(CommentAuthzError)
  })

  it('rejects null actor on any comment', () => {
    expect(() => assertCanModify(null, 'edit', userOwner, 'c1')).toThrow(CommentAuthzError)
    expect(() => assertCanModify(null, 'edit', guestOwner, 'c1')).toThrow(CommentAuthzError)
  })
})

describe('assertCanModerate', () => {
  it('allows actor with canModerate', () => {
    expect(() => assertCanModerate(moderator, 'setStatus', 'c1')).not.toThrow()
  })

  it('rejects actor without canModerate', () => {
    expect(() => assertCanModerate(author, 'setStatus', 'c1')).toThrow(CommentAuthzError)
  })

  it('rejects actor with canModerate=false', () => {
    const notMod: Actor = { id: 'u3', canModerate: false }
    expect(() => assertCanModerate(notMod, 'setStatus', 'c1')).toThrow(CommentAuthzError)
  })
})
