use super::arguments::ParsedArguments;
use super::parser::{Id, Link, MetaLine, QuotedString};

/// Represents an element in the Wasot document - either a Block, Text, ContextLine, or VoidElement
/// This implements the composite pattern where blocks can contain other elements
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Element {
    /// A structured block with type, parameters, and potentially nested elements
    Block(Block),
    /// Raw text content with line range information
    Text(Text),
    /// A context line that provides metadata without being part of the content hierarchy
    /// Context lines use the syntax `./mytag` and are managed by the system
    ContextLine(MetaLine),
    /// A void element that is self-closing and cannot have children
    /// Void elements use the syntax `.hr:` (trailing colon marks void element)
    VoidElement(MetaLine),
}

/// Represents a text element with line range information
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Text {
    /// Starting line number (inclusive)
    pub from: usize,
    /// Ending line number (exclusive, following programming convention)
    pub to: usize,
    /// The actual text lines
    pub lines: Vec<String>,
    /// Parsed links for each line (outer vec corresponds to lines, inner vec contains links found in that line)
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub links: Vec<Vec<Link>>,
}

impl Text {
    /// Create a new text element
    #[must_use]
    pub fn new(from: usize, to: usize, lines: Vec<String>) -> Self {
        Text {
            from,
            to,
            lines,
            links: Vec::new(),
        }
    }

    /// Create a new text element with links
    #[must_use]
    pub fn with_links(from: usize, to: usize, lines: Vec<String>, links: Vec<Vec<Link>>) -> Self {
        Text {
            from,
            to,
            lines,
            links,
        }
    }

    /// Create an empty text element
    #[must_use]
    pub fn empty() -> Self {
        Text {
            from: 0,
            to: 0,
            lines: Vec::new(),
            links: Vec::new(),
        }
    }

    /// Check if this text element is empty
    #[must_use]
    pub fn is_empty(&self) -> bool {
        self.lines.is_empty()
    }

    /// Get the content as a single string
    #[must_use]
    pub fn content_as_string(&self) -> String {
        self.lines.join("\n")
    }

    /// Get the number of lines
    #[must_use]
    pub fn line_count(&self) -> usize {
        self.lines.len()
    }
}

impl Element {
    /// Check if this element is empty
    /// Note: ContextLine and VoidElement are never considered empty as they always carry metadata
    #[must_use]
    pub fn is_empty(&self) -> bool {
        match self {
            Element::Block(block) => block.is_empty(),
            Element::Text(text) => text.is_empty(),
            Element::ContextLine(_) | Element::VoidElement(_) => false,
        }
    }

    /// Get the element as a block if it is one
    #[must_use]
    pub fn as_block(&self) -> Option<&Block> {
        match self {
            Element::Block(block) => Some(block),
            Element::Text(_) | Element::ContextLine(_) | Element::VoidElement(_) => None,
        }
    }

    /// Get the element as text if it is one
    #[must_use]
    pub fn as_text(&self) -> Option<&Text> {
        match self {
            Element::Text(text) => Some(text),
            Element::Block(_) | Element::ContextLine(_) | Element::VoidElement(_) => None,
        }
    }

    /// Get the element as a context line (MetaLine) if it is one
    #[must_use]
    pub fn as_context_line(&self) -> Option<&MetaLine> {
        match self {
            Element::ContextLine(meta_line) => Some(meta_line),
            Element::Block(_) | Element::Text(_) | Element::VoidElement(_) => None,
        }
    }

    /// Get the element as a void element (MetaLine) if it is one
    #[must_use]
    pub fn as_void_element(&self) -> Option<&MetaLine> {
        match self {
            Element::VoidElement(meta_line) => Some(meta_line),
            Element::Block(_) | Element::Text(_) | Element::ContextLine(_) => None,
        }
    }
}

/// Represents a hierarchical block in a Wasot document
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Block {
    /// The meta-line that defines this block (contains type, level, inline_text, id, arguments, etc.)
    pub meta_line: MetaLine,

    /// Child elements (blocks or text) nested within this block
    pub children: Vec<Element>,

    /// Optional parent reference (None for root blocks)
    /// Using an index into a parent container rather than a direct reference
    /// to avoid circular references and lifetime issues
    pub parent_index: Option<usize>,
}

impl Block {
    /// Create a new block from a meta-line
    #[must_use]
    pub fn new(meta_line: MetaLine) -> Self {
        Block {
            meta_line,
            children: Vec::new(),
            parent_index: None,
        }
    }

    /// Create an implicit text block at level 0
    #[must_use]
    pub fn new_implicit_text(line_index: usize) -> Self {
        let meta_line = MetaLine {
            type_name: "text".to_string(),
            level: 0,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(line_index),
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
            is_void: false,
        };
        Block::new(meta_line)
    }

    /// Create a heading block (self-closing)
    #[must_use]
    pub fn new_heading(mut meta_line: MetaLine) -> Self {
        // Headings use the type "#", "##", etc.
        let type_suffix = if meta_line.type_name.is_empty() {
            String::new()
        } else {
            format!(" {}", meta_line.type_name)
        };
        meta_line.type_name = format!("{}{}", "#".repeat(meta_line.level), type_suffix);
        Block::new(meta_line)
    }

    /// Add a content line to this block by wrapping it in a Text element
    pub fn add_content_line(&mut self, line: String, line_number: usize) {
        self.add_content_line_with_links(line, line_number, Vec::new());
    }

