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

/// A trait for types that can transform events
pub trait TransformerTrait: Send {
    /// Process events and return transformed events
    fn transform(&mut self, events: Vec<Event>) -> Vec<Event>;
}

/// Wrapper to make any Consumer + Emitter into a `TransformerTrait`
struct TransformerAdapter<T: Consumer + Emitter> {
    transformer: T,
}

impl<T: Consumer + Emitter + Send> TransformerTrait for TransformerAdapter<T> {
    fn transform(&mut self, events: Vec<Event>) -> Vec<Event> {
        // Feed events to the transformer
        self.transformer.on_start();
        for event in events {
            self.transformer.handle(event);
        }
        self.transformer.on_finish();

        // Collect output events from the transformer
        // The transformer should have accumulated events internally
        let reader = self.transformer.subscribe();
        reader.collect()
    }
}

/// An emitter that wraps another emitter and applies multiple transformers to its output.
/// This creates a new emitter from the composition of an emitter and transformers.
pub struct TransformersEmitter<E: Emitter + 'static>
where
    E::Reader: 'static,
{
    /// The base emitter
    emitter: E,
    /// The transformers to apply in sequence
    transformers: Vec<Arc<Mutex<dyn TransformerTrait>>>,
    /// Storage for transformed events
    output_events: Arc<Mutex<VecDeque<Event>>>,
}

impl<E: Emitter + 'static> TransformersEmitter<E>
where
    E::Reader: 'static,
{
    /// Create a new transformers emitter with multiple transformers
    fn new(emitter: E, transformers: Vec<Arc<Mutex<dyn TransformerTrait>>>) -> Self {
        Self {
            emitter,
            transformers,
            output_events: Arc::new(Mutex::new(VecDeque::new())),
        }
    }
}

/// Iterator for `TransformersEmitter`
pub struct TransformersEmitterIterator {
    events: Arc<Mutex<VecDeque<Event>>>,
}

impl Iterator for TransformersEmitterIterator {
    type Item = Event;

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

impl<E: Emitter + 'static> Emitter for TransformersEmitter<E>
where
    E::Reader: 'static,
{
    type Reader = TransformersEmitterIterator;

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

    fn run(self) {
        // Get the reader before running the emitter
        let base_reader = self.emitter.subscribe();

        // Run the emitter synchronously
        self.emitter.run();

        // Collect all events from the reader
        let mut current_events: Vec<Event> = base_reader.collect();

        // If no transformers, just pass through
        if self.transformers.is_empty() {
            if let Ok(mut output) = self.output_events.lock() {
                for event in current_events {
                    output.push_back(event);
                }
            }
            return;
        }

        // Process through each transformer in sequence
        for transformer in &self.transformers {
            if let Ok(mut t) = transformer.lock() {
                current_events = t.transform(current_events);
            }
        }

        // Store final output
        if let Ok(mut output) = self.output_events.lock() {
            for event in current_events {
                output.push_back(event);
            }
        }
    }
}

/// Convenience function to create a transformer pipeline from an emitter and multiple transformers.
/// Returns a new emitter that applies all transformers in sequence.
pub fn transformer_pipeline<E, T>(emitter: E, transformers: Vec<T>) -> TransformersEmitter<E>
where
    E: Emitter + 'static,
    E::Reader: 'static,
    T: Consumer + Emitter + Send + 'static,
{
    let wrapped_transformers: Vec<Arc<Mutex<dyn TransformerTrait>>> = transformers
        .into_iter()
        .map(|t| {
            Arc::new(Mutex::new(TransformerAdapter { transformer: t }))
                as Arc<Mutex<dyn TransformerTrait>>
        })
        .collect();

    TransformersEmitter::new(emitter, wrapped_transformers)
}

/// Convenience function to apply a single transformer to an emitter.
/// This is a simpler version of `transformer_pipeline` for the common single-transformer case.
pub fn apply_transformer<E, T>(emitter: E, transformer: T) -> TransformersEmitter<E>
where
    E: Emitter + 'static,
    E::Reader: 'static,
    T: Consumer + Emitter + Send + 'static,
{
    transformer_pipeline(emitter, vec![transformer])
}

/// A simplified pipeline builder for chaining transformers
pub struct PipelineBuilder {
    /// Storage for events during processing
    events: Vec<Event>,
}

impl PipelineBuilder {
    /// Create a new pipeline builder from an emitter
    pub fn from_emitter<E: Emitter>(emitter: E) -> Self {
        let reader = emitter.subscribe();
        emitter.run();

        Self {
            events: reader.collect(),
        }
    }

