//! Validator return type — Accept, Reject (with reason + originating
//! validator id), or Unknown when a validator cannot decide.

use serde::{Deserialize, Serialize};

/// Result of running a validator against a slice of authoritative state.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Verdict {
    /// The validator considers the input well-formed and fit-for-purpose.
    Accept,
    /// The validator rejected the input. `validator_id` matches the id of
    /// the validator that produced the rejection.
    Reject {
        /// Human-readable reason. Surfaces in MCP/CLI/HTTP error responses.
        reason: String,
        /// Originating validator id (matches `catalog/validators/<id>.ncl`).
        validator_id: String,
    },
    /// The validator cannot decide — typically because a Contextual
    /// validator could not load its slice. Callers MUST treat `Unknown`
    /// as a failure for pre-validation; post-validation may attest it
    /// asynchronously.
    Unknown,
}

impl Verdict {
    /// Convenience constructor for the rejection variant.
    pub fn reject(reason: impl Into<String>, validator_id: impl Into<String>) -> Self {
        Self::Reject {
            reason: reason.into(),
            validator_id: validator_id.into(),
        }
    }

    /// Whether the verdict permits the operation to proceed.
    pub fn is_accept(&self) -> bool {
        matches!(self, Self::Accept)
    }
}