    /// Add a content line with parsed links to this block by wrapping it in a Text element
    pub fn add_content_line_with_links(
        &mut self,
        line: String,
        line_number: usize,
        line_links: Vec<Link>,
    ) {
        // If the last child is a text element, append to it
        if let Some(Element::Text(text)) = self.children.last_mut() {
            text.lines.push(line);
            text.links.push(line_links);
            text.to = line_number + 1;
        } else {
            // Create a new text element with links
            let text = Text::with_links(line_number, line_number + 1, vec![line], vec![line_links]);
            self.children.push(Element::Text(text));
        }
    }

    /// Add a child element to this block
    pub fn add_child(&mut self, child: Element) {
        self.children.push(child);
    }

    /// Add a child block to this block
    pub fn add_child_block(&mut self, mut child: Block, child_index: usize) {
        child.parent_index = Some(child_index);
        self.children.push(Element::Block(child));
    }

    /// Check if this block is a heading block
    #[must_use]
    pub fn is_heading(&self) -> bool {
        self.block_type().starts_with('#')
    }

    /// Check if this block is an implicit text block
    #[must_use]
    pub fn is_implicit_text(&self) -> bool {
        self.block_type() == "text" && self.level() == 0
    }

    /// Get the depth of nesting for this block (counting from root)
    #[must_use]
    pub fn depth(&self) -> usize {
        self.level()
    }

    /// Check if this block can contain the given child level
    #[must_use]
    pub fn can_contain_level(&self, child_level: usize) -> bool {
        child_level > self.level()
    }

    /// Get the total number of content lines in this block (counting text elements)
    #[must_use]
    pub fn content_line_count(&self) -> usize {
        self.children
            .iter()
            .map(|child| match child {
                Element::Text(text) => text.line_count(),
                Element::Block(_) | Element::ContextLine(_) | Element::VoidElement(_) => 0,
            })
            .sum()
    }

    /// Check if this block is empty (no children)
    #[must_use]
    pub fn is_empty(&self) -> bool {
        self.children.is_empty()
    }

    /// Get the MetaLine for this block
    #[must_use]
    pub fn to_meta_line(&self) -> MetaLine {
        self.meta_line.clone()
    }

    /// Get the block type
    #[must_use]
    pub fn block_type(&self) -> &str {
        &self.meta_line.type_name
    }

    /// Get the block level
    #[must_use]
    pub fn level(&self) -> usize {
        self.meta_line.level
    }

    /// Get the inline text
    #[must_use]
    pub fn inline_text(&self) -> &QuotedString {
        &self.meta_line.inline_text
    }

    /// Get the ID
    #[must_use]
    pub fn id(&self) -> &Id {
        &self.meta_line.id
    }

    /// Get the line index
    #[must_use]
    pub fn line_index(&self) -> usize {
        self.meta_line.line_index.unwrap_or(0)
    }

    /// Get the arguments
    #[must_use]
    pub fn arguments(&self) -> &ParsedArguments {
        &self.meta_line.arguments
    }
}

/// Container for managing a collection of blocks with proper parent-child relationships
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct BlockContainer {
    /// All blocks stored in a flat vector
    blocks: Vec<Block>,

    /// Indices of root-level blocks (those without parents)
    root_indices: Vec<usize>,
}

impl BlockContainer {
    /// Create a new empty block container
    #[must_use]
    pub fn new() -> Self {
        BlockContainer {
            blocks: Vec::new(),
            root_indices: Vec::new(),
        }
    }

    /// Add a block to the container and return its index
    pub fn add_block(&mut self, block: Block) -> usize {
        let index = self.blocks.len();
        self.blocks.push(block);

        // If this block has no parent, it's a root block
        if self.blocks[index].parent_index.is_none() {
            self.root_indices.push(index);
        }

        index
    }

    /// Get a block by index
    #[must_use]
    pub fn get_block(&self, index: usize) -> Option<&Block> {
        self.blocks.get(index)
    }

    /// Get a mutable reference to a block by index
    pub fn get_block_mut(&mut self, index: usize) -> Option<&mut Block> {
        self.blocks.get_mut(index)
    }

    /// Get all root blocks
    #[must_use]
    pub fn root_blocks(&self) -> Vec<&Block> {
        self.root_indices
            .iter()
            .filter_map(|&index| self.blocks.get(index))
            .collect()
    }

    /// Get the parent of a block by index
    #[must_use]
    pub fn get_parent(&self, index: usize) -> Option<&Block> {
        let block = self.blocks.get(index)?;
        let parent_index = block.parent_index?;
        self.blocks.get(parent_index)
    }

    /// Get all children of a block by index
    #[must_use]
    pub fn get_children(&self, index: usize) -> Vec<&Element> {
        if let Some(block) = self.blocks.get(index) {
            block.children.iter().collect()
        } else {
            Vec::new()
        }
    }

    /// Total number of blocks in the container
    #[must_use]
    pub fn len(&self) -> usize {
        self.blocks.len()
    }

    /// Check if the container is empty
    #[must_use]
    pub fn is_empty(&self) -> bool {
        self.blocks.is_empty()
    }
}

impl Default for BlockContainer {
    fn default() -> Self {
        Self::new()
    }
}

impl Block {
    /// Serialize this block to JSON
    pub fn to_json(&self) -> Result<String, serde_json::Error> {
        serde_json::to_string(self)
    }

    /// Serialize this block to pretty JSON
    pub fn to_json_pretty(&self) -> Result<String, serde_json::Error> {
        serde_json::to_string_pretty(self)
    }

    /// Deserialize a block from JSON
    pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(json)
    }
}

impl BlockContainer {
    /// Serialize this container to JSON
    pub fn to_json(&self) -> Result<String, serde_json::Error> {
        serde_json::to_string(self)
    }

    /// Serialize this container to pretty JSON
    pub fn to_json_pretty(&self) -> Result<String, serde_json::Error> {
        serde_json::to_string_pretty(self)
    }

