use crate::events::{Consumer, Emitter, Event};
use crate::transformers::Transformer;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

/// A simple dummy transformer that echoes all events it receives.
/// This is the simplest possible transformer - it passes through
/// all events unchanged from input to output.
///
/// This transformer stores events in memory and allows them to be
/// read back via the iterator interface.
pub struct EchoTransformer {
    /// Shared storage for events that have been consumed
    events: Arc<Mutex<VecDeque<Event>>>,
}

impl EchoTransformer {
    /// Create a new EchoTransformer
    pub fn new() -> Self {
        Self {
            events: Arc::new(Mutex::new(VecDeque::new())),
        }
    }

    /// Clear all stored events
    pub fn clear(&mut self) {
        if let Ok(mut events) = self.events.lock() {
            events.clear();
        }
    }
}

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

impl Consumer for EchoTransformer {
    fn handle(&mut self, event: Event) {
        // Simply store every event we receive
        if let Ok(mut events) = self.events.lock() {
            events.push_back(event);
        }
    }

    fn on_start(&mut self) {
        // Nothing special to do on start
    }

    fn on_finish(&mut self) {
        // Nothing special to do on finish
    }
}

/// Iterator for reading events from the EchoTransformer
pub struct EchoTransformerIterator {
    events: Arc<Mutex<VecDeque<Event>>>,
}

impl Iterator for EchoTransformerIterator {
    type Item = Event;

    fn next(&mut self) -> Option<Self::Item> {
        if let Ok(mut events) = self.events.lock() {
            events.pop_front()
        } else {
            None
        }
    }
}

impl Emitter for EchoTransformer {
    type Reader = EchoTransformerIterator;

    fn subscribe(&self) -> Self::Reader {
        EchoTransformerIterator {
            events: Arc::clone(&self.events),
        }
    }

    fn run(self) {
        // For a transformer, run doesn't need to do anything special
        // The events are emitted as they are consumed
    }
}

