//! Pure-content helpers and CRDT-backed metadata lookups.
//!
//! Story 865 stripped YAML front matter from stored content and the codebase
//! at large; the only remaining functions here read the CRDT or operate on
//! the markdown body directly.
/// Parse unchecked todo items (`- [ ] ...`) from a markdown string.
pub fn parse_unchecked_todos(contents: &str) -> Vec<String> {
    contents
        .lines()
        .filter_map(|line| {
            let trimmed = line.trim();
            trimmed.strip_prefix("- [ ] ").map(|text| text.to_string())
        })
        .collect()
}

/// Return `true` if the story is currently in `Stage::Frozen`
/// (story 945: frozen is a typed stage variant, not a flag).
///
/// Used by the pipeline advance code to suppress stage transitions for frozen
/// stories.
pub fn is_story_frozen_in_store(story_id: &str) -> bool {
    crate::pipeline_state::read_typed(story_id)
        .ok()
        .flatten()
        .map(|item| matches!(item.stage, crate::pipeline_state::Stage::Frozen { .. }))
        .unwrap_or(false)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parse_unchecked_todos_mixed() {
        let input = "## AC\n- [ ] First thing\n- [x] Done thing\n- [ ] Second thing\n";
        assert_eq!(
            parse_unchecked_todos(input),
            vec!["First thing", "Second thing"]
        );
    }

    #[test]
    fn parse_unchecked_todos_all_checked() {
        let input = "- [x] Done\n- [x] Also done\n";
        assert!(parse_unchecked_todos(input).is_empty());
    }

    #[test]
    fn parse_unchecked_todos_no_checkboxes() {
        let input = "# Story\nSome text\n- A bullet\n";
        assert!(parse_unchecked_todos(input).is_empty());
    }

    #[test]
    fn parse_unchecked_todos_leading_whitespace() {
        let input = "  - [ ] Indented item\n";
        assert_eq!(parse_unchecked_todos(input), vec!["Indented item"]);
    }
}
