#[cfg(test)]
mod tests {
    use crate::emitters::wasot_file_emitter::WasotFileEmitter;
    use crate::events::{Consumer, Emitter, Event};
    use crate::parsers::wasot::{parse_footnotes, Footnote};
    use std::io::Cursor;
    use std::sync::{Arc, Mutex};

    /// A test consumer that collects events for testing
    struct FootnoteTestConsumer {
        events: Arc<Mutex<Vec<Event>>>,
    }

    impl FootnoteTestConsumer {
        fn new() -> Self {
            Self {
                events: Arc::new(Mutex::new(Vec::new())),
            }
        }
    }

    impl Consumer for FootnoteTestConsumer {
        fn handle(&mut self, event: Event) {
            self.events.lock().unwrap().push(event);
        }
    }

    #[test]
    fn test_text_event_with_footnotes() {
        let wasot_content = r#"
This is text with footnotes
*1 https://example.com
*2 https://another.com
More text here
*3 Reference text here
"#;

        let cursor = Cursor::new(wasot_content.as_bytes());
        let emitter = WasotFileEmitter::from_reader(Box::new(cursor));
        let consumer = FootnoteTestConsumer::new();
        let consumer_events = consumer.events.clone();

        // Create a reader from the emitter
        let reader = emitter.subscribe();

        // Run the emitter in the background
        std::thread::spawn(move || {
            emitter.run();
        });

        // Consume events
        let mut consumer_instance = consumer;
        consumer_instance.run(reader);

        // Check the collected events
        let events = consumer_events.lock().unwrap().clone();

        // Should have at least one TextFinished event
        let text_events: Vec<_> = events
            .iter()
            .filter_map(|e| match e {
                Event::TextFinished {
                    lines,
                    links: _,
                    footnotes,
                } => Some((lines, footnotes)),
                _ => None,
            })
            .collect();

        assert!(
            !text_events.is_empty(),
            "Should have at least one TextFinished event"
        );

        // Check that footnotes were parsed correctly
        let (lines, footnotes) = &text_events[0];

        // Should have the correct number of footnotes
        assert_eq!(footnotes.len(), 3, "Should have 3 footnotes");

        // Check individual footnotes
        assert_eq!(footnotes[0].marker, 1);
        assert_eq!(footnotes[0].link, "https://example.com");

        assert_eq!(footnotes[1].marker, 2);
        assert_eq!(footnotes[1].link, "https://another.com");

        assert_eq!(footnotes[2].marker, 3);
        assert_eq!(footnotes[2].link, "Reference text here");

        // All lines should be included
        assert!(
            lines.len() >= 4,
            "Should have multiple lines including footnotes"
        );
    }

    #[test]
    fn test_text_event_without_footnotes() {
        let wasot_content = r#"
This is text without footnotes
Just regular content
No footnotes here
"#;

        let cursor = Cursor::new(wasot_content.as_bytes());
        let emitter = WasotFileEmitter::from_reader(Box::new(cursor));
        let consumer = FootnoteTestConsumer::new();
        let consumer_events = consumer.events.clone();

        // Create a reader from the emitter
        let reader = emitter.subscribe();

        // Run the emitter in the background
        std::thread::spawn(move || {
            emitter.run();
        });

        // Consume events
        let mut consumer_instance = consumer;
        consumer_instance.run(reader);

        // Check the collected events
        let events = consumer_events.lock().unwrap().clone();

        // Should have at least one TextFinished event
        let text_events: Vec<_> = events
            .iter()
            .filter_map(|e| match e {
                Event::TextFinished {
                    lines: _,
                    links: _,
                    footnotes,
                } => Some(footnotes),
                _ => None,
            })
            .collect();

        assert!(
            !text_events.is_empty(),
            "Should have at least one TextFinished event"
        );

        // Check that no footnotes were found
        let footnotes = &text_events[0];
        assert_eq!(footnotes.len(), 0, "Should have no footnotes");
    }