    /// Apply a transformer to the current events
    #[must_use]
    pub fn apply<T: Consumer + Emitter>(self, mut transformer: T) -> Self {
        transformer.on_start();
        for event in self.events {
            transformer.handle(event);
        }
        transformer.on_finish();

        Self {
            events: transformer.subscribe().collect(),
        }
    }

    /// Get the final events
    #[must_use]
    pub fn build(self) -> Vec<Event> {
        self.events
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::transformers::{EchoTransformer, SelectorTransformer};
    use crate::WasotFileEmitter;

    #[test]
    fn test_single_transformer() {
        let content = ".document\n..paragraph\nHello\n../\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let transformer = SelectorTransformer::new(vec!["paragraph".to_string()]);

        let composed = apply_transformer(emitter, transformer);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        assert!(!events.is_empty());
        assert!(events.len() < 10); // Filtered events
    }

    #[test]
    fn test_multiple_transformers_pipeline() {
        let content = ".document\n..section\n...paragraph\nHello\n.../\n../\n./";

        // Test with two selector transformers chained
        // The second transformer will only pass events when the stack matches "section"
        // But after the first filter, the stack context is lost, so we need both selectors
        // to match what we want
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let transformers = vec![
            SelectorTransformer::new(vec!["document".to_string(), "section".to_string()]), // Pass document and section
            SelectorTransformer::new(vec!["section".to_string()]), // Also must match section
        ];

        let composed = transformer_pipeline(emitter, transformers);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();

        // Should have filtered events appropriately
        assert!(
            !events.is_empty(),
            "Should have some events after transformers"
        );
    }

    #[test]
    fn test_empty_transformers_pipeline() {
        let content = ".document\nHello\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        let transformers: Vec<EchoTransformer> = vec![];
        let composed = transformer_pipeline(emitter, transformers);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        assert!(!events.is_empty()); // Should pass through all events
    }

    #[test]
    fn test_pipeline_builder() {
        let content = ".document\n..section\n...paragraph\nHello\n.../\n../\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        // Note: PipelineBuilder applies transformers sequentially
        // Each transformer gets a fresh state, so context is lost
        let events = PipelineBuilder::from_emitter(emitter)
            .apply(EchoTransformer::new())
            .apply(EchoTransformer::new())
            .build();

        assert!(!events.is_empty());
    }

    #[test]
    fn test_transformer_with_no_matching_events() {
        // Test when selector doesn't match any elements
        let content = ".document\nHello\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let transformer = SelectorTransformer::new(vec!["nonexistent".to_string()]);

        let composed = apply_transformer(emitter, transformer);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        assert_eq!(
            events.len(),
            0,
            "Should have no events when selector doesn't match"
        );
    }

    #[test]
    fn test_multiple_selectors_in_single_transformer() {
        let content =
            ".document\n..section\n...paragraph\nHello\n.../\n..footer\nFooter text\n../\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        // Multiple selectors in one transformer - should match both section and footer
        let transformer =
            SelectorTransformer::new(vec!["section".to_string(), "footer".to_string()]);

        let composed = apply_transformer(emitter, transformer);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        assert!(
            events.len() > 3,
            "Should have events from both section and footer"
        );
    }

    #[test]
    fn test_deeply_nested_selectors() {
        let content = ".a\n..b\n...c\n....d\n.....e\nDeep content\n...../\n..../\n.../\n../\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        // Test deep nesting selector
        let transformer = SelectorTransformer::new(vec!["e".to_string()]);

        let composed = apply_transformer(emitter, transformer);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        assert!(!events.is_empty(), "Should match deeply nested element");
    }

    #[test]
    fn test_empty_content() {
        // Edge case: empty content
        let content = "";
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let transformer = SelectorTransformer::new(vec!["any".to_string()]);

        let composed = apply_transformer(emitter, transformer);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        assert_eq!(events.len(), 0, "Empty content should produce no events");
    }

    #[test]
    fn test_single_line_content() {
        // Edge case: single line with no blocks
        let content = "Just text";
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let transformer = EchoTransformer::new();

        let composed = apply_transformer(emitter, transformer);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        assert!(!events.is_empty(), "Single line should produce text event");
    }

    #[test]
    fn test_transform_chain_order() {
        let content = ".document\n..header\nHeader\n../\n..section\nContent\n../\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        // Chain transformers - the second transformer gets events without context
        // So we need to configure both transformers to pass the right events
        let transformers = vec![
            SelectorTransformer::new(vec!["document".to_string(), "section".to_string()]),
            SelectorTransformer::new(vec!["section".to_string()]),
        ];

        let composed = transformer_pipeline(emitter, transformers);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        // Should filter to section-related events
        assert!(!events.is_empty(), "Should have some section events");
    }

    #[test]
    fn test_large_number_of_transformers() {
        // Stress test: many transformers in chain
        let content = ".document\n..section\nContent\n../\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        let mut transformers = vec![];
        for _ in 0..10 {
            transformers.push(EchoTransformer::new());
        }

        let composed = transformer_pipeline(emitter, transformers);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        assert!(
            !events.is_empty(),
            "Should pass through all events even with many transformers"
        );
    }

    #[test]
    fn test_transformer_state_isolation() {
        // Test that transformers don't interfere with each other's state
        let content = ".document\n..section\nContent\n../\n./";

        // Run first pipeline
        let emitter1 = WasotFileEmitter::from_string(content.to_string());
        let transformer1 = SelectorTransformer::new(vec!["section".to_string()]);
        let composed1 = apply_transformer(emitter1, transformer1);
        let reader1 = composed1.subscribe();
        composed1.run();
        let events1: Vec<Event> = reader1.collect();

        // Run second pipeline with same content but different selector
        let emitter2 = WasotFileEmitter::from_string(content.to_string());
        let transformer2 = SelectorTransformer::new(vec!["document".to_string()]);
        let composed2 = apply_transformer(emitter2, transformer2);
        let reader2 = composed2.subscribe();
        composed2.run();
        let events2: Vec<Event> = reader2.collect();

        // Events should be different based on selector
        assert_ne!(
            events1.len(),
            events2.len(),
            "Different selectors should produce different results"
        );
    }

    #[test]
    fn test_special_characters_in_content() {
        // Test content with special characters
        let content = ".document\n..section\n特殊文字🎉\n< > & \" '\n../\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let transformer = EchoTransformer::new();

        let composed = apply_transformer(emitter, transformer);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        assert!(!events.is_empty(), "Should handle special characters");

        // Verify text content is preserved
        for event in events {
            if let Event::TextFinished { lines, .. } = event {
                if !lines.is_empty() {
                    assert!(
                        lines.iter().any(|l| l.contains("特殊文字")),
                        "Should preserve Unicode"
                    );
                }
            }
        }
    }

    #[test]
    fn test_concurrent_subscriptions() {
        // Test multiple subscriptions to same pipeline
        // NOTE: Due to the current implementation using a shared VecDeque,
        // events are consumed when read, so multiple readers will compete
        let content = ".document\nContent\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let transformer = EchoTransformer::new();

        let composed = apply_transformer(emitter, transformer);

        // Create multiple subscriptions before running
        let reader1 = composed.subscribe();
        let reader2 = composed.subscribe();

        composed.run();

        // Both readers share the same event queue, so they compete for events
        let events1: Vec<Event> = reader1.collect();
        let events2: Vec<Event> = reader2.collect();

        // Total events between both readers should equal the original count
        assert!(
            events1.len() + events2.len() > 0,
            "Events should be distributed between readers"
        );
    }

    #[test]
    fn test_malformed_wasot_content() {
        // Test with malformed/incomplete blocks
        let content = ".document\n..section\nNo closing block";
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let transformer = EchoTransformer::new();

        let composed = apply_transformer(emitter, transformer);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        // Should handle gracefully - parser should still emit some events
        assert!(
            !events.is_empty(),
            "Should handle malformed content gracefully"
        );
    }

    #[test]
    fn test_transformer_error_handling() {
        // Test transformer that filters out all events
        let content = ".document\n..section\nContent\n../\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        // Chain of transformers where one filters everything
        let transformers = vec![
            SelectorTransformer::new(vec!["nonexistent".to_string()]), // Filters all
            SelectorTransformer::new(vec!["section".to_string()]),     // Should receive no events
        ];

        let composed = transformer_pipeline(emitter, transformers);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        assert_eq!(events.len(), 0, "Pipeline should handle empty event stream");
    }

    #[test]
    fn test_very_long_lines() {
        // Test with very long lines
        let long_line = "x".repeat(10000);
        let content = format!(".document\n{long_line}\n./");
        let emitter = WasotFileEmitter::from_string(content);
        let transformer = EchoTransformer::new();

        let composed = apply_transformer(emitter, transformer);
        let reader = composed.subscribe();
        composed.run();

        let events: Vec<Event> = reader.collect();
        assert!(!events.is_empty(), "Should handle very long lines");

        // Verify long content is preserved
        for event in events {
            if let Event::TextFinished { lines, .. } = event {
                if !lines.is_empty() && lines[0].len() > 9000 {
                    assert_eq!(lines[0].len(), 10000, "Long line should be preserved");
                }
            }
        }
    }

    #[test]
    fn test_pipeline_builder_empty() {
        // Test PipelineBuilder with no transformers
        let content = ".document\nContent\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        let events = PipelineBuilder::from_emitter(emitter).build();
        assert!(
            !events.is_empty(),
            "Builder with no transformers should pass all events"
        );
    }

    #[test]
    fn test_pipeline_builder_chain() {
        // Test PipelineBuilder with long chain of echo transformers
        let content = ".document\n..section\n...paragraph\nContent\n.../\n../\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        // Using echo transformers that pass everything through
        let events = PipelineBuilder::from_emitter(emitter)
            .apply(EchoTransformer::new())
            .apply(EchoTransformer::new())
            .apply(EchoTransformer::new())
            .build();

        assert!(!events.is_empty(), "Long builder chain should work");
    }

    #[test]
    fn test_thread_safety() {
        // Test that the Arc<Mutex<>> pattern works correctly
        use std::thread;

        let content = ".document\nContent\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());
        let transformer = EchoTransformer::new();

        let composed = apply_transformer(emitter, transformer);
        let reader = composed.subscribe();

        // Run in a separate thread
        let handle = thread::spawn(move || {
            composed.run();
        });

        handle.join().expect("Thread should complete");

        let events: Vec<Event> = reader.collect();
        assert!(!events.is_empty(), "Thread-based execution should work");
    }

    #[test]
    fn test_transformer_trait_implementation() {
        // Test specific lines of TransformerTrait implementation
        struct MockTransformer {
            events: Vec<Event>,
        }

        impl MockTransformer {
            fn new() -> Self {
                Self { events: Vec::new() }
            }
        }

        impl Consumer for MockTransformer {
            fn handle(&mut self, event: Event) {
                self.events.push(event);
            }
            fn on_start(&mut self) {}
            fn on_finish(&mut self) {}
        }

        impl Emitter for MockTransformer {
            type Reader = std::vec::IntoIter<Event>;

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

            fn run(self) {}
        }

        // Test TransformerAdapter transform method (covers line 17)
        let mut adapter = TransformerAdapter {
            transformer: MockTransformer::new(),
        };
        let test_events = vec![Event::BlockFinished];
        let result = adapter.transform(test_events);
        assert_eq!(result.len(), 1); // MockTransformer should pass through the event
    }

    #[test]
    fn test_transformers_emitter_new() {
        // Test TransformersEmitter::new function (covers line 51)
        let content = ".document\nContent\n./";
        let base_emitter = WasotFileEmitter::from_string(content.to_string());
        let transformers: Vec<Arc<Mutex<dyn TransformerTrait>>> = vec![];

        let emitter = TransformersEmitter::new(base_emitter, transformers);
        assert!(emitter.transformers.is_empty());
    }

    #[test]
    fn test_transformers_emitter_iterator_next() {
        // Test TransformersEmitterIterator::next method (covers lines 68-72)
        let events = Arc::new(Mutex::new(VecDeque::from([Event::BlockFinished])));
        let mut iterator = TransformersEmitterIterator {
            events: events.clone(),
        };

        // Test successful next
        let event = iterator.next();
        assert!(event.is_some());

        // Test empty next
        let empty_event = iterator.next();
        assert!(empty_event.is_none());
    }

    #[test]
    fn test_transformers_emitter_subscribe() {
        // Test TransformersEmitter::subscribe method (covers lines 83-85)
        let content = ".document\nContent\n./";
        let base_emitter = WasotFileEmitter::from_string(content.to_string());
        let transformers: Vec<Arc<Mutex<dyn TransformerTrait>>> = vec![];

        let emitter = TransformersEmitter::new(base_emitter, transformers);
        let reader = emitter.subscribe();

        // Verify reader is created
        assert!(reader.events.lock().is_ok());
    }

    #[test]
    fn test_transformers_emitter_run_empty_transformers() {
        // Test TransformersEmitter::run with no transformers (covers lines 89-106)
        let content = ".document\nContent\n./";
        let base_emitter = WasotFileEmitter::from_string(content.to_string());
        let transformers: Vec<Arc<Mutex<dyn TransformerTrait>>> = vec![];

        let emitter = TransformersEmitter::new(base_emitter, transformers);
        let reader = emitter.subscribe();
        emitter.run();

        let events: Vec<Event> = reader.collect();
        assert!(!events.is_empty());
    }

    #[test]
    fn test_transformer_pipeline_function() {
        // Test transformer_pipeline function (covers lines 127-141)
        let content = ".document\nContent\n./";
        let base_emitter = WasotFileEmitter::from_string(content.to_string());
        let transformers = vec![EchoTransformer::new()];

        let pipeline = transformer_pipeline(base_emitter, transformers);
        assert_eq!(pipeline.transformers.len(), 1);
    }

    #[test]
    fn test_apply_transformer_function() {
        // Test apply_transformer function (covers line 152)
        let content = ".document\nContent\n./";
        let base_emitter = WasotFileEmitter::from_string(content.to_string());
        let transformer = EchoTransformer::new();

        let pipeline = apply_transformer(base_emitter, transformer);
        assert_eq!(pipeline.transformers.len(), 1);
    }

    #[test]
    fn test_pipeline_builder_from_emitter() {
        // Test PipelineBuilder::from_emitter (covers lines 163-168)
        let content = ".document\nContent\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        let builder = PipelineBuilder::from_emitter(emitter);
        assert!(!builder.events.is_empty());
    }

    #[test]
    fn test_pipeline_builder_apply() {
        // Test PipelineBuilder::apply method (covers lines 174-182)
        let content = ".document\nContent\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        let builder = PipelineBuilder::from_emitter(emitter).apply(EchoTransformer::new());
        assert!(!builder.events.is_empty());
    }

    #[test]
    fn test_pipeline_builder_build() {
        // Test PipelineBuilder::build method (covers lines 188-189)
        let content = ".document\nContent\n./";
        let emitter = WasotFileEmitter::from_string(content.to_string());

        let events = PipelineBuilder::from_emitter(emitter).build();
        assert!(!events.is_empty());
    }
}
