use crate::events::{Emitter, Event};
use crate::parsers::wasot::{Id, MetaLine, ParsedArguments, QuotedString};
use rand::prelude::*;
use rand::rngs::StdRng;

/// High-performance random emitter optimized for extreme scale generation
///
/// This emitter prioritizes speed over variety by using:
/// - Pre-computed string templates
/// - Minimal allocations
/// - Simple random selection from pre-built pools
/// - Optimized for throughput rather than diversity
pub struct FastRandomEmitter {
    event_count: usize,
    seed: Option<u64>,
}

pub struct FastRandomEmitterIterator {
    rng: StdRng, // Standard RNG
    events_generated: usize,
    total_events: usize,
    open_blocks: usize,
    finished: bool,
    // Pre-computed pools for fast selection
    type_names: Vec<&'static str>,
    words: Vec<&'static str>,
    sentences: Vec<&'static str>,
    ids: Vec<&'static str>,
    // Pre-allocated buffers to avoid allocations
    temp_line_buffer: Vec<String>,
}

impl FastRandomEmitter {
    pub fn new(event_count: usize) -> Self {
        Self {
            event_count,
            seed: None,
        }
    }

    pub fn with_seed(event_count: usize, seed: u64) -> Self {
        Self {
            event_count,
            seed: Some(seed),
        }
    }
}

impl FastRandomEmitterIterator {
    fn new(event_count: usize, seed: Option<u64>) -> Self {
        let rng = if let Some(seed) = seed {
            StdRng::seed_from_u64(seed)
        } else {
            StdRng::from_entropy()
        };

        // Pre-computed pools for O(1) selection
        let type_names = vec![
            "p",
            "div",
            "section",
            "heading",
            "code",
            "quote",
            "list",
            "item",
            "image",
            "link",
            "table",
            "row",
            "cell",
            "footer",
            "header",
            "nav",
            "article",
            "aside",
            "block",
            "container",
            "wrapper",
            "widget",
            "component",
            "#",
            "##",
            "###",
            "custom",
            "data",
            "meta",
            "config",
        ];

        let words = vec![
            "the",
            "quick",
            "brown",
            "fox",
            "jumps",
            "over",
            "lazy",
            "dog",
            "lorem",
            "ipsum",
            "dolor",
            "sit",
            "amet",
            "consectetur",
            "adipiscing",
            "elit",
            "sed",
            "do",
            "eiusmod",
            "tempor",
            "incididunt",
            "ut",
            "labore",
            "et",
            "dolore",
            "magna",
            "aliqua",
            "enim",
            "ad",
            "minim",
            "veniam",
            "quis",
            "nostrud",
            "exercitation",
            "ullamco",
            "laboris",
            "nisi",
            "aliquip",
            "ex",
            "ea",
            "commodo",
            "consequat",
            "duis",
            "aute",
            "irure",
            "in",
            "reprehenderit",
            "voluptate",
            "velit",
            "esse",
            "cillum",
            "fugiat",
            "nulla",
            "pariatur",
            "excepteur",
            "sint",
            "occaecat",
            "cupidatat",
            "non",
            "proident",
            "sunt",
            "culpa",
            "qui",
            "officia",
            "deserunt",
            "mollit",
        ];

        let sentences = vec![
            "Lorem ipsum dolor sit amet",
            "Quick brown fox jumps over lazy dog",
            "The quick brown fox jumps",
            "Consectetur adipiscing elit sed do",
            "Eiusmod tempor incididunt ut labore",
            "Et dolore magna aliqua enim",
            "Ad minim veniam quis nostrud",
            "Exercitation ullamco laboris nisi aliquip",
            "Ex ea commodo consequat duis",
            "Aute irure dolor in reprehenderit",
            "Voluptate velit esse cillum fugiat",
            "Nulla pariatur excepteur sint occaecat",
            "Cupidatat non proident sunt culpa",
            "Qui officia deserunt mollit anim",
            "Id est laborum sed ut",
            "Perspiciatis unde omnis iste natus",
        ];

        let ids = vec![
            "main",
            "content",
            "header",
            "footer",
            "nav",
            "sidebar",
            "article",
            "section",
            "div",
            "span",
            "p",
            "h1",
            "h2",
            "h3",
            "img",
            "link",
            "btn",
            "form",
            "input",
            "table",
            "row",
            "cell",
            "list",
            "item",
            "widget",
            "component",
            "container",
            "wrapper",
            "block",
            "element",
        ];

        Self {
            rng,
            events_generated: 0,
            total_events: event_count,
            open_blocks: 0,
            finished: false,
            type_names,
            words,
            sentences,
            ids,
            temp_line_buffer: Vec::with_capacity(5), // Pre-allocate for text lines
        }
    }

