///|
/// User-facing processing status returned by handlers and middleware.
pub(all) enum HookStatus {
  Accepted
  Ignored
  Retried
  Failed
} derive(Eq, Debug)

///|
/// A structured result that can be logged, retried, or asserted in tests.
pub(all) struct HookResult {
  status : HookStatus
  message : String
  retryable : Bool
  attempts : Int
} derive(Eq, Debug)

///|
/// Stable text used by diagnostics and examples.
pub fn HookStatus::to_string(self : HookStatus) -> String {
  match self {
    Accepted => "Accepted"
    Ignored => "Ignored"
    Retried => "Retried"
    Failed => "Failed"
  }
}

///|
/// Construct a general result.
pub fn HookResult::HookResult(
  status : HookStatus,
  message : StringView,
  retryable? : Bool = false,
  attempts? : Int = 1,
) -> HookResult {
  { status, message: message.to_owned(), retryable, attempts }
}

///|
/// Successful handling result.
pub fn accepted(message? : StringView = "accepted") -> HookResult {
  HookResult(Accepted, message)
}

///|
/// Ignored event result.
pub fn ignored(message? : StringView = "ignored") -> HookResult {
  HookResult(Ignored, message)
}

///|
/// Failed event result.
pub fn failed(
  message? : StringView = "failed",
  retryable? : Bool = false,
) -> HookResult {
  HookResult(Failed, message, retryable~)
}

///|
/// Retry event result.
pub fn retried(
  message? : StringView = "retry scheduled",
  attempts? : Int = 1,
) -> HookResult {
  HookResult(Retried, message, retryable=true, attempts~)
}

///|
/// Whether the final state represents successful completion.
pub fn HookResult::is_ok(self : HookResult) -> Bool {
  match self.status {
    Accepted => true
    Ignored => true
    Retried => false
    Failed => false
  }
}

///|
/// Whether another delivery attempt should be scheduled.
pub fn HookResult::should_retry(self : HookResult) -> Bool {
  self.retryable || self.status == Retried
}