#[cfg(test)]
mod tests {
    use crate::emitters::wasot_file_emitter::WasotFileEmitter;
    use crate::events::{Emitter, Event};
    use std::io::Write;
    use std::thread;
    use tempfile::NamedTempFile;

    #[test]
    fn test_auto_id_generation() {
        // Test that blocks without IDs get auto-generated IDs
        let content = r#".block
Some content
.div
More content
"#;
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let receiver = emitter.subscribe();

        // Run the emitter in a background thread
        let handle = thread::spawn(move || {
            emitter.run();
        });

        let mut collected_events = Vec::new();
        let mut block_ids = Vec::new();

        // Collect events
        for event in receiver {
            if let Event::BlockStarted { meta_line } = &event {
                if !meta_line.id.is_empty() {
                    block_ids.push(meta_line.id.as_str().to_string());
                }
            }
            collected_events.push(event);

            // Stop after reasonable number of events
            if collected_events.len() > 10 {
                break;
            }
        }

        // Wait for the emitter to finish
        let _ = handle.join();

        // Should have auto-generated IDs
        assert_eq!(block_ids.len(), 2);
        assert_eq!(block_ids[0], "1");
        assert_eq!(block_ids[1], "2");
    }

    #[test]
    fn test_auto_id_with_existing_ids() {
        // Test that auto-generated IDs start after the maximum existing ID
        let content = r#".block :5
Content
.div :10
More content
.section
Section content
.p :2
Paragraph
.span
Span content
"#;
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let receiver = emitter.subscribe();

        // Run the emitter in a background thread
        let handle = thread::spawn(move || {
            emitter.run();
        });

        let mut block_ids = Vec::new();

        // Collect block IDs
        for event in receiver {
            if let Event::BlockStarted { meta_line } = &event {
                if !meta_line.id.is_empty() {
                    block_ids.push(meta_line.id.as_str().to_string());
                }
            }

            // Stop after reasonable number of events
            if block_ids.len() >= 5 {
                break;
            }
        }

        // Wait for the emitter to finish
        let _ = handle.join();

        // Should have all 5 blocks with IDs
        assert_eq!(block_ids.len(), 5);
        assert_eq!(block_ids[0], "5");
        assert_eq!(block_ids[1], "10");
        assert_eq!(block_ids[2], "1"); // Auto-generated starts from 1 for from_string
        assert_eq!(block_ids[3], "2");
        assert_eq!(block_ids[4], "2"); // Next auto-generated is 2 (from_string doesn't scan)
    }

    #[test]
    fn test_auto_id_with_base36_existing() {
        // Test with existing base36 IDs
        let content = r#".block :abc
Content
.div
More content
.section :xyz
Section content
"#;
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let receiver = emitter.subscribe();

        // Run the emitter in a background thread
        let handle = thread::spawn(move || {
            emitter.run();
        });

        let mut block_ids = Vec::new();

        // Collect block IDs
        for event in receiver {
            if let Event::BlockStarted { meta_line } = &event {
                if !meta_line.id.is_empty() {
                    block_ids.push((meta_line.id.as_str().to_string(), meta_line.id.as_u64()));
                }
            }

            if block_ids.len() >= 3 {
                break;
            }
        }

        // Wait for the emitter to finish
        let _ = handle.join();

        assert_eq!(block_ids.len(), 3);

        // "abc" = 13368 in base36
        assert_eq!(block_ids[0].0, "abc");
        assert_eq!(block_ids[0].1, Some(13368));

        // Auto-generated should start from 1 for from_string (no file to scan)
        // The div block gets ID "1"
        assert_eq!(block_ids[1].0, "1");
        assert_eq!(block_ids[1].1, Some(1));

        // "xyz" = 44027 in base36
        assert_eq!(block_ids[2].0, "xyz");
        assert_eq!(block_ids[2].1, Some(44027));
    }

    #[test]
    fn test_headings_get_auto_ids() {
        // Test that headings also get auto-generated IDs
        let content = r#".. Heading 1
.block
Content
... Heading 2
"#;
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let receiver = emitter.subscribe();

        // Run the emitter in a background thread
        let handle = thread::spawn(move || {
            emitter.run();
        });

        let mut block_ids = Vec::new();
        let mut block_types = Vec::new();

        // Collect block IDs and types
        for event in receiver {
            if let Event::BlockStarted { meta_line } = &event {
                block_types.push(meta_line.type_name.clone());
                if !meta_line.id.is_empty() {
                    block_ids.push(meta_line.id.as_str().to_string());
                }
            }

            if block_ids.len() >= 3 {
                break;
            }
        }

        // Wait for the emitter to finish
        let _ = handle.join();

        // All blocks including headings should have IDs
        assert_eq!(block_ids.len(), 3);
        assert_eq!(block_ids[0], "1"); // First heading
        assert_eq!(block_ids[1], "2"); // Block
        assert_eq!(block_ids[2], "3"); // Second heading

        // Verify block types
        assert_eq!(block_types[0], ""); // Empty type_name for headings
        assert_eq!(block_types[1], "block");
        assert_eq!(block_types[2], ""); // Empty type_name for headings
    }