    /// Deserialize a container from JSON
    pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(json)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::parsers::wasot::{Id, MetaLine};

    #[test]
    fn test_block_creation() {
        let meta_line = MetaLine {
            type_name: "p".to_string(),
            level: 1,
            inline_text: QuotedString::new("Some text".to_string(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new(meta_line);

        assert_eq!(block.block_type(), "p");
        assert_eq!(block.level(), 1);
        assert_eq!(block.inline_text().content, "Some text");
        assert!(block.children.is_empty());
        assert_eq!(block.parent_index, None);
    }

    #[test]
    fn test_implicit_text_block() {
        let block = Block::new_implicit_text(0);

        assert_eq!(block.block_type(), "text");
        assert_eq!(block.level(), 0);
        assert!(block.is_implicit_text());
        assert!(!block.is_heading());
    }

    #[test]
    fn test_heading_block() {
        let meta_line = MetaLine {
            type_name: String::new(),
            level: 2,
            inline_text: QuotedString::new("Heading Text".to_string(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new_heading(meta_line);

        assert_eq!(block.block_type(), "##");
        assert_eq!(block.level(), 2);
        assert!(block.is_heading());
        assert!(!block.is_implicit_text());
    }

    #[test]
    fn test_block_container() {
        let mut container = BlockContainer::new();

        let block1 = Block::new_implicit_text(0);
        let block2 = Block::new_implicit_text(0);

        let index1 = container.add_block(block1);
        let index2 = container.add_block(block2);

        assert_eq!(container.len(), 2);
        assert_eq!(container.root_indices.len(), 2);
        assert!(container.get_block(index1).is_some());
        assert!(container.get_block(index2).is_some());
    }

    #[test]
    fn test_content_operations() {
        let mut block = Block::new_implicit_text(0);

        assert!(block.is_empty());
        assert_eq!(block.content_line_count(), 0);

        block.add_content_line("First line".to_string(), 0);
        block.add_content_line("Second line".to_string(), 1);

        assert!(!block.is_empty());
        assert_eq!(block.content_line_count(), 2);
        let mut text_content = Vec::new();
        for child in &block.children {
            if let Element::Text(text) = child {
                text_content.extend(text.lines.clone());
            }
        }
        assert_eq!(text_content.join("\n"), "First line\nSecond line");
    }

    #[test]
    fn test_block_depth_and_level_checking() {
        let mut block = Block::new_implicit_text(0);
        block.meta_line.level = 2;

        assert_eq!(block.depth(), 2);
        assert!(block.can_contain_level(3));
        assert!(block.can_contain_level(4));
        assert!(!block.can_contain_level(2));
        assert!(!block.can_contain_level(1));
    }

    #[test]
    fn test_heading_with_type_name() {
        let meta_line = MetaLine {
            type_name: "chapter".to_string(),
            level: 1,
            inline_text: QuotedString::new("Introduction".to_string(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new_heading(meta_line);

        assert_eq!(block.block_type(), "# chapter");
        assert_eq!(block.level(), 1);
        assert!(block.is_heading());
    }

    #[test]
    fn test_add_child_block() {
        let mut parent = Block::new_implicit_text(0);
        let child = Block::new_implicit_text(0);

        parent.add_child_block(child, 5);

        assert_eq!(parent.children.len(), 1);
        if let Element::Block(child_block) = &parent.children[0] {
            assert_eq!(child_block.parent_index, Some(5));
        } else {
            panic!("Expected Block element");
        }
        assert!(!parent.is_empty()); // has children, so not empty
    }

    #[test]
    fn test_block_container_default() {
        let container = BlockContainer::default();
        assert!(container.is_empty());
        assert_eq!(container.len(), 0);
    }

    #[test]
    fn test_block_container_parent_child_operations() {
        let mut container = BlockContainer::new();

        let mut parent = Block::new_implicit_text(0);
        parent.meta_line.level = 1;
        let mut child = Block::new_implicit_text(0);
        child.meta_line.level = 2;
        child.parent_index = Some(0); // Will be parent

        let _parent_idx = container.add_block(parent);
        let child_idx = container.add_block(child);

        assert_eq!(container.len(), 2);
        assert_eq!(container.root_indices.len(), 1); // Only parent is root

        let parent_block = container.get_parent(child_idx);
        assert!(parent_block.is_some());
        assert_eq!(parent_block.unwrap().level(), 1);
    }

    #[test]
    fn test_block_container_mutable_access() {
        let mut container = BlockContainer::new();
        let block = Block::new_implicit_text(0);
        let idx = container.add_block(block);

        {
            let block_mut = container.get_block_mut(idx);
            assert!(block_mut.is_some());
            block_mut.unwrap().add_content_line("test".to_string(), 0);
        }

        let block = container.get_block(idx).unwrap();
        assert_eq!(block.content_line_count(), 1);
    }

    #[test]
    fn test_block_container_children() {
        let mut container = BlockContainer::new();
        let mut parent = Block::new_implicit_text(0);

        let child1 = Block::new_implicit_text(0);
        let child2 = Block::new_implicit_text(0);

        parent.add_child_block(child1, 1);
        parent.add_child_block(child2, 2);

        let idx = container.add_block(parent);
        let children = container.get_children(idx);

        assert_eq!(children.len(), 2);
    }

    #[test]
    fn test_block_container_invalid_indices() {
        let container = BlockContainer::new();

        assert!(container.get_block(999).is_none());
        assert!(container.get_parent(999).is_none());
        assert_eq!(container.get_children(999).len(), 0);
    }

    #[test]
    fn test_block_serialization() {
        let block = Block::new_implicit_text(0);

        let json = block.to_json();
        assert!(json.is_ok());

        let pretty_json = block.to_json_pretty();
        assert!(pretty_json.is_ok());

        let json_str = json.unwrap();
        let deserialized = Block::from_json(&json_str);
        assert!(deserialized.is_ok());
        assert_eq!(deserialized.unwrap(), block);
    }

    #[test]
    fn test_container_serialization() {
        let mut container = BlockContainer::new();
        container.add_block(Block::new_implicit_text(0));

        let json = container.to_json();
        assert!(json.is_ok());

        let pretty_json = container.to_json_pretty();
        assert!(pretty_json.is_ok());

        let json_str = json.unwrap();
        let deserialized = BlockContainer::from_json(&json_str);
        assert!(deserialized.is_ok());
        assert_eq!(deserialized.unwrap(), container);
    }

    #[test]
    fn test_get_text_content_empty() {
        let block = Block::new_implicit_text(0);
        let mut text_content = Vec::new();
        for child in &block.children {
            if let Element::Text(text) = child {
                text_content.extend(text.lines.clone());
            }
        }
        assert_eq!(text_content.join("\n"), "");
    }

    #[test]
    fn test_get_text_content_single_line() {
        let mut block = Block::new_implicit_text(0);
        block.add_content_line("single line".to_string(), 0);
        let mut text_content = Vec::new();
        for child in &block.children {
            if let Element::Text(text) = child {
                text_content.extend(text.lines.clone());
            }
        }
        assert_eq!(text_content.join("\n"), "single line");
    }

    #[test]
    fn test_block_with_id() {
        let meta_line = MetaLine {
            type_name: "div".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::new("my-id".to_string()),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new(meta_line);
        assert_eq!(block.id().value, "my-id");
    }

    #[test]
    fn test_text_creation() {
        let lines = vec!["First line".to_string(), "Second line".to_string()];
        let text = Text::new(1, 3, lines.clone());

        assert_eq!(text.from, 1);
        assert_eq!(text.to, 3);
        assert_eq!(text.lines, lines);
        assert!(!text.is_empty());
        assert_eq!(text.line_count(), 2);
        assert_eq!(text.content_as_string(), "First line\nSecond line");
    }

    #[test]
    fn test_text_empty() {
        let text = Text::empty();
        assert_eq!(text.from, 0);
        assert_eq!(text.to, 0);
        assert!(text.is_empty());
        assert_eq!(text.line_count(), 0);
        assert_eq!(text.content_as_string(), "");
        assert!(text.links.is_empty());
    }

    #[test]
    fn test_text_with_links() {
        use super::super::parser::{ExternalIdReference, TargetType};

        let lines = vec!["Text with a link".to_string()];
        let doc_ref = ExternalIdReference::parse("otherdoc.localid").unwrap();
        let link = Link {
            name: Some(QuotedString::new("link name".to_string(), false)),
            target: Some("otherdoc.localid".to_string()),
            target_type: TargetType::IdInDocument(doc_ref),
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
            start_index: 5,
            length: 10,
        };
        let links = vec![vec![link]];

        let text = Text::with_links(0, 1, lines.clone(), links.clone());

        assert_eq!(text.from, 0);
        assert_eq!(text.to, 1);
        assert_eq!(text.lines, lines);
        assert_eq!(text.links.len(), 1);
        assert_eq!(text.links[0].len(), 1);
        assert!(matches!(
            text.links[0][0].target_type,
            TargetType::IdInDocument(_)
        ));
    }

    #[test]
    fn test_text_new_has_empty_links() {
        let text = Text::new(0, 1, vec!["line".to_string()]);
        assert!(text.links.is_empty());
    }

    #[test]
    fn test_element_block_variant() {
        let mut block = Block::new_implicit_text(0);
        block.add_content_line("Some content".to_string(), 0);
        let element = Element::Block(block.clone());

        assert!(!element.is_empty());
        assert!(element.as_block().is_some());
        assert!(element.as_text().is_none());
        assert_eq!(element.as_block().unwrap(), &block);
    }

    #[test]
    fn test_element_text_variant() {
        let text = Text::new(1, 2, vec!["content".to_string()]);
        let element = Element::Text(text.clone());

        assert!(!element.is_empty());
        assert!(element.as_text().is_some());
        assert!(element.as_block().is_none());
        assert_eq!(element.as_text().unwrap(), &text);
    }

    #[test]
    fn test_element_empty() {
        let empty_text = Text::empty();
        let element = Element::Text(empty_text);
        assert!(element.is_empty());

        let empty_block = Block::new_implicit_text(0);
        let element = Element::Block(empty_block);
        assert!(element.is_empty());
    }

    #[test]
    fn test_get_text_content_mixed_elements() {
        let mut block = Block::new_implicit_text(0);

        // Add some text content
        block.add_content_line("First line".to_string(), 0);
        block.add_content_line("Second line".to_string(), 1);

        // Add a nested block
        let nested_block = Block::new_implicit_text(0);
        block.add_child(Element::Block(nested_block));

        // Add more text content
        let text_element = Text::new(2, 3, vec!["Third line".to_string()]);
        block.add_child(Element::Text(text_element));

        let mut text_content = Vec::new();
        for child in &block.children {
            if let Element::Text(text) = child {
                text_content.extend(text.lines.clone());
            }
        }
        assert_eq!(text_content.len(), 3); // Only text elements, ignoring nested block
        assert_eq!(text_content[0], "First line");
        assert_eq!(text_content[1], "Second line");
        assert_eq!(text_content[2], "Third line");
    }

    // ==============================================================================
    // Additional Tests for Specific Coverage Lines
    // ==============================================================================

    #[test]
    fn test_text_new() {
        // Test line 28 - Text::new function
        let text = Text::new(5, 10, vec!["line1".to_string(), "line2".to_string()]);
        assert_eq!(text.from, 5);
        assert_eq!(text.to, 10);
        assert_eq!(text.lines.len(), 2);
    }

    #[test]
    fn test_text_empty_detailed() {
        // Test line 34 - Text::empty function call
        let text = Text::empty();
        assert_eq!(text.from, 0);
        assert_eq!(text.to, 0);
        assert_eq!(text.lines.len(), 0);

        // Test line 38 - lines: Vec::new() in empty
        assert!(text.lines.is_empty());
    }

    #[test]
    fn test_text_is_empty() {
        // Test lines 44-45 - Text::is_empty function
        let empty_text = Text::empty();
        assert!(empty_text.is_empty());

        let non_empty_text = Text::new(0, 1, vec!["content".to_string()]);
        assert!(!non_empty_text.is_empty());
    }

    #[test]
    fn test_text_content_as_string() {
        // Test lines 50-51 - Text::content_as_string function
        let text = Text::new(
            0,
            3,
            vec![
                "line1".to_string(),
                "line2".to_string(),
                "line3".to_string(),
            ],
        );
        let content = text.content_as_string();
        assert_eq!(content, "line1\nline2\nline3");

        // Test with empty text
        let empty_text = Text::empty();
        assert_eq!(empty_text.content_as_string(), "");
    }

    #[test]
    fn test_text_line_count() {
        // Test lines 56-57 - Text::line_count function
        let text = Text::new(
            0,
            5,
            vec![
                "a".to_string(),
                "b".to_string(),
                "c".to_string(),
                "d".to_string(),
                "e".to_string(),
            ],
        );
        assert_eq!(text.line_count(), 5);

        let empty_text = Text::empty();
        assert_eq!(empty_text.line_count(), 0);
    }

    #[test]
    fn test_element_is_empty_detailed() {
        // Test lines 64-67 - Element::is_empty function
        let empty_block = Block::new_implicit_text(0);
        let block_element = Element::Block(empty_block);
        assert!(block_element.is_empty());

        let empty_text = Text::empty();
        let text_element = Element::Text(empty_text);
        assert!(text_element.is_empty());
    }

    #[test]
    fn test_element_as_block_detailed() {
        // Test lines 73-76 - Element::as_block function
        let block = Block::new_implicit_text(0);
        let block_element = Element::Block(block.clone());

        // Test Some case
        assert!(block_element.as_block().is_some());
        assert_eq!(block_element.as_block().unwrap(), &block);

        // Test None case with text
        let text = Text::empty();
        let text_element = Element::Text(text);
        assert!(text_element.as_block().is_none());
    }

    #[test]
    fn test_element_as_text_detailed() {
        // Test lines 82-85 - Element::as_text function
        let text = Text::new(0, 1, vec!["test".to_string()]);
        let text_element = Element::Text(text.clone());

        // Test Some case
        assert!(text_element.as_text().is_some());
        assert_eq!(text_element.as_text().unwrap(), &text);

        // Test None case with block
        let block = Block::new_implicit_text(0);
        let block_element = Element::Block(block);
        assert!(block_element.as_text().is_none());
    }

    #[test]
    fn test_block_new_detailed() {
        // Test line 108 - Block::new function declaration
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new(meta_line.clone());

        // Test line 111 - children: Vec::new() initialization
        assert_eq!(block.children.len(), 0);
        assert_eq!(block.meta_line, meta_line);
        assert_eq!(block.parent_index, None);
    }

    #[test]
    fn test_block_new_implicit_text_detailed() {
        // Test line 118 - new_implicit_text function declaration
        let block = Block::new_implicit_text(42);

        // Test line 120 - type_name assignment
        assert_eq!(block.meta_line.type_name, "text");

        // Test lines 122-125 - field assignments
        assert_eq!(block.meta_line.level, 0);
        assert_eq!(block.meta_line.inline_text.content, "");
        assert!(!block.meta_line.inline_text.quoted);
        assert_eq!(block.meta_line.line_index, Some(42));

        // Test line 130 - Block::new call
        assert_eq!(block.children.len(), 0);
        assert_eq!(block.parent_index, None);
    }

    #[test]
    fn test_block_new_heading_detailed() {
        // Test line 135 - new_heading function declaration
        let meta_line = MetaLine {
            type_name: "title".to_string(),
            level: 3,
            inline_text: QuotedString::new("My Heading".to_string(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new_heading(meta_line);

        // Test lines 137-138 - type_suffix logic for non-empty type_name
        assert_eq!(block.meta_line.type_name, "### title");

        // Test line 140 - format! with type suffix
        // Test lines 142-143 - type_name assignment and Block::new call
        assert_eq!(block.level(), 3);
        assert!(block.is_heading());
    }

    #[test]
    fn test_block_new_heading_empty_type() {
        // Test empty type_name case in new_heading
        let meta_line = MetaLine {
            type_name: String::new(),
            level: 2,
            inline_text: QuotedString::new("Plain Heading".to_string(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new_heading(meta_line);
        assert_eq!(block.meta_line.type_name, "##");
    }

    #[test]
    fn test_add_content_line_detailed() {
        // Test line 147 - add_content_line function
        let mut block = Block::new_implicit_text(0);

        // Test lines 149-151 - append to existing text element
        block.add_content_line("first".to_string(), 0);
        assert_eq!(block.children.len(), 1);

        block.add_content_line("second".to_string(), 1);
        assert_eq!(block.children.len(), 1); // Still one text element

        if let Element::Text(text) = &block.children[0] {
            assert_eq!(text.lines.len(), 2);
            assert_eq!(text.to, 2); // line_number + 1
        }

        // Test lines 154-155 - create new text element when last is not text
        let nested_block = Block::new_implicit_text(0);
        block.add_child(Element::Block(nested_block));

        block.add_content_line("third".to_string(), 2);
        assert_eq!(block.children.len(), 3); // text, block, text
    }

    #[test]
    fn test_add_content_line_with_links() {
        use super::super::parser::{ExternalIdReference, TargetType};

        let mut block = Block::new_implicit_text(0);

        // Create a link with IdInDocument target
        let doc_ref = ExternalIdReference::parse("readme.intro").unwrap();
        let link = Link {
            name: Some(QuotedString::new("see readme".to_string(), false)),
            target: Some("readme.intro".to_string()),
            target_type: TargetType::IdInDocument(doc_ref),
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
            start_index: 0,
            length: 20,
        };

        // Add first line with a link
        block.add_content_line_with_links("Text with link".to_string(), 0, vec![link.clone()]);
        assert_eq!(block.children.len(), 1);

        if let Element::Text(text) = &block.children[0] {
            assert_eq!(text.lines.len(), 1);
            assert_eq!(text.links.len(), 1);
            assert_eq!(text.links[0].len(), 1);
            assert!(matches!(
                text.links[0][0].target_type,
                TargetType::IdInDocument(_)
            ));
        } else {
            panic!("Expected Text element");
        }

        // Add second line without links - should append to existing Text
        block.add_content_line_with_links("Plain text".to_string(), 1, vec![]);
        assert_eq!(block.children.len(), 1); // Still one element

        if let Element::Text(text) = &block.children[0] {
            assert_eq!(text.lines.len(), 2);
            assert_eq!(text.links.len(), 2);
            assert_eq!(text.links[0].len(), 1); // First line has link
            assert_eq!(text.links[1].len(), 0); // Second line has no links
        } else {
            panic!("Expected Text element");
        }
    }

    #[test]
    fn test_add_child_detailed() {
        // Test lines 160-161 - add_child function
        let mut block = Block::new_implicit_text(0);
        let text_element = Element::Text(Text::new(0, 1, vec!["test".to_string()]));

        block.add_child(text_element);
        assert_eq!(block.children.len(), 1);
    }

    #[test]
    fn test_add_child_block_detailed() {
        // Test lines 165-167 - add_child_block function
        let mut parent = Block::new_implicit_text(0);
        let child = Block::new_implicit_text(0);

        parent.add_child_block(child, 42);

        assert_eq!(parent.children.len(), 1);
        if let Element::Block(child_block) = &parent.children[0] {
            assert_eq!(child_block.parent_index, Some(42));
        }
    }

    #[test]
    fn test_is_heading_detailed() {
        // Test lines 172-173 - is_heading function
        let heading_block = Block::new_heading(MetaLine {
            type_name: String::new(),
            level: 1,
            inline_text: QuotedString::new("Heading".to_string(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        });

        assert!(heading_block.is_heading());

        let regular_block = Block::new_implicit_text(0);
        assert!(!regular_block.is_heading());
    }

    #[test]
    fn test_is_implicit_text_detailed() {
        // Test lines 178-179 - is_implicit_text function
        let implicit_text_block = Block::new_implicit_text(0);
        assert!(implicit_text_block.is_implicit_text());

        let mut regular_block = Block::new_implicit_text(0);
        regular_block.meta_line.level = 1;
        assert!(!regular_block.is_implicit_text()); // level != 0

        let mut non_text_block = Block::new_implicit_text(0);
        non_text_block.meta_line.type_name = "div".to_string();
        assert!(!non_text_block.is_implicit_text()); // type != "text"
    }

    #[test]
    fn test_depth_detailed() {
        // Test lines 184-185 - depth function
        let mut block = Block::new_implicit_text(0);
        block.meta_line.level = 5;
        assert_eq!(block.depth(), 5);
    }

    #[test]
    fn test_can_contain_level_detailed() {
        // Test lines 190-191 - can_contain_level function
        let mut block = Block::new_implicit_text(0);
        block.meta_line.level = 3;

        assert!(block.can_contain_level(4));
        assert!(block.can_contain_level(5));
        assert!(!block.can_contain_level(3));
        assert!(!block.can_contain_level(2));
        assert!(!block.can_contain_level(1));
    }

    #[test]
    fn test_content_line_count_detailed() {
        // Test lines 196-197, 199-201 - content_line_count function
        let mut block = Block::new_implicit_text(0);

        // Add text elements
        let text1 = Text::new(0, 2, vec!["line1".to_string(), "line2".to_string()]);
        let text2 = Text::new(2, 4, vec!["line3".to_string(), "line4".to_string()]);

        block.add_child(Element::Text(text1));
        block.add_child(Element::Text(text2));

        // Add a block element (should contribute 0 to line count)
        let nested_block = Block::new_implicit_text(0);
        block.add_child(Element::Block(nested_block));

        assert_eq!(block.content_line_count(), 4); // Only text elements count
    }

    #[test]
    fn test_block_is_empty_detailed() {
        // Test lines 208-209 - Block::is_empty function
        let empty_block = Block::new_implicit_text(0);
        assert!(empty_block.is_empty());

        let mut non_empty_block = Block::new_implicit_text(0);
        non_empty_block.add_content_line("content".to_string(), 0);
        assert!(!non_empty_block.is_empty());
    }

    #[test]
    fn test_to_meta_line_detailed() {
        // Test lines 214-215 - to_meta_line function
        let original_meta_line = MetaLine {
            type_name: "section".to_string(),
            level: 2,
            inline_text: QuotedString::new("Section Title".to_string(), true),
            id: Id::new("sec1".to_string()),
            line_index: Some(42),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new(original_meta_line.clone());
        let cloned_meta_line = block.to_meta_line();

        assert_eq!(cloned_meta_line, original_meta_line);
    }

    #[test]
    fn test_block_type_detailed() {
        // Test lines 220-221 - block_type function
        let meta_line = MetaLine {
            type_name: "custom_type".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new(meta_line);
        assert_eq!(block.block_type(), "custom_type");
    }

    #[test]
    fn test_level_detailed() {
        // Test lines 226-227 - level function
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 7,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new(meta_line);
        assert_eq!(block.level(), 7);
    }

    #[test]
    fn test_inline_text_detailed() {
        // Test lines 232-233 - inline_text function
        let quoted_string = QuotedString::new("Inline content".to_string(), true);
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: quoted_string.clone(),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new(meta_line);
        assert_eq!(block.inline_text(), &quoted_string);
    }

    #[test]
    fn test_id_detailed() {
        // Test lines 238-239 - id function
        let id = Id::new("test_id".to_string());
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: id.clone(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new(meta_line);
        assert_eq!(block.id(), &id);
    }

    #[test]
    fn test_line_index_detailed() {
        // Test lines 244-245 - line_index function
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(123),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };

        let block = Block::new(meta_line.clone());
        assert_eq!(block.line_index(), 123);

        // Test unwrap_or(0) case
        let mut meta_line_no_index = meta_line;
        meta_line_no_index.line_index = None;
        let block_no_index = Block::new(meta_line_no_index);
        assert_eq!(block_no_index.line_index(), 0);
    }

    #[test]
    fn test_arguments_detailed() {
        // Test lines 250-251 - arguments function
        let args = ParsedArguments {
            args: vec![QuotedString::new("arg1".to_string(), false)],
            kwargs: vec![(
                QuotedString::new("key".to_string(), false),
                QuotedString::new("value".to_string(), false),
            )],
        };
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: args.clone(),
        };

        let block = Block::new(meta_line);
        assert_eq!(block.arguments(), &args);
    }

    #[test]
    fn test_block_container_new_detailed() {
        // Test line 268 - BlockContainer::new function
        let container = BlockContainer::new();

        // Test lines 270-271 - initialization
        assert_eq!(container.blocks.len(), 0);
        assert_eq!(container.root_indices.len(), 0);
        assert!(container.is_empty());
    }

    #[test]
    fn test_block_container_add_block_detailed() {
        // Test lines 276-278 - add_block function
        let mut container = BlockContainer::new();
        let block = Block::new_implicit_text(0);

        let index = container.add_block(block);
        assert_eq!(index, 0);
        assert_eq!(container.blocks.len(), 1);

        // Test lines 281-282 - root block detection
        assert_eq!(container.root_indices.len(), 1);
        assert_eq!(container.root_indices[0], 0);
    }

    #[test]
    fn test_block_container_get_block_detailed() {
        // Test lines 290-291 - get_block function
        let mut container = BlockContainer::new();
        let block = Block::new_implicit_text(0);
        let index = container.add_block(block);

        let retrieved = container.get_block(index);
        assert!(retrieved.is_some());

        let invalid = container.get_block(999);
        assert!(invalid.is_none());
    }

    #[test]
    fn test_block_container_get_block_mut_detailed() {
        // Test lines 295-296 - get_block_mut function
        let mut container = BlockContainer::new();
        let block = Block::new_implicit_text(0);
        let index = container.add_block(block);

        let retrieved_mut = container.get_block_mut(index);
        assert!(retrieved_mut.is_some());

        let invalid_mut = container.get_block_mut(999);
        assert!(invalid_mut.is_none());
    }

    #[test]
    fn test_block_container_non_root_block() {
        // Test adding a block with a parent (not a root block)
        let mut container = BlockContainer::new();

        // Add parent first
        let parent_block = Block::new_implicit_text(0);
        let parent_index = container.add_block(parent_block);

        // Add child with parent reference
        let mut child_block = Block::new_implicit_text(0);
        child_block.parent_index = Some(parent_index);
        let child_index = container.add_block(child_block);

        // Should only have 1 root (the parent)
        assert_eq!(container.root_indices.len(), 1);
        assert_eq!(container.len(), 2);
        assert_eq!(container.root_indices[0], parent_index);

        // Child should not be in root_indices
        assert!(!container.root_indices.contains(&child_index));
    }

    #[test]
    fn test_root_blocks_detailed() {
        // Test lines 301-304 - root_blocks function
        let mut container = BlockContainer::new();

        // Create root blocks
        let root1_meta = MetaLine {
            type_name: "root1".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let root1 = Block::new(root1_meta);
        let _root1_index = container.add_block(root1);

        let root2_meta = MetaLine {
            type_name: "root2".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let root2 = Block::new(root2_meta);
        let _root2_index = container.add_block(root2);

        let roots = container.root_blocks();
        assert_eq!(roots.len(), 2);
        assert_eq!(roots[0].block_type(), "root1");
        assert_eq!(roots[1].block_type(), "root2");
    }

    #[test]
    fn test_get_parent_detailed() {
        // Test lines 310-313 - get_parent function
        let mut container = BlockContainer::new();

        // Create parent block
        let parent_meta = MetaLine {
            type_name: "parent".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let parent = Block::new(parent_meta);
        let parent_index = container.add_block(parent);

        // Create child block with parent reference
        let child_meta = MetaLine {
            type_name: "child".to_string(),
            level: 2,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let mut child = Block::new(child_meta);
        child.parent_index = Some(parent_index);
        let child_index = container.add_block(child);

        // Test getting parent
        let parent = container.get_parent(child_index);
        assert!(parent.is_some());
        assert_eq!(parent.unwrap().block_type(), "parent");

        // Test block without parent
        let no_parent = container.get_parent(parent_index);
        assert!(no_parent.is_none());

        // Test invalid index
        let invalid = container.get_parent(999);
        assert!(invalid.is_none());
    }

    #[test]
    fn test_get_children_detailed() {
        // Test lines 318-322 - get_children function
        let mut container = BlockContainer::new();

        let parent_meta = MetaLine {
            type_name: "parent".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let mut parent = Block::new(parent_meta);

        // Add child elements to the parent
        let child1 = Element::Text(Text::new(0, 1, vec!["child1".to_string()]));
        let child2 = Element::Text(Text::new(0, 1, vec!["child2".to_string()]));
        parent.children.push(child1);
        parent.children.push(child2);

        let parent_index = container.add_block(parent);

        // Test getting children
        let children = container.get_children(parent_index);
        assert_eq!(children.len(), 2);

        // Test with invalid index
        let no_children = container.get_children(999);
        assert_eq!(no_children.len(), 0);
    }

    #[test]
    fn test_container_len_detailed() {
        // Test lines 328-329 - len function
        let mut container = BlockContainer::new();
        assert_eq!(container.len(), 0);

        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let block = Block::new(meta_line);
        container.add_block(block);
        assert_eq!(container.len(), 1);
    }

    #[test]
    fn test_container_is_empty_detailed() {
        // Test lines 334-335 - is_empty function
        let mut container = BlockContainer::new();
        assert!(container.is_empty());

        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let block = Block::new(meta_line);
        container.add_block(block);
        assert!(!container.is_empty());
    }

    #[test]
    fn test_container_default_detailed() {
        // Test lines 340-341 - default function for BlockContainer
        let container = BlockContainer::default();
        assert_eq!(container.len(), 0);
        assert!(container.is_empty());
    }

    #[test]
    fn test_block_to_json_detailed() {
        // Test lines 347-348 - to_json function for Block
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new("inline text".to_string(), false),
            id: Id::new("test_id".to_string()),
            line_index: Some(42),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let block = Block::new(meta_line);

        let json = block.to_json();
        assert!(json.is_ok());
        let json_str = json.unwrap();
        assert!(json_str.contains("test"));
        assert!(json_str.contains("inline text"));
        assert!(json_str.contains("test_id"));
    }

    #[test]
    fn test_block_to_json_pretty_detailed() {
        // Test lines 352-353 - to_json_pretty function for Block
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new("inline text".to_string(), false),
            id: Id::new("test_id".to_string()),
            line_index: Some(42),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let block = Block::new(meta_line);

        let json = block.to_json_pretty();
        assert!(json.is_ok());
        let json_str = json.unwrap();
        assert!(json_str.contains("test"));
        assert!(json_str.contains("inline text"));
        assert!(json_str.contains("test_id"));
        // Pretty JSON should contain newlines and indentation
        assert!(json_str.contains('\n'));
    }

    #[test]
    fn test_block_from_json_detailed() {
        // Test lines 357-358 - from_json function for Block
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new("inline text".to_string(), false),
            id: Id::new("test_id".to_string()),
            line_index: Some(42),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let original_block = Block::new(meta_line);

        // Serialize to JSON and then deserialize
        let json_str = original_block.to_json().unwrap();
        let deserialized_block = Block::from_json(&json_str);

        assert!(deserialized_block.is_ok());
        let deserialized = deserialized_block.unwrap();
        assert_eq!(deserialized.block_type(), "test");
        assert_eq!(deserialized.level(), 1);
        assert_eq!(deserialized.line_index(), 42);

        // Test with invalid JSON
        let invalid_result = Block::from_json("invalid json");
        assert!(invalid_result.is_err());
    }

    #[test]
    fn test_container_to_json_detailed() {
        // Test lines 364-365 - to_json function for BlockContainer
        let mut container = BlockContainer::new();
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let block = Block::new(meta_line);
        container.add_block(block);

        let json = container.to_json();
        assert!(json.is_ok());
        let json_str = json.unwrap();
        assert!(json_str.contains("test"));
    }

    #[test]
    fn test_container_to_json_pretty_detailed() {
        // Test lines 369-370 - to_json_pretty function for BlockContainer
        let mut container = BlockContainer::new();
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let block = Block::new(meta_line);
        container.add_block(block);

        let json = container.to_json_pretty();
        assert!(json.is_ok());
        let json_str = json.unwrap();
        assert!(json_str.contains("test"));
        // Pretty JSON should contain newlines
        assert!(json_str.contains('\n'));
    }

    #[test]
    fn test_container_from_json_detailed() {
        // Test lines 374-375 - from_json function for BlockContainer
        let mut original_container = BlockContainer::new();
        let meta_line = MetaLine {
            type_name: "test".to_string(),
            level: 1,
            inline_text: QuotedString::new(String::new(), false),
            id: Id::empty(),
            line_index: Some(0),
            is_void: false,
            arguments: ParsedArguments {
                args: Vec::new(),
                kwargs: Vec::new(),
            },
        };
        let block = Block::new(meta_line);
        original_container.add_block(block);

        // Serialize to JSON and then deserialize
        let json_str = original_container.to_json().unwrap();
        let deserialized_container = BlockContainer::from_json(&json_str);

        assert!(deserialized_container.is_ok());
        let deserialized = deserialized_container.unwrap();
        assert_eq!(deserialized.len(), 1);

        // Test with invalid JSON
        let invalid_result = BlockContainer::from_json("invalid json");
        assert!(invalid_result.is_err());
    }
}