    #[test]
    fn test_text_event_with_mixed_content_and_footnotes() {
        let wasot_content = r#"
.paragraph
This is paragraph content
*1 https://example.com
Regular text line
*2 https://another.com
More content

.quote
Quote content here
*3 Reference for quote
"#;

        let cursor = Cursor::new(wasot_content.as_bytes());
        let emitter = WasotFileEmitter::from_reader(Box::new(cursor));
        let consumer = FootnoteTestConsumer::new();
        let consumer_events = consumer.events.clone();

        // Create a reader from the emitter
        let reader = emitter.subscribe();

        // Run the emitter in the background
        std::thread::spawn(move || {
            emitter.run();
        });

        // Consume events
        let mut consumer_instance = consumer;
        consumer_instance.run(reader);

        // Check the collected events
        let events = consumer_events.lock().unwrap().clone();

        // Should have multiple TextFinished events
        let text_events: Vec<_> = events
            .iter()
            .filter_map(|e| match e {
                Event::TextFinished {
                    lines: _,
                    links: _,
                    footnotes,
                } => Some(footnotes),
                _ => None,
            })
            .collect();

        assert!(
            text_events.len() >= 2,
            "Should have multiple TextFinished events"
        );

        // Find text events with footnotes
        let mut total_footnotes = 0;
        let mut found_footnotes = Vec::new();

        for footnotes in &text_events {
            for footnote in footnotes.iter() {
                found_footnotes.push((footnote.marker, footnote.link.clone()));
                total_footnotes += 1;
            }
        }

        // Should have found footnotes *1, *2, and *3 across all text events
        assert_eq!(
            total_footnotes, 3,
            "Should have 3 footnotes total across all text blocks"
        );

        // Check that we found the expected footnotes (order may vary)
        assert!(found_footnotes
            .iter()
            .any(|(marker, link)| *marker == 1 && link == "https://example.com"));
        assert!(found_footnotes
            .iter()
            .any(|(marker, link)| *marker == 2 && link == "https://another.com"));
        assert!(found_footnotes
            .iter()
            .any(|(marker, link)| *marker == 3 && link == "Reference for quote"));
    }

    #[test]
    fn test_footnote_parsing_edge_cases() {
        let wasot_content = r#"
Text with various footnote patterns
*1 Valid footnote
* Invalid footnote (no number)
*abc Invalid footnote (non-numeric)
*2https://example.com Invalid (no space)
*3  Valid with extra spaces
*999 Valid large number
"#;

        let cursor = Cursor::new(wasot_content.as_bytes());
        let emitter = WasotFileEmitter::from_reader(Box::new(cursor));
        let consumer = FootnoteTestConsumer::new();
        let consumer_events = consumer.events.clone();

        // Create a reader from the emitter
        let reader = emitter.subscribe();

        // Run the emitter in the background
        std::thread::spawn(move || {
            emitter.run();
        });

        // Consume events
        let mut consumer_instance = consumer;
        consumer_instance.run(reader);

        // Check the collected events
        let events = consumer_events.lock().unwrap().clone();

        let text_events: Vec<_> = events
            .iter()
            .filter_map(|e| match e {
                Event::TextFinished {
                    lines: _,
                    links: _,
                    footnotes,
                } => Some(footnotes),
                _ => None,
            })
            .collect();

        assert!(
            !text_events.is_empty(),
            "Should have at least one TextFinished event"
        );

        // Should only have valid footnotes (1, 3, and 999)
        let footnotes = &text_events[0];
        assert_eq!(footnotes.len(), 3, "Should have 3 valid footnotes");

        assert_eq!(footnotes[0].marker, 1);
        assert_eq!(footnotes[0].link, "Valid footnote");

        assert_eq!(footnotes[1].marker, 3);
        assert_eq!(footnotes[1].link, "Valid with extra spaces");

        assert_eq!(footnotes[2].marker, 999);
        assert_eq!(footnotes[2].link, "Valid large number");
    }

    #[test]
    fn test_footnote_with_unicode_content() {
        let wasot_content = r#"
Text with Unicode footnotes
*1 https://example.com/世界
*2 Reference with émojis 🎉
*3 Arabic text: مرحبا
"#;

        let cursor = Cursor::new(wasot_content.as_bytes());
        let emitter = WasotFileEmitter::from_reader(Box::new(cursor));
        let consumer = FootnoteTestConsumer::new();
        let consumer_events = consumer.events.clone();

        // Create a reader from the emitter
        let reader = emitter.subscribe();

        // Run the emitter in the background
        std::thread::spawn(move || {
            emitter.run();
        });

        // Consume events
        let mut consumer_instance = consumer;
        consumer_instance.run(reader);

        // Check the collected events
        let events = consumer_events.lock().unwrap().clone();

        let text_events: Vec<_> = events
            .iter()
            .filter_map(|e| match e {
                Event::TextFinished {
                    lines: _,
                    links: _,
                    footnotes,
                } => Some(footnotes),
                _ => None,
            })
            .collect();

        assert!(
            !text_events.is_empty(),
            "Should have at least one TextFinished event"
        );

        let footnotes = &text_events[0];
        assert_eq!(footnotes.len(), 3, "Should have 3 footnotes");

        assert_eq!(footnotes[0].marker, 1);
        assert_eq!(footnotes[0].link, "https://example.com/世界");

        assert_eq!(footnotes[1].marker, 2);
        assert_eq!(footnotes[1].link, "Reference with émojis 🎉");

        assert_eq!(footnotes[2].marker, 3);
        assert_eq!(footnotes[2].link, "Arabic text: مرحبا");
    }

