/**
 * Capability-based actor — NO role model baked in (R1: no defaults baked in). The distribution's
 * route resolves the adopter's roles (admin/editor/author) into these capability booleans.
 */
export type Actor = {
  id: string
  /** May modify/remove entries authored by others (editor/admin). */
  canEditAny?: boolean
  /** May perform privileged state transitions: publish / schedule / unpublish (editor/admin). */
  canPublish?: boolean
  /** May read visibility='members' entries once published (subscriber/member). */
  canViewMembers?: boolean
  /** May create/rename/move/delete taxonomy terms (editor/admin). */
  canManageTaxonomy?: boolean
}

export type ContentAction = 'read' | 'create' | 'update' | 'publish' | 'schedule' | 'unpublish' | 'remove' | 'trash' | 'restore'

export class ContentAuthzError extends Error {
  override readonly name = 'ContentAuthzError'
  constructor(
    readonly action: ContentAction,
    readonly actorId: string,
    readonly detail: string,
    readonly entryId?: string,
  ) {
    super(`content authz denied: ${action} by ${actorId} — ${detail}`)
  }
}

/** Object-level authz (IDOR floor, spec §3.2): only the author or an editor may touch an entry. */
export function assertCanModify(actor: Actor, action: ContentAction, ownerAuthor: string, entryId: string): void {
  if (actor.canEditAny) return
  if (ownerAuthor !== actor.id) {
    throw new ContentAuthzError(action, actor.id, 'actor is not the author and lacks canEditAny', entryId)
  }
}

/** Privileged state transition (publish/schedule/unpublish) — requires canPublish. */
export function assertCanPublish(actor: Actor, action: ContentAction, entryId: string): void {
  if (!actor.canPublish) {
    throw new ContentAuthzError(action, actor.id, 'actor lacks canPublish', entryId)
  }
}

/** Term lifecycle (create/rename/move/delete) — requires canManageTaxonomy. */
export function assertCanManageTaxonomy(actor: Actor): void {
  if (!actor.canManageTaxonomy) {
    throw new ContentAuthzError('update', actor.id, 'actor lacks canManageTaxonomy')
  }
}