impl Transformer for EchoTransformer {}

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

    #[test]
    fn test_echo_transformer_passes_through_events() {
        let mut transformer = EchoTransformer::new();

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

        // Consume the event
        transformer.handle(event.clone());

        // Check that we can read back the same event
        let mut reader = transformer.subscribe();
        let received = reader.next().unwrap();
        match (event, received) {
            (
                Event::BlockStarted {
                    meta_line: original,
                },
                Event::BlockStarted { meta_line: echoed },
            ) => {
                assert_eq!(original.line_index, echoed.line_index);
                assert_eq!(original.type_name, echoed.type_name);
            }
            _ => panic!("Events don't match"),
        }
    }

    #[test]
    fn test_echo_transformer_handles_multiple_events() {
        let mut transformer = EchoTransformer::new();

        // Send multiple events
        for i in 1..=3 {
            let meta = MetaLine {
                line_index: Some(i),
                level: 1,
                type_name: format!("block{i}"),
                id: Id::new("".to_string()),
                inline_text: QuotedString::new("".to_string(), false),
                arguments: ParsedArguments {
                    args: vec![],
                    kwargs: vec![],
                },
                is_void: false,
            };
            transformer.handle(Event::BlockStarted { meta_line: meta });
        }

        // Verify all events are received in order
        let mut reader = transformer.subscribe();
        for i in 1..=3 {
            let event = reader.next().unwrap();
            if let Event::BlockStarted { meta_line } = event {
                assert_eq!(meta_line.type_name, format!("block{i}"));
            } else {
                panic!("Unexpected event type");
            }
        }
    }

    #[test]
    fn test_echo_transformer_as_pipeline() {
        let mut transformer = EchoTransformer::new();

        // Simulate a pipeline: consume events and check they can be re-emitted
        let events = vec![
            Event::BlockStarted {
                meta_line: MetaLine {
                    line_index: Some(1),
                    is_void: false,
                    level: 1,
                    type_name: "document".to_string(),
                    id: Id::new("".to_string()),
                    inline_text: QuotedString::new("".to_string(), false),
                    arguments: ParsedArguments {
                        args: vec![],
                        kwargs: vec![],
                    },
                },
            },
            Event::TextFinished {
                lines: vec!["Hello world".to_string()],
                links: vec![vec![]],
                footnotes: vec![],
            },
            Event::BlockFinished,
        ];

        // Process all events
        for event in events.clone() {
            transformer.handle(event);
        }

        // Read them back
        let reader = transformer.subscribe();
        let collected: Vec<Event> = reader.collect();
        assert_eq!(collected.len(), 3);
        assert_eq!(collected, events);
    }

    #[test]
    fn test_echo_transformer_new() {
        // Test line 19 in function `new`
        let transformer = EchoTransformer::new();

        // Test line 21 in function `new` - verify the Arc<Mutex<VecDeque<Event>>> is initialized
        assert_eq!(transformer.events.lock().unwrap().len(), 0);
    }

    #[test]
    fn test_echo_transformer_clear() {
        let mut transformer = EchoTransformer::new();

        // Add some events first
        let meta = MetaLine {
            line_index: Some(1),
            is_void: false,
            level: 1,
            type_name: "test".to_string(),
            id: Id::new("".to_string()),
            inline_text: QuotedString::new("".to_string(), false),
            arguments: ParsedArguments {
                args: vec![],
                kwargs: vec![],
            },
        };
        transformer.handle(Event::BlockStarted { meta_line: meta });
        assert_eq!(transformer.events.lock().unwrap().len(), 1);

        // Test lines 26-28 in function `clear`
        transformer.clear();
        assert_eq!(transformer.events.lock().unwrap().len(), 0);
    }

    #[test]
    fn test_echo_transformer_default() {
        // Test lines 34-35 in function `default`
        let transformer = EchoTransformer::default();
        assert_eq!(transformer.events.lock().unwrap().len(), 0);
    }

    #[test]
    fn test_echo_transformer_handle() {
        let mut transformer = EchoTransformer::new();
        let meta = MetaLine {
            line_index: Some(1),
            is_void: false,
            level: 1,
            type_name: "test".to_string(),
            id: Id::new("".to_string()),
            inline_text: QuotedString::new("".to_string(), false),
            arguments: ParsedArguments {
                args: vec![],
                kwargs: vec![],
            },
        };
        let event = Event::BlockStarted { meta_line: meta };

        // Test line 40 in function `handle`
        transformer.handle(event.clone());

        // Test lines 42-43 in function `handle` - verify event was stored
        assert_eq!(transformer.events.lock().unwrap().len(), 1);
    }

    #[test]
    fn test_echo_transformer_consumer_lifecycle() {
        let mut transformer = EchoTransformer::new();

        // Test line 47 in function `on_start`
        transformer.on_start(); // Should not panic or change state
        assert_eq!(transformer.events.lock().unwrap().len(), 0);

        // Test line 51 in function `on_finish`
        transformer.on_finish(); // Should not panic or change state
        assert_eq!(transformer.events.lock().unwrap().len(), 0);
    }

    #[test]
    fn test_echo_transformer_iterator_next() {
        let mut transformer = EchoTransformer::new();
        let meta = MetaLine {
            line_index: Some(1),
            is_void: false,
            level: 1,
            type_name: "test".to_string(),
            id: Id::new("".to_string()),
            inline_text: QuotedString::new("".to_string(), false),
            arguments: ParsedArguments {
                args: vec![],
                kwargs: vec![],
            },
        };
        let event = Event::BlockStarted { meta_line: meta };

        transformer.handle(event.clone());
        let mut reader = transformer.subscribe();

        // Test lines 64-66 in function `next`
        let result = reader.next();
        assert!(result.is_some());

        // Test line 68 in function `next` - when queue is empty
        let result = reader.next();
        assert!(result.is_none());
    }

    #[test]
    fn test_echo_transformer_subscribe() {
        let transformer = EchoTransformer::new();

        // Test line 76 in function `subscribe`
        let _reader = transformer.subscribe();

        // Test line 78 in function `subscribe` - verify Arc::clone works
        // This is tested implicitly by the reader being able to access the same data
        let mut reader2 = transformer.subscribe();
        assert!(reader2.next().is_none()); // Empty initially
    }

    #[test]
    fn test_echo_transformer_run() {
        let transformer = EchoTransformer::new();

        // Test line 82 in function `run`
        transformer.run(); // Should not panic and complete successfully
    }
}
