//! Facade pattern for simple parser usage
//!
//! This module provides a simple interface for the Wasot parser:
//! Lines in → Events out

use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;

use crate::parsers::wasot::element_parser::ElementParser;
// ====================================================== OLD CODE ===============================================================================================

/// Simple facade for the Wasot parser
///
/// This provides a high-level interface for parsing Wasot markup language.
/// It handles the event-driven architecture internally while providing
/// simple methods for processing input.
///
/// # Examples
///
/// ## Basic Usage
/// ```
/// use wasot_compiler::WasotParser;
///
/// let mut parser = WasotParser::new();
///
/// // Parse a simple Wasot document
/// let result = parser.read_string(".p\nHello World\n..span\nNested content");
/// assert!(result.is_ok());
/// ```
///
/// ## Processing Individual Lines
/// ```
/// use wasot_compiler::WasotParser;
///
/// let mut parser = WasotParser::new();
///
/// // Process lines one by one
/// parser.process_line(".div").unwrap();
/// parser.process_line("Some content").unwrap();
/// parser.process_line("..p").unwrap();
/// parser.process_line("Nested paragraph").unwrap();
/// ```
///
pub struct WasotParser {
    element_parser: ElementParser,
}

impl WasotParser {
    /// Create a new parser instance
    ///
    /// # Examples
    /// ```
    /// use wasot_compiler::WasotParser;
    ///
    /// let parser = WasotParser::new();
    /// // Parser is ready to process Wasot content
    /// ```
    pub fn new() -> Self {
        let element_parser = ElementParser::new();

        Self { element_parser }
    }

    /// Process a single line of input
    ///
    /// This is the core method - feed lines one by one and get events out.
    /// Note that blocks remain open until explicitly closed or until parsing
    /// is finished.
    ///
    /// # Examples
    /// ```
    /// use wasot_compiler::WasotParser;
    ///
    /// let mut parser = WasotParser::new();
    ///
    /// // Process a block definition
    /// parser.process_line(".p").unwrap();
    ///
    /// // Add content to the block
    /// parser.process_line("Hello World").unwrap();
    ///
    /// // Process another block
    /// parser.process_line("..span").unwrap();
    /// parser.process_line("Nested content").unwrap();
    /// ```
    ///
    /// # Errors
    /// Returns an error if the line cannot be parsed or contains invalid syntax.
    pub fn process_line(&mut self, line: &str) -> Result<(), String> {
        let _closed_count = self.element_parser.process_line(line, 0)?;
        Ok(())
    }

    /// Read and process an entire file
    ///
    /// Uses streaming to process the file line by line, automatically
    /// finishing parsing when complete.
    ///
    /// # Examples
    /// ```no_run
    /// use wasot_compiler::WasotParser;
    ///
    /// let mut parser = WasotParser::new();
    ///
    /// // Process a Wasot file
    /// parser.read_file("document.wasot").unwrap();
    /// ```
    ///
    /// # Errors
    /// Returns an error if the file cannot be read or contains invalid syntax.
    pub fn read_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Box<dyn std::error::Error>> {
        let file = File::open(path)?;
        let reader = BufReader::new(file);

        // Process each line
        for (line_num, line) in reader.lines().enumerate() {
            let line = line?;
            self.element_parser.process_line(&line, line_num)?;
        }

        // Finish processing
        let _closed_count = self.element_parser.finish()?;

        Ok(())
    }

