//! Core data types for story metadata: [`QaMode`] and [`ItemType`] enums.

/// QA mode for a story: determines how the pipeline handles post-coder review.
///
/// - `Server` — skip the QA agent; rely on server gate checks (clippy + tests).
///   If gates pass, advance straight to merge.
/// - `Agent` — spin up a QA agent (Claude session) to review code and run gates.
/// - `Human` — hold in QA for human approval after server gates pass.
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum QaMode {
    Server,
    Agent,
    Human,
}

impl QaMode {
    /// Parse a string into a `QaMode`. Returns `None` for unrecognised values.
    pub fn from_str(s: &str) -> Option<Self> {
        match s.trim().to_lowercase().as_str() {
            "server" => Some(Self::Server),
            "agent" => Some(Self::Agent),
            "human" => Some(Self::Human),
            _ => None,
        }
    }

    /// Return the lowercase string representation of this QA mode.
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Server => "server",
            Self::Agent => "agent",
            Self::Human => "human",
        }
    }
}

impl std::fmt::Display for QaMode {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(self.as_str())
    }
}

/// The type of a pipeline work item.
///
/// Stored as a typed register in the CRDT (`"story"`, `"bug"`, `"spike"`,
/// `"refactor"`, `"epic"`).  `None` in the view means "infer from the
/// story_id slug prefix".
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum ItemType {
    Story,
    Bug,
    Spike,
    Refactor,
    Epic,
}

impl ItemType {
    /// Parse a string into an `ItemType`. Returns `None` for unrecognised values.
    pub fn from_str(s: &str) -> Option<Self> {
        match s.trim().to_lowercase().as_str() {
            "story" => Some(Self::Story),
            "bug" => Some(Self::Bug),
            "spike" => Some(Self::Spike),
            "refactor" => Some(Self::Refactor),
            "epic" => Some(Self::Epic),
            _ => None,
        }
    }

    /// Return the lowercase string representation of this item type.
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Story => "story",
            Self::Bug => "bug",
            Self::Spike => "spike",
            Self::Refactor => "refactor",
            Self::Epic => "epic",
        }
    }
}

impl std::fmt::Display for ItemType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(self.as_str())
    }
}