    #[test]
    fn test_duplicate_footnote_markers() {
        let wasot_content = r#"
Text with duplicate footnote markers
*1 First reference
*2 Second reference
*1 Duplicate marker with different content
*3 Third reference
"#;

        let cursor = Cursor::new(wasot_content.as_bytes());
        let emitter = WasotFileEmitter::from_reader(Box::new(cursor));
        let consumer = FootnoteTestConsumer::new();
        let consumer_events = consumer.events.clone();

        // Create a reader from the emitter
        let reader = emitter.subscribe();

        // Run the emitter in the background
        std::thread::spawn(move || {
            emitter.run();
        });

        // Consume events
        let mut consumer_instance = consumer;
        consumer_instance.run(reader);

        // Check the collected events
        let events = consumer_events.lock().unwrap().clone();

        let text_events: Vec<_> = events
            .iter()
            .filter_map(|e| match e {
                Event::TextFinished {
                    lines: _,
                    links: _,
                    footnotes,
                } => Some(footnotes),
                _ => None,
            })
            .collect();

        assert!(
            !text_events.is_empty(),
            "Should have at least one TextFinished event"
        );

        let footnotes = &text_events[0];
        assert_eq!(
            footnotes.len(),
            4,
            "Should have 4 footnotes (including duplicate)"
        );

        // Both footnotes with marker 1 should be preserved
        let marker_1_footnotes: Vec<_> = footnotes.iter().filter(|f| f.marker == 1).collect();
        assert_eq!(
            marker_1_footnotes.len(),
            2,
            "Should have 2 footnotes with marker 1"
        );

        assert_eq!(marker_1_footnotes[0].link, "First reference");
        assert_eq!(
            marker_1_footnotes[1].link,
            "Duplicate marker with different content"
        );
    }

    #[test]
    fn test_footnote_event_validation() {
        // Test that TextFinished events with footnotes pass validation
        let event = Event::TextFinished {
            lines: vec![
                "Text with footnote".to_string(),
                "*1 https://example.com".to_string(),
            ],
            links: vec![Vec::new(), Vec::new()],
            footnotes: vec![Footnote {
                marker: 1,
                link: "https://example.com".to_string(),
            }],
        };

        assert!(
            event.validate(),
            "TextFinished event with footnotes should validate"
        );
    }

    #[test]
    fn test_empty_footnotes_list() {
        // Test that TextFinished events with empty footnotes work correctly
        let event = Event::TextFinished {
            lines: vec!["Text without footnotes".to_string()],
            links: vec![Vec::new()],
            footnotes: vec![],
        };

        assert!(
            event.validate(),
            "TextFinished event with empty footnotes should validate"
        );
    }

    #[test]
    fn test_parse_footnotes_direct() {
        // Direct test of the parse_footnotes function
        let lines = vec![
            "Regular text line".to_string(),
            "*1 https://example.com".to_string(),
            "Another text line".to_string(),
            "*2 Reference text".to_string(),
            "*Invalid footnote".to_string(),
            "*3 Third footnote".to_string(),
        ];

        let footnotes = parse_footnotes(&lines);

        assert_eq!(footnotes.len(), 3, "Should parse 3 valid footnotes");

        assert_eq!(footnotes[0].marker, 1);
        assert_eq!(footnotes[0].link, "https://example.com");

        assert_eq!(footnotes[1].marker, 2);
        assert_eq!(footnotes[1].link, "Reference text");

        assert_eq!(footnotes[2].marker, 3);
        assert_eq!(footnotes[2].link, "Third footnote");
    }
}