    fn generate_fast_meta_line(&mut self) -> MetaLine {
        // Fast random level (1-3, more weighted toward 1-2)
        let level = match self.rng.gen_range(0..10) {
            0..=5 => 1,
            6..=8 => 2,
            _ => 3,
        };

        // Fast type name selection
        let type_name = self.type_names.choose(&mut self.rng).unwrap().to_string();

        // Simple inline text (25% chance, pre-computed)
        let inline_text = if self.rng.gen_bool(0.25) {
            QuotedString::new(
                self.sentences.choose(&mut self.rng).unwrap().to_string(),
                false, // Skip quoting complexity for speed
            )
        } else {
            QuotedString::new(String::new(), false)
        };

        // Simple ID (20% chance)
        let id = if self.rng.gen_bool(0.2) {
            Id::new(self.ids.choose(&mut self.rng).unwrap().to_string())
        } else {
            Id::empty()
        };

        // Minimal arguments for speed
        let arguments = if self.rng.gen_bool(0.3) {
            // 30% chance of 1-2 simple arguments
            let num_args = self.rng.gen_range(1..=2);
            let args: Vec<QuotedString> = (0..num_args)
                .map(|_| {
                    QuotedString::new(self.words.choose(&mut self.rng).unwrap().to_string(), false)
                })
                .collect();

            ParsedArguments {
                args,
                kwargs: vec![],
            }
        } else {
            ParsedArguments {
                args: vec![],
                kwargs: vec![],
            }
        };

        MetaLine {
            type_name,
            inline_text,
            level,
            id,
            line_index: None,
            arguments,
            is_void: false,
        }
    }

    fn generate_fast_text_lines(&mut self) -> Vec<String> {
        // Clear the pre-allocated buffer
        self.temp_line_buffer.clear();

        // Generate 1-3 lines quickly
        let num_lines = self.rng.gen_range(1..=3);

        for _ in 0..num_lines {
            // Use pre-computed sentences with minimal processing
            let sentence = self.sentences.choose(&mut self.rng).unwrap();
            self.temp_line_buffer.push(sentence.to_string());
        }

        // Return a clone to avoid lifetime issues
        self.temp_line_buffer.clone()
    }
}

impl Iterator for FastRandomEmitterIterator {
    type Item = Event;

    fn next(&mut self) -> Option<Self::Item> {
        if self.finished {
            return None;
        }

        // If we've generated all requested events, start closing blocks
        if self.events_generated >= self.total_events {
            if self.open_blocks > 0 {
                self.open_blocks -= 1;
                return Some(Event::BlockFinished);
            } else {
                self.finished = true;
                return None;
            }
        }

        // Simplified event distribution for speed
        let event_type = self.rng.gen_range(0..10);

        let event = match event_type {
            0..=5 => {
                // Generate BlockStarted event (60% chance)
                let meta_line = self.generate_fast_meta_line();
                self.open_blocks += 1;
                Event::BlockStarted { meta_line }
            }
            6..=8 => {
                // Generate TextFinished event (30% chance)
                let lines = self.generate_fast_text_lines();
                // Generate empty links for each line (no links in random text for performance)
                let links = vec![Vec::new(); lines.len()];
                Event::TextFinished {
                    lines,
                    links,
                    footnotes: vec![],
                }
            }
            9 => {
                // Generate BlockFinished event (10% chance)
                if self.open_blocks > 0 {
                    self.open_blocks -= 1;
                    Event::BlockFinished
                } else {
                    // Can't close a block if none are open, generate simple text instead
                    Event::TextFinished {
                        lines: vec!["Simple text line".to_string()],
                        links: vec![Vec::new()],
                        footnotes: vec![],
                    }
                }
            }
            _ => unreachable!(),
        };

        self.events_generated += 1;
        Some(event)
    }
}