    #[test]
    fn test_explicit_close_no_id() {
        // Test that explicit close blocks (./) don't get IDs
        let content = r#".block
Content
./
"#;
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let receiver = emitter.subscribe();

        // Run the emitter in a background thread
        let handle = thread::spawn(move || {
            emitter.run();
        });

        let mut block_count = 0;
        let mut close_block_seen = false;

        // Collect events
        for event in receiver {
            if let Event::BlockStarted { meta_line } = &event {
                block_count += 1;
                if meta_line.type_name == "/" {
                    close_block_seen = true;
                    // Close blocks should not have IDs
                    assert!(meta_line.id.is_empty());
                }
            }

            if block_count > 5 {
                break;
            }
        }

        // Wait for the emitter to finish
        let _ = handle.join();

        // Should have seen only 1 BlockStarted event - the block
        // (close blocks don't emit BlockStarted)
        assert_eq!(block_count, 1);
        assert!(!close_block_seen);
    }

    #[test]
    fn test_file_based_scanning() {
        // Test that file-based scanning works correctly to find max ID
        let content = r#".block :z
Content
.div
More content
.section :5
Section content
"#;

        // Write to a temporary file
        let mut temp_file = NamedTempFile::new().unwrap();
        temp_file.write_all(content.as_bytes()).unwrap();
        temp_file.flush().unwrap();

        let emitter = WasotFileEmitter::from_file(temp_file.path());
        let receiver = emitter.subscribe();

        // Run the emitter in a background thread
        let handle = thread::spawn(move || {
            emitter.run();
        });

        let mut block_ids = Vec::new();

        // Collect block IDs
        for event in receiver {
            if let Event::BlockStarted { meta_line } = &event {
                if !meta_line.id.is_empty() {
                    block_ids.push(meta_line.id.as_str().to_string());
                }
            }

            if block_ids.len() >= 3 {
                break;
            }
        }

        // Wait for the emitter to finish
        let _ = handle.join();

        // Should have: z (35), 10 (auto-generated after max 35), 5
        assert_eq!(block_ids.len(), 3);
        assert_eq!(block_ids[0], "z"); // 35 in base36
        assert_eq!(block_ids[1], "10"); // 36 in base36
        assert_eq!(block_ids[2], "5");
    }

    #[test]
    fn test_wasot_emitter_never_emits_blocks_without_ids() {
        // Comprehensive test: WasotFileEmitter should NEVER emit blocks without IDs
        let content = r#"Plain text at start
.block
Block content
.div :existing-id
Div content
.. Heading
Heading content
...
Another heading
.section
Section content
./
More plain text
.footer
Footer content
"#;

        let emitter = WasotFileEmitter::from_string(content.to_string());
        let receiver = emitter.subscribe();

        // Run the emitter in a background thread
        let handle = thread::spawn(move || {
            emitter.run();
        });

        let mut blocks_without_ids = Vec::new();
        let mut all_block_events = Vec::new();

        // Collect ALL block events and check for missing IDs
        for event in receiver {
            if let Event::BlockStarted { meta_line } = &event {
                all_block_events.push((
                    meta_line.type_name.clone(),
                    meta_line.id.as_str().to_string(),
                    meta_line.level,
                ));

                if meta_line.id.is_empty() {
                    blocks_without_ids.push(meta_line.type_name.clone());
                }
            }

            // Prevent infinite loop
            if all_block_events.len() > 20 {
                break;
            }
        }

        // Wait for the emitter to finish
        let _ = handle.join();

        // CRITICAL ASSERTION: WasotFileEmitter should NEVER emit blocks without IDs
        assert!(
            blocks_without_ids.is_empty(),
            "WasotFileEmitter emitted blocks without IDs: {blocks_without_ids:?}. All blocks should have auto-generated IDs."
        );

        // Verify we got a reasonable number of blocks
        assert!(
            all_block_events.len() >= 5,
            "Expected at least 5 block events, got {}",
            all_block_events.len()
        );

        // Verify all blocks have non-empty IDs
        for (block_type, id, level) in &all_block_events {
            assert!(
                !id.is_empty(),
                "Block '{block_type}' at level {level} has empty ID - this should never happen with WasotFileEmitter"
            );
        }

        // Verify the existing ID is preserved
        let existing_id_block = all_block_events
            .iter()
            .find(|(block_type, id, _)| block_type == "div" && id == "existing-id");
        assert!(
            existing_id_block.is_some(),
            "Existing ID 'existing-id' should be preserved"
        );

        // Verify auto-generated IDs are valid base36
        for (block_type, id, _) in &all_block_events {
            if id != "existing-id" {
                // This should be an auto-generated ID, so it should parse as base36
                let parsed = crate::base36::base36_to_u64(id);
                assert!(
                    parsed.is_ok(),
                    "Auto-generated ID '{}' for block '{}' is not valid base36: {:?}",
                    id,
                    block_type,
                    parsed.err()
                );
            }
        }
    }
}
