use super::Event;
use bus::BusReader;

/// Wrapper around BusReader that implements Iterator
pub struct BusReaderIterator {
    reader: BusReader<Event>,
}

impl BusReaderIterator {
    pub fn new(reader: BusReader<Event>) -> Self {
        Self { reader }
    }
}

impl Iterator for BusReaderIterator {
    type Item = Event;

    fn next(&mut self) -> Option<Self::Item> {
        // BusReader::recv() blocks until an event is available or the bus is closed
        self.reader.recv().ok()
    }
}

// Ensure it's Send as required by the trait bounds
unsafe impl Send for BusReaderIterator {}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::events::Event;
    use crate::parsers::wasot::{Id, MetaLine, ParsedArguments, QuotedString};
    use bus::Bus;

    #[test]
    fn test_new_constructor() {
        let mut bus = Bus::new(10);
        let reader = bus.add_rx();
        let iterator = BusReaderIterator::new(reader);

        // Verify the iterator was created successfully
        // We can't access the internal reader field directly, but we can verify
        // the iterator exists and has the expected type
        assert_eq!(
            std::mem::size_of_val(&iterator),
            std::mem::size_of::<BusReaderIterator>()
        );
    }

    #[test]
    fn test_iterator_next_with_events() {
        let mut bus = Bus::new(10);
        let reader = bus.add_rx();
        let mut iterator = BusReaderIterator::new(reader);

        // Create a test event
        let test_event = Event::BlockStarted {
            meta_line: MetaLine {
                level: 1,
                type_name: "test".to_string(),
                id: Id::new("test_id".to_string()),
                arguments: ParsedArguments {
                    args: vec![],
                    kwargs: vec![],
                },
                inline_text: QuotedString::new("test text".to_string(), false),
                line_index: Some(0),
                is_void: false,
            },
        };

        // Send an event to the bus
        bus.broadcast(test_event.clone());

        // The iterator should receive the event
        let received = iterator.next();
        assert!(received.is_some());

        if let Some(Event::BlockStarted { meta_line }) = received {
            assert_eq!(meta_line.type_name, "test");
            assert_eq!(meta_line.level, 1);
        } else {
            panic!("Expected BlockStarted event");
        }
    }

    #[test]
    fn test_iterator_next_with_closed_bus() {
        let mut bus = Bus::new(10);
        let reader = bus.add_rx();
        let mut iterator = BusReaderIterator::new(reader);

        // Drop the bus to close it
        drop(bus);

        // When the bus is closed, next() should return None
        let result = iterator.next();
        assert!(result.is_none());
    }

    #[test]
    fn test_iterator_multiple_events() {
        let mut bus = Bus::new(10);
        let reader = bus.add_rx();
        let mut iterator = BusReaderIterator::new(reader);

        // Create multiple test events
        let event1 = Event::BlockStarted {
            meta_line: MetaLine {
                level: 1,
                type_name: "event1".to_string(),
                id: Id::new("id1".to_string()),
                arguments: ParsedArguments {
                    args: vec![],
                    kwargs: vec![],
                },
                inline_text: QuotedString::new("".to_string(), false),
                line_index: Some(0),
                is_void: false,
            },
        };

        let event2 = Event::TextFinished {
            lines: vec!["test line".to_string()],
            links: vec![vec![]],
            footnotes: vec![],
        };

        let event3 = Event::BlockFinished;

        // Send events to the bus
        bus.broadcast(event1.clone());
        bus.broadcast(event2.clone());
        bus.broadcast(event3.clone());

        // Iterator should receive all events in order
        let received1 = iterator.next();
        assert!(received1.is_some());
        assert!(matches!(received1, Some(Event::BlockStarted { .. })));

        let received2 = iterator.next();
        assert!(received2.is_some());
        assert!(matches!(received2, Some(Event::TextFinished { .. })));

        let received3 = iterator.next();
        assert!(received3.is_some());
        assert!(matches!(received3, Some(Event::BlockFinished)));

        // After bus is dropped, should return None
        drop(bus);
        let received4 = iterator.next();
        assert!(received4.is_none());
    }

    #[test]
    fn test_iterator_send_trait() {
        // Test that BusReaderIterator implements Send
        fn assert_send<T: Send>() {}
        assert_send::<BusReaderIterator>();
    }

    #[test]
    fn test_iterator_with_different_event_types() {
        let mut bus = Bus::new(10);
        let reader = bus.add_rx();
        let mut iterator = BusReaderIterator::new(reader);

        // Test with different event types
        let block_event = Event::BlockStarted {
            meta_line: MetaLine {
                level: 2,
                type_name: "paragraph".to_string(),
                id: Id::empty(),
                arguments: ParsedArguments {
                    args: vec![QuotedString::new("arg1".to_string(), false)],
                    kwargs: vec![(
                        QuotedString::new("key".to_string(), false),
                        QuotedString::new("value".to_string(), true),
                    )],
                },
                inline_text: QuotedString::new("inline text".to_string(), false),
                line_index: Some(5),
                is_void: false,
            },
        };

        let text_event = Event::TextFinished {
            lines: vec![
                "Line one".to_string(),
                "Line two".to_string(),
                "Line three".to_string(),
            ],
            links: vec![vec![], vec![], vec![]],
            footnotes: vec![],
        };

        // Send events
        bus.broadcast(block_event);
        bus.broadcast(text_event);
        bus.broadcast(Event::BlockFinished);

        // Verify all events are received correctly
        let event1 = iterator.next().unwrap();
        if let Event::BlockStarted { meta_line } = event1 {
            assert_eq!(meta_line.type_name, "paragraph");
            assert_eq!(meta_line.level, 2);
            assert_eq!(meta_line.arguments.args.len(), 1);
            assert_eq!(meta_line.arguments.kwargs.len(), 1);
            assert_eq!(meta_line.inline_text.content, "inline text");
            assert_eq!(meta_line.line_index, Some(5));
        } else {
            panic!("Expected BlockStarted event");
        }

        let event2 = iterator.next().unwrap();
        if let Event::TextFinished { lines, .. } = event2 {
            assert_eq!(lines.len(), 3);
            assert_eq!(lines[0], "Line one");
            assert_eq!(lines[1], "Line two");
            assert_eq!(lines[2], "Line three");
        } else {
            panic!("Expected TextFinished event");
        }

        let event3 = iterator.next().unwrap();
        assert!(matches!(event3, Event::BlockFinished));
    }

    #[test]
    fn test_iterator_behavior_with_very_small_bus_capacity() {
        // Test iterator behavior with very small bus capacity (capacity of 1)
        let mut bus = Bus::new(1);
        let reader = bus.add_rx();
        let mut iterator = BusReaderIterator::new(reader);

        let test_event = Event::BlockFinished;

        // With capacity 1, the bus should still work correctly
        bus.broadcast(test_event);

        let received = iterator.next();
        assert!(received.is_some());
        assert!(matches!(received, Some(Event::BlockFinished)));

        // After receiving the event, next call should block until bus is closed
        drop(bus);
        let received2 = iterator.next();
        assert!(received2.is_none());
    }

    #[test]
    fn test_iterator_with_maximum_bus_capacity() {
        // Test iterator with a large bus capacity
        let mut bus = Bus::new(1000);
        let reader = bus.add_rx();
        let mut iterator = BusReaderIterator::new(reader);

        // Send multiple events to test the large capacity
        let test_events: Vec<Event> = (0..100)
            .map(|i| Event::BlockStarted {
                meta_line: MetaLine {
                    level: 1,
                    type_name: format!("test_{i}"),
                    id: Id::new(format!("id_{i}")),
                    arguments: ParsedArguments {
                        args: vec![],
                        kwargs: vec![],
                    },
                    inline_text: QuotedString::new("".to_string(), false),
                    line_index: Some(i),
                    is_void: false,
                },
            })
            .collect();

        // Broadcast all events
        for event in &test_events {
            bus.broadcast(event.clone());
        }

        // Verify all events are received in order
        for i in 0..100 {
            let received = iterator.next();
            assert!(received.is_some());
            if let Some(Event::BlockStarted { meta_line }) = received {
                assert_eq!(meta_line.type_name, format!("test_{i}"));
                assert_eq!(meta_line.line_index, Some(i));
            } else {
                panic!("Expected BlockStarted event for index {i}");
            }
        }
    }

    #[test]
    fn test_iterator_error_handling_when_receiver_disconnected() {
        // Test iterator error handling when receiver is disconnected
        let mut bus = Bus::new(10);
        let reader = bus.add_rx();
        let mut iterator = BusReaderIterator::new(reader);

        // Send an event first
        let test_event = Event::BlockFinished;
        bus.broadcast(test_event);

        // Receive the event
        let received = iterator.next();
        assert!(received.is_some());

        // Drop the bus to disconnect
        drop(bus);

        // Further calls to next() should return None (graceful handling)
        let received2 = iterator.next();
        assert!(received2.is_none());

        // Multiple calls should consistently return None
        let received3 = iterator.next();
        assert!(received3.is_none());
    }

    #[test]
    fn test_concurrent_access_to_iterator_from_multiple_threads() {
        use std::sync::{Arc, Barrier};
        use std::thread;

        // Test concurrent access to iterator from multiple threads
        let mut bus = Bus::new(100);
        let reader = bus.add_rx();
        let iterator = Arc::new(std::sync::Mutex::new(BusReaderIterator::new(reader)));

        let barrier = Arc::new(Barrier::new(3)); // 2 worker threads + main thread
        let mut handles = vec![];

        // Clone references for threads
        let iterator_clone1 = Arc::clone(&iterator);
        let iterator_clone2 = Arc::clone(&iterator);
        let barrier_clone1 = Arc::clone(&barrier);
        let barrier_clone2 = Arc::clone(&barrier);

        // Thread 1: Try to read from iterator
        let handle1 = thread::spawn(move || {
            barrier_clone1.wait();
            let mut iter = iterator_clone1.lock().unwrap();
            iter.next() // May or may not receive an event depending on timing
        });

        // Thread 2: Try to read from iterator
        let handle2 = thread::spawn(move || {
            barrier_clone2.wait();
            let mut iter = iterator_clone2.lock().unwrap();
            iter.next() // May or may not receive an event depending on timing
        });

        handles.push(handle1);
        handles.push(handle2);

        // Wait for threads to be ready
        barrier.wait();

        // Send some events
        bus.broadcast(Event::BlockFinished);
        bus.broadcast(Event::BlockFinished);

        // Close the bus to unblock any waiting threads
        drop(bus);

        // Wait for all threads to complete
        let mut results = vec![];
        for handle in handles {
            results.push(handle.join().unwrap());
        }

        // At least one thread should have received an event or None (when bus closed)
        // This test mainly verifies that concurrent access doesn't cause panics or deadlocks
        assert!(results.len() == 2);
        // Both results should be either Some(Event::BlockFinished) or None
        for result in results {
            match result {
                Some(Event::BlockFinished) => {} // OK
                None => {}                       // OK - bus was closed
                _ => panic!("Unexpected event type received"),
            }
        }
    }
}