    /// Read and process from a string
    ///
    /// Processes the entire string content, automatically finishing
    /// parsing when complete.
    ///
    /// # Examples
    /// ```
    /// use wasot_compiler::WasotParser;
    ///
    /// let mut parser = WasotParser::new();
    ///
    /// let wasot_content = r#"
    /// .article
    /// Introduction paragraph
    ///
    /// ..h2
    /// Section Heading
    ///
    /// ..p
    /// More content here
    /// "#;
    ///
    /// parser.read_string(wasot_content).unwrap();
    /// ```
    ///
    /// # Errors
    /// Returns an error if the content contains invalid syntax.
    pub fn read_string(&mut self, content: &str) -> Result<(), String> {
        // Process each line
        for (line_num, line) in content.lines().enumerate() {
            self.element_parser.process_line(line, line_num)?;
        }

        // Finish processing
        let _closed_count = self.element_parser.finish()?;

        Ok(())
    }
}

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

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Write;
    use tempfile::NamedTempFile;

    #[test]
    fn test_parser_creation() {
        let _parser = WasotParser::new();
        // Parser creation successful - just checking it doesn't panic
    }

    #[test]
    fn test_parser_default() {
        let _parser = WasotParser::default();
        // Default parser creation successful - just checking it doesn't panic
    }

    #[test]
    fn test_process_single_line() {
        let mut parser = WasotParser::new();
        let result = parser.process_line(".p");
        assert!(result.is_ok());
    }

    #[test]
    fn test_process_multiple_lines() {
        let mut parser = WasotParser::new();

        parser.process_line(".div").unwrap();
        parser.process_line("Content line").unwrap();
        parser.process_line("..p").unwrap();
        parser.process_line("Nested content").unwrap();

        // Processing should be successful - just checking it doesn't panic
    }

    #[test]
    fn test_read_string() {
        let mut parser = WasotParser::new();
        let content = ".p\nHello World\n..span\nNested text";
        let result = parser.read_string(content);
        assert!(result.is_ok());
    }

    #[test]
    fn test_read_file_success() {
        let mut parser = WasotParser::new();

        // Create a temporary file
        let mut temp_file = NamedTempFile::new().unwrap();
        writeln!(temp_file, ".div").unwrap();
        writeln!(temp_file, "File content").unwrap();
        writeln!(temp_file, "..p").unwrap();
        writeln!(temp_file, "Nested content").unwrap();
        temp_file.flush().unwrap();

        let result = parser.read_file(temp_file.path());
        assert!(result.is_ok());
    }

    #[test]
    fn test_read_file_not_found() {
        let mut parser = WasotParser::new();
        let result = parser.read_file("/non/existent/file.wasot");
        assert!(result.is_err());

        // Should be an IO error
        let error_string = result.unwrap_err().to_string();
        assert!(error_string.contains("No such file") || error_string.contains("cannot find"));
    }

    #[test]
    fn test_read_empty_string() {
        let mut parser = WasotParser::new();
        let result = parser.read_string("");
        assert!(result.is_ok());
    }

    #[test]
    fn test_read_string_with_only_text() {
        let mut parser = WasotParser::new();
        let content = "Just some text\nMore text";
        let result = parser.read_string(content);
        assert!(result.is_ok());
    }

    #[test]
    fn test_error_handling_in_process_line() {
        let mut parser = WasotParser::new();

        // Process a line that creates a block
        parser.process_line(".div").unwrap();

        // Try to close a block when we don't have any open
        // Actually this should work since we do have a block open
        let result = parser.process_line("./");
        assert!(result.is_ok());
    }

    #[test]
    fn test_line_numbering_in_read_string() {
        let mut parser = WasotParser::new();
        let content = "Line 0\n.p\nLine 2\nLine 3";
        let result = parser.read_string(content);
        assert!(result.is_ok());
    }

    #[test]
    fn test_new_initializes_element_parser() {
        let parser = WasotParser::new();

        // Test that the parser has an element parser initialized
        // We can't access it directly, but we can test that it works by processing lines
        // The new() function creates an ElementParser and stores it
        assert_eq!(parser.element_parser.current_depth(), 0);
    }

    #[test]
    fn test_process_line_calls_element_parser() {
        let mut parser = WasotParser::new();

        // Test that process_line properly delegates to element parser
        let result = parser.process_line(".div");
        assert!(result.is_ok());

        // Verify the element parser received the line by checking depth
        assert_eq!(parser.element_parser.current_depth(), 1);

        // Add content line
        let result = parser.process_line("Content");
        assert!(result.is_ok());

        // Depth should remain the same for content lines
        assert_eq!(parser.element_parser.current_depth(), 1);
    }

    #[test]
    fn test_close_block_ignored_when_nothing_open() {
        let mut parser = WasotParser::new();

        // Closing a block without opening one first should be silently ignored
        let result = parser.process_line("./");
        assert!(result.is_ok());
    }

    #[test]
    fn test_read_file_opens_and_reads() {
        let mut parser = WasotParser::new();

        // Create a temporary file with specific content
        let mut temp_file = NamedTempFile::new().unwrap();
        writeln!(temp_file, ".article").unwrap();
        writeln!(temp_file, "Article content").unwrap();
        writeln!(temp_file, "..section").unwrap();
        writeln!(temp_file, "Section content").unwrap();
        temp_file.flush().unwrap();

        // Test that read_file successfully opens and reads the file
        let result = parser.read_file(temp_file.path());
        assert!(result.is_ok());

        // Verify that the file was processed by checking the parser state
        // All blocks should be finished after read_file completes
        assert_eq!(parser.element_parser.current_depth(), 0);
    }

    #[test]
    fn test_read_file_line_enumeration() {
        let mut parser = WasotParser::new();

        // Create a multi-line file
        let mut temp_file = NamedTempFile::new().unwrap();
        writeln!(temp_file, "First line").unwrap();
        writeln!(temp_file, ".p").unwrap();
        writeln!(temp_file, "Third line").unwrap();
        writeln!(temp_file, "Fourth line").unwrap();
        temp_file.flush().unwrap();

        // The read_file method should enumerate lines correctly
        let result = parser.read_file(temp_file.path());
        assert!(result.is_ok());
    }

    #[test]
    fn test_read_file_io_error() {
        let mut parser = WasotParser::new();

        // Test with a path that doesn't exist
        let result = parser.read_file("/absolutely/nonexistent/path/file.wasot");
        assert!(result.is_err());

        // Should be an IO error from File::open
        let error = result.unwrap_err();
        // The error should be related to file not found
        let error_msg = error.to_string();
        assert!(
            error_msg.contains("No such file")
                || error_msg.contains("cannot find")
                || error_msg.contains("not found")
        );
    }

    #[test]
    fn test_read_file_finish_processing() {
        let mut parser = WasotParser::new();

        // Create a file with unclosed blocks
        let mut temp_file = NamedTempFile::new().unwrap();
        writeln!(temp_file, ".div").unwrap();
        writeln!(temp_file, "..p").unwrap();
        writeln!(temp_file, "Content").unwrap();
        // Note: blocks are not explicitly closed
        temp_file.flush().unwrap();

        let result = parser.read_file(temp_file.path());
        assert!(result.is_ok());

        // After read_file, all blocks should be finished
        assert_eq!(parser.element_parser.current_depth(), 0);
    }

    #[test]
    fn test_read_string_line_processing() {
        let mut parser = WasotParser::new();

        // Test that read_string processes each line with correct line numbers
        let content = "Line 0\n.div\nLine 2\n..p\nLine 4";
        let result = parser.read_string(content);
        assert!(result.is_ok());

        // Verify processing completed successfully
        assert_eq!(parser.element_parser.current_depth(), 0);
    }

    #[test]
    fn test_read_string_enumeration() {
        let mut parser = WasotParser::new();

        // Test the line enumeration in read_string
        let content = "Text line\nAnother text line\n.block\nBlock content";
        let result = parser.read_string(content);
        assert!(result.is_ok());
    }

    #[test]
    fn test_read_string_finish_processing() {
        let mut parser = WasotParser::new();

        // Create content with unclosed blocks
        let content = ".outer\n..inner\nContent";
        let result = parser.read_string(content);
        assert!(result.is_ok());

        // After read_string, element_parser should finish all blocks
        assert_eq!(parser.element_parser.current_depth(), 0);
    }

    #[test]
    fn test_read_string_close_ignored_when_nothing_open() {
        let mut parser = WasotParser::new();

        // Closing without opening should be silently ignored
        let content = "./";
        let result = parser.read_string(content);
        assert!(result.is_ok());
    }

    #[test]
    fn test_default_calls_new() {
        let parser = WasotParser::default();

        // Default should create the same as new()
        assert_eq!(parser.element_parser.current_depth(), 0);

        // Test that it's functional
        let mut parser = parser;
        let result = parser.process_line(".test");
        assert!(result.is_ok());
    }

    #[test]
    fn test_new_creates_functional_parser() {
        let parser = WasotParser::new();

        // Verify that new() creates a properly initialized parser
        // by testing that the element_parser is in the expected initial state
        assert_eq!(parser.element_parser.current_depth(), 0);
        assert!(!parser.element_parser.has_open_blocks());
    }

    #[test]
    fn test_process_line_with_various_inputs() {
        let mut parser = WasotParser::new();

        // Test with meta line
        let result = parser.process_line(".div");
        assert!(result.is_ok());

        // Test with content line
        let result = parser.process_line("Some content");
        assert!(result.is_ok());

        // Test with empty line
        let result = parser.process_line("");
        assert!(result.is_ok());

        // Test with heading
        let result = parser.process_line(".. Heading");
        assert!(result.is_ok());
    }

    #[test]
    fn test_read_file_with_empty_file() {
        let mut parser = WasotParser::new();

        // Create an empty file
        let temp_file = NamedTempFile::new().unwrap();
        temp_file.as_file().sync_all().unwrap();

        let result = parser.read_file(temp_file.path());
        assert!(result.is_ok());

        // Parser should remain in initial state
        assert_eq!(parser.element_parser.current_depth(), 0);
    }

    #[test]
    fn test_read_string_with_single_line() {
        let mut parser = WasotParser::new();

        let result = parser.read_string("Single line");
        assert!(result.is_ok());

        // Should complete successfully
        assert_eq!(parser.element_parser.current_depth(), 0);
    }

    #[test]
    fn test_complex_file_processing() {
        let mut parser = WasotParser::new();

        // Create a complex file structure
        let mut temp_file = NamedTempFile::new().unwrap();
        writeln!(temp_file, ".article").unwrap();
        writeln!(temp_file, "Introduction").unwrap();
        writeln!(temp_file).unwrap(); // empty line
        writeln!(temp_file, ".. Chapter 1").unwrap();
        writeln!(temp_file, "..section").unwrap();
        writeln!(temp_file, "Section content").unwrap();
        writeln!(temp_file, "...subsection").unwrap();
        writeln!(temp_file, "Nested content").unwrap();
        temp_file.flush().unwrap();

        let result = parser.read_file(temp_file.path());
        assert!(result.is_ok());

        // Should complete with all blocks closed
        assert_eq!(parser.element_parser.current_depth(), 0);
    }

    #[test]
    fn test_complex_string_processing() {
        let mut parser = WasotParser::new();

        let content = r#".document
Document title

.. Main Heading
Main content

..section
Section content
...nested
Deep content

.. Another Heading
More content"#;

        let result = parser.read_string(content);
        assert!(result.is_ok());

        // Should complete successfully
        assert_eq!(parser.element_parser.current_depth(), 0);
    }
}
