/** Polymorphic entity attach — opaque to the module. */
export type CommentTarget = { type: string; id: string }

/**
 * standard comment author: registered user OR anonymous guest.
 * email is stored but REDACTED from non-moderator reads (spec §3 info-disclosure floor).
 */
export type CommentAuthor =
  | { kind: 'user'; userId: string }
  | { kind: 'guest'; name: string; email?: string; url?: string }

/** Moderation lifecycle (spec §3). */
export type CommentStatus = 'published' | 'pending' | 'spam' | 'trashed'

export type Comment = {
  id: string
  target: CommentTarget
  parentId: string | null
  author: CommentAuthor
  body: string
  /** Sanitized HTML — render-safe; XSS hard-floor (spec §3). */
  bodyHtml: string
  status: CommentStatus
  /** STORED at insert (= parent.depth+1, 0 top-level); immutable (spec §3). */
  depth: number
  /** ISO-8601 UTC, re-derived from createdAtMs (record-store lesson). */
  createdAt: string
  editedAt: string | null
}

export type CommentInput = {
  target: CommentTarget
  parentId?: string | null
  author: CommentAuthor
  body: string
  /**
   * Default 'pending' (hard-floor #3).
   * Non-moderator caller passing anything other than 'pending' → CommentAuthzError.
   */
  initialStatus?: CommentStatus
}

/** Host-injected HTML sanitizer — REQUIRED on post/edit; no default no-op (spec §3). */
export type Sanitize = (raw: string) => string

/** Capability-based actor — role resolution is the caller's concern (content parity). */
export type Actor = { id: string; canModerate?: boolean }

export type EntityRef = { id: string; target: CommentTarget }

export type ListQuery = {
  /** Default 'published' only; other statuses require actor.canModerate. */
  status?: CommentStatus | CommentStatus[]
  /** Default 'oldest' (chronological thread display). */
  order?: 'oldest' | 'newest'
  /** Clamped; never throws. */
  limit?: number
  /** Opaque base64url keyset over NUMERIC (createdAtMs, seq). */
  cursor?: string
}

export type Page<T> = { items: T[]; nextCursor: string | null }

/** Tenancy readiness seam — no-op in public schema (content parity). */
export type StoreOpts = { scope?: unknown }