impl Emitter for FastRandomEmitter {
    type Reader = FastRandomEmitterIterator;

    fn subscribe(&self) -> Self::Reader {
        FastRandomEmitterIterator::new(self.event_count, self.seed)
    }

    fn run(self) {
        // For the run method, we can just consume the iterator
        let _events: Vec<_> = self.subscribe().collect();
    }
}

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

    #[test]
    fn test_new() {
        // Test line 34 in function `new`
        let emitter = FastRandomEmitter::new(100);
        assert_eq!(emitter.event_count, 100);
        assert!(emitter.seed.is_none());
    }

    #[test]
    fn test_with_seed() {
        // Test line 41 and 44 in function `with_seed`
        let emitter = FastRandomEmitter::with_seed(50, 12345);
        assert_eq!(emitter.event_count, 50);
        assert_eq!(emitter.seed, Some(12345));
    }

    #[test]
    fn test_fast_random_emitter_iterator_new() {
        // Test lines 50-52 and 54, 58 in function `new`
        let iter = FastRandomEmitterIterator::new(10, Some(42));
        assert_eq!(iter.events_generated, 0);
        assert_eq!(iter.total_events, 10);
        assert_eq!(iter.open_blocks, 0);
        assert!(!iter.finished);
        assert_eq!(iter.temp_line_buffer.capacity(), 5);

        // Test without seed
        let iter_no_seed = FastRandomEmitterIterator::new(20, None);
        assert_eq!(iter_no_seed.total_events, 20);
    }

    #[test]
    fn test_generate_fast_meta_line() {
        // Test lines 226, 228-231, 235, 238, 240, 244 in function `generate_fast_meta_line`
        let mut iter = FastRandomEmitterIterator::new(100, Some(42));

        let meta_line = iter.generate_fast_meta_line();

        // Verify the meta line has valid properties
        assert!(!meta_line.type_name.is_empty());
        assert!(meta_line.level >= 1 && meta_line.level <= 3);

        // Generate multiple meta lines to test randomness
        for _ in 0..10 {
            let meta = iter.generate_fast_meta_line();
            assert!(meta.level >= 1 && meta.level <= 3);
            assert!(!meta.type_name.is_empty());
        }
    }

    #[test]
    fn test_generate_fast_text_lines() {
        // Test lines 285, 287, 290, 292, 294-295, 299 in function `generate_fast_text_lines`
        let mut iter = FastRandomEmitterIterator::new(100, Some(42));

        let lines = iter.generate_fast_text_lines();

        assert!(!lines.is_empty());
        assert!(!lines.is_empty() && lines.len() <= 3);

        for line in &lines {
            assert!(!line.is_empty());
        }
    }

    #[test]
    fn test_iterator_next_block_started() {
        // Test lines 306-308, 312-315, 317-318, 323 in function `next`
        let mut iter = FastRandomEmitterIterator::new(1, Some(42));

        // Force a BlockStarted event by setting up state
        iter.rng = StdRng::seed_from_u64(42);

        let event = iter.next();
        assert!(event.is_some());

        // Keep generating until we get a BlockStarted event
        let mut found_block_started = false;
        let mut iter2 = FastRandomEmitterIterator::new(50, Some(123));

        for _ in 0..20 {
            if let Some(Event::BlockStarted { .. }) = iter2.next() {
                found_block_started = true;
                break;
            }
        }
        assert!(
            found_block_started,
            "Should generate at least one BlockStarted event"
        );
    }

    #[test]
    fn test_iterator_next_text_finished() {
        let mut iter = FastRandomEmitterIterator::new(50, Some(789));

        let mut found_text_finished = false;

        for _ in 0..20 {
            if let Some(Event::TextFinished {
                lines,
                links,
                footnotes,
            }) = iter.next()
            {
                found_text_finished = true;
                assert!(!lines.is_empty());
                assert_eq!(lines.len(), links.len());
                assert!(footnotes.is_empty());
                break;
            }
        }
        assert!(
            found_text_finished,
            "Should generate at least one TextFinished event"
        );
    }

    #[test]
    fn test_iterator_next_block_finished() {
        let mut iter = FastRandomEmitterIterator::new(50, Some(456));

        // First generate some blocks to have something to close
        iter.open_blocks = 2;

        let mut found_block_finished = false;

        for _ in 0..30 {
            if let Some(Event::BlockFinished) = iter.next() {
                found_block_finished = true;
                break;
            }
        }
        assert!(
            found_block_finished,
            "Should generate at least one BlockFinished event"
        );
    }

    #[test]
    fn test_iterator_finishing_sequence() {
        // Test lines 325-326, 328-329, 332, 334, 336, 340, 345-347, 351-353, 360-361
        let mut iter = FastRandomEmitterIterator::new(2, Some(42));

        // Generate all requested events
        let _event1 = iter.next();
        let _event2 = iter.next();

        // Now we should be in the finishing phase
        assert!(iter.events_generated >= iter.total_events);

        // If there are open blocks, we should get BlockFinished events
        if iter.open_blocks > 0 {
            let finish_event = iter.next();
            if let Some(Event::BlockFinished) = finish_event {
                // This is expected
            } else {
                // If no more blocks to close, we should get None
                assert!(finish_event.is_none());
            }
        }
    }

    #[test]
    fn test_iterator_finished_state() {
        let mut iter = FastRandomEmitterIterator::new(1, Some(42));

        // Generate the single event
        let _event = iter.next();

        // Simulate finishing all open blocks
        iter.finished = true;

        // Should return None when finished
        assert!(iter.next().is_none());
    }

    #[test]
    fn test_emitter_subscribe() {
        // Test lines 368-369 in function `subscribe`
        let emitter = FastRandomEmitter::new(5);
        let iter = emitter.subscribe();

        assert_eq!(iter.total_events, 5);
        assert_eq!(iter.events_generated, 0);
        assert!(!iter.finished);
    }

    #[test]
    fn test_emitter_run() {
        // Test line 372, 374 in function `run`
        let emitter = FastRandomEmitter::new(3);

        // This should not panic
        emitter.run();
    }

    #[test]
    fn test_fast_random_emitter_generates_events() {
        let emitter = FastRandomEmitter::new(10);
        let events: Vec<_> = emitter.subscribe().collect();
        assert!(!events.is_empty());
        assert!(events.len() >= 10);
    }

    #[test]
    fn test_fast_random_emitter_with_seed_is_deterministic() {
        let emitter1 = FastRandomEmitter::with_seed(20, 42);
        let emitter2 = FastRandomEmitter::with_seed(20, 42);

        let events1: Vec<_> = emitter1.subscribe().collect();
        let events2: Vec<_> = emitter2.subscribe().collect();

        assert_eq!(events1, events2);
    }

    #[test]
    fn test_all_blocks_are_closed() {
        let emitter = FastRandomEmitter::new(100);
        let events: Vec<_> = emitter.subscribe().collect();

        let mut open_blocks = 0;
        for event in &events {
            match event {
                Event::BlockStarted { .. } => open_blocks += 1,
                Event::BlockFinished => {
                    assert!(
                        open_blocks > 0,
                        "BlockFinished without matching BlockStarted"
                    );
                    open_blocks -= 1;
                }
                Event::TextFinished { .. }
                | Event::ContextLine { .. }
                | Event::VoidElement { .. } => {}
            }
        }
        assert_eq!(open_blocks, 0, "All blocks should be closed");
    }

    #[test]
    fn test_meta_line_properties() {
        let mut iter = FastRandomEmitterIterator::new(100, Some(42));

        for _ in 0..10 {
            let meta_line = iter.generate_fast_meta_line();

            // Test that type_name is from the predefined pool
            assert!(iter.type_names.contains(&meta_line.type_name.as_str()));

            // Test level is in valid range (1-3)
            assert!(meta_line.level >= 1 && meta_line.level <= 3);

            // Test line_index is None (as per the implementation)
            assert!(meta_line.line_index.is_none());
        }
    }

    #[test]
    fn test_text_lines_properties() {
        let mut iter = FastRandomEmitterIterator::new(100, Some(42));

        for _ in 0..10 {
            let lines = iter.generate_fast_text_lines();

            // Should generate 1-3 lines
            assert!(!lines.is_empty() && lines.len() <= 3);

            // All lines should be non-empty
            for line in &lines {
                assert!(!line.is_empty());
            }
        }
    }

    #[test]
    fn test_different_seeds_produce_different_output() {
        let emitter1 = FastRandomEmitter::with_seed(10, 12345);
        let emitter2 = FastRandomEmitter::with_seed(10, 67890);

        let events1: Vec<_> = emitter1.subscribe().collect();
        let events2: Vec<_> = emitter2.subscribe().collect();

        // Events should be different with different seeds
        assert_ne!(events1, events2);
    }

    #[test]
    fn test_zero_events() {
        let emitter = FastRandomEmitter::new(0);
        let events: Vec<_> = emitter.subscribe().collect();

        // Should only contain block closing events if any were opened
        assert!(events.iter().all(|e| matches!(e, Event::BlockFinished)));
    }

    #[test]
    fn test_event_types_generated() {
        let emitter = FastRandomEmitter::new(100);
        let events: Vec<_> = emitter.subscribe().collect();

        let mut has_block_started = false;
        let mut has_text_finished = false;
        let mut has_block_finished = false;

        for event in &events {
            match event {
                Event::BlockStarted { .. } => has_block_started = true,
                Event::TextFinished { .. } => has_text_finished = true,
                Event::BlockFinished => has_block_finished = true,
                Event::ContextLine { .. } | Event::VoidElement { .. } => {}
            }
        }

        // Should generate all types of events
        assert!(has_block_started, "Should generate BlockStarted events");
        assert!(has_text_finished, "Should generate TextFinished events");
        assert!(has_block_finished, "Should generate BlockFinished events");
    }

    #[test]
    fn test_text_event_structure() {
        let emitter = FastRandomEmitter::new(50);
        let events: Vec<_> = emitter.subscribe().collect();

        for event in &events {
            if let Event::TextFinished {
                lines,
                links,
                footnotes,
            } = event
            {
                // Links should match lines
                assert_eq!(lines.len(), links.len());

                // Footnotes should be empty (as per implementation)
                assert!(footnotes.is_empty());

                // All link vectors should be empty (as per implementation)
                for link_vec in links {
                    assert!(link_vec.is_empty());
                }
            }
        }
    }

    #[test]
    fn test_emitter_trait_implementation() {
        let emitter = FastRandomEmitter::new(5);

        // Test that it implements Emitter trait properly
        let iter1 = emitter.subscribe();
        let iter2 = emitter.subscribe();

        // Different iterators should be independent
        let events1: Vec<_> = iter1.collect();
        let events2: Vec<_> = iter2.collect();

        // Both should generate events
        assert!(!events1.is_empty());
        assert!(!events2.is_empty());
    }

    #[test]
    #[ignore = "slow"] // Very slow test: takes 786ms. Run with --ignored to include.
    fn test_performance_comparison() {
        use std::time::Instant;

        // Test FastRandomEmitter performance
        let start = Instant::now();
        let fast_emitter = FastRandomEmitter::new(10000);
        let _fast_events: Vec<_> = fast_emitter.subscribe().collect();
        let fast_duration = start.elapsed();

        // Test original RandomEmitter performance
        let start = Instant::now();
        let regular_emitter = crate::emitters::random_emitter::RandomEmitter::new(10000);
        let _regular_events: Vec<_> = regular_emitter.subscribe().collect();
        let regular_duration = start.elapsed();

        println!("FastRandomEmitter: {fast_duration:?}");
        println!("RandomEmitter: {regular_duration:?}");

        // FastRandomEmitter should be significantly faster
        assert!(fast_duration < regular_duration);
    }
}
