/**
 * @module errors/notFound
 * @description Named not-found errors for Brainy's public contract.
 *
 * Operations that require an existing record — `update()`, `relate()`,
 * `updateRelation()`, `similar({ to: id })`, `transact()` planning, and
 * speculative `db.with()` planning — throw these instead of a generic
 * `Error`, so callers can branch with `instanceof` and read the missing
 * `id` programmatically instead of parsing message strings:
 *
 * - {@link EntityNotFoundError} — a referenced entity (noun) does not exist
 *   in the store (or, for `db.with()`, is not visible at the pinned
 *   generation).
 * - {@link RelationNotFoundError} — a referenced relationship (verb) does
 *   not exist.
 *
 * Both are exported from the package root (`@soulcraft/brainy`).
 */

/**
 * @description Thrown when an operation references an entity id that does
 * not exist. Carries the missing {@link EntityNotFoundError.id} so callers
 * can recover (re-create, skip, or surface it) without string matching.
 *
 * @example
 * try {
 *   await brain.update({ id, metadata: { status: 'active' } })
 * } catch (err) {
 *   if (err instanceof EntityNotFoundError) {
 *     console.log(`missing entity: ${err.id}`)
 *   }
 * }
 */
export class EntityNotFoundError extends Error {
  /** The entity id that could not be found. */
  public readonly id: string

  /**
   * @param id - The entity id that could not be found.
   * @param message - Optional message override for call sites that add
   *   context (e.g. source/target role, pinned generation). Defaults to
   *   `Entity <id> not found`.
   */
  constructor(id: string, message?: string) {
    super(message ?? `Entity ${id} not found`)
    this.name = 'EntityNotFoundError'
    this.id = id
  }
}

/**
 * @description Thrown when an operation references a relationship id that
 * does not exist. Carries the missing {@link RelationNotFoundError.id} so
 * callers can recover without string matching.
 *
 * @example
 * try {
 *   await brain.updateRelation({ id: relId, subtype: 'dotted-line' })
 * } catch (err) {
 *   if (err instanceof RelationNotFoundError) {
 *     console.log(`missing relation: ${err.id}`)
 *   }
 * }
 */
export class RelationNotFoundError extends Error {
  /** The relationship id that could not be found. */
  public readonly id: string

  /**
   * @param id - The relationship id that could not be found.
   * @param message - Optional message override for call sites that add
   *   context. Defaults to `Relation <id> not found`.
   */
  constructor(id: string, message?: string) {
    super(message ?? `Relation ${id} not found`)
    this.name = 'RelationNotFoundError'
    this.id = id
  }
}
