import { describe, expect, it } from 'vitest'
import {
  CommentAuthzError,
  CommentNotFoundError,
  CommentSanitizationError,
  CommentValidationError,
  InvalidCursorError,
  isCommentError,
} from './errors.js'

describe('isCommentError — structural guard, instanceof-free', () => {
  it('accepts all module error types by code', () => {
    const errors = [
      new CommentValidationError('body', 'empty'),
      new CommentNotFoundError('id=1'),
      new CommentAuthzError('edit', 'u1', 'c1', 'not owner'),
      new CommentSanitizationError('missing sanitize fn'),
      new InvalidCursorError(),
    ]
    for (const e of errors) {
      expect(isCommentError(e)).toBe(true)
    }
  })

  it('rejects non-module objects without code or wrong prefix', () => {
    expect(isCommentError(new Error('plain'))).toBe(false)
    expect(isCommentError({ code: 'CONTENT_VALIDATION' })).toBe(false)
    expect(isCommentError(null)).toBe(false)
    expect(isCommentError(42)).toBe(false)
    expect(isCommentError(undefined)).toBe(false)
  })

  it('works on plain object with code — no instanceof needed', () => {
    // Two deduped copies of the same class STILL match the guard
    const fakeCopy = { code: 'COMMENT_VALIDATION', field: 'body', detail: 'too long' }
    expect(isCommentError(fakeCopy)).toBe(true)
  })

  it('errors carry contextful fields', () => {
    const v = new CommentValidationError('body', 'exceeds max')
    expect(v.field).toBe('body')
    expect(v.detail).toBe('exceeds max')
    expect(v.code).toBe('COMMENT_VALIDATION')

    const authz = new CommentAuthzError('remove', 'u2', 'c9', 'not moderator')
    expect(authz.action).toBe('remove')
    expect(authz.actorId).toBe('u2')
    expect(authz.commentId).toBe('c9')
  })
})
