use std::any::TypeId;
use std::sync::{Arc, RwLock};

use super::handler::{BoxedHandler, CustomHandlerId, HandlerEntry, HandlerOptions};
use super::response::EventResponse;
use super::types::{CustomEvent, DispatchPhase, EventEnvelope, EventMeta};
use super::DispatchResult;

/// Thread-safe event dispatcher
pub struct EventDispatcher {
    handlers: Arc<RwLock<Vec<HandlerEntry>>>,
    pending_removals: Arc<RwLock<Vec<CustomHandlerId>>>,
}

impl EventDispatcher {
    /// Create a new event dispatcher
    pub fn new() -> Self {
        Self {
            handlers: Arc::new(RwLock::new(Vec::new())),
            pending_removals: Arc::new(RwLock::new(Vec::new())),
        }
    }

    /// Register an event handler
    pub fn on<E: CustomEvent>(
        &mut self,
        handler: impl Fn(&E, &mut EventMeta) -> EventResponse + Send + Sync + 'static,
    ) -> CustomHandlerId {
        self.on_with_options::<E>(handler, HandlerOptions::default())
    }

    /// Register an event handler with options
    pub fn on_with_options<E: CustomEvent>(
        &mut self,
        handler: impl Fn(&E, &mut EventMeta) -> EventResponse + Send + Sync + 'static,
        options: HandlerOptions,
    ) -> CustomHandlerId {
        let id = CustomHandlerId::new();
        let type_id = TypeId::of::<E>();

        let boxed: BoxedHandler = Box::new(move |any, meta| {
            if let Some(event) = any.downcast_ref::<E>() {
                handler(event, meta)
            } else {
                EventResponse::Ignored
            }
        });

        let entry = HandlerEntry {
            id,
            handler: boxed,
            options,
            type_id,
        };

        if let Ok(mut handlers) = self.handlers.write() {
            handlers.push(entry);
            // Sort by priority (higher priority first)
            handlers.sort_by(|a, b| b.options.priority.cmp(&a.options.priority));
        }

        id
    }

    /// Register a one-time event handler
    pub fn once<E: CustomEvent>(
        &mut self,
        handler: impl Fn(&E, &mut EventMeta) -> EventResponse + Send + Sync + 'static,
    ) -> CustomHandlerId {
        self.on_with_options::<E>(handler, HandlerOptions::default().once(true))
    }

    /// Remove an event handler
    pub fn off(&mut self, handler_id: CustomHandlerId) {
        if let Ok(mut handlers) = self.handlers.write() {
            handlers.retain(|h| h.id != handler_id);
        }
    }

    /// Remove all handlers for a specific event type
    pub fn off_all<E: CustomEvent>(&mut self) {
        let type_id = TypeId::of::<E>();
        if let Ok(mut handlers) = self.handlers.write() {
            handlers.retain(|h| h.type_id != type_id);
        }
    }

    /// Clear all handlers
    pub fn clear(&mut self) {
        if let Ok(mut handlers) = self.handlers.write() {
            handlers.clear();
        }
    }

    /// Dispatch an event
    pub fn dispatch<E: CustomEvent>(&self, event: E) -> DispatchResult {
        self.dispatch_envelope(EventEnvelope::new(event))
    }

    /// Dispatch an event with custom envelope
    pub fn dispatch_envelope<E: CustomEvent>(&self, envelope: EventEnvelope<E>) -> DispatchResult {
        let EventEnvelope { event, mut meta } = envelope;
        let type_id = TypeId::of::<E>();
        let mut handlers_to_remove = Vec::new();
        let mut handler_count = 0;

        // Get read lock and process handlers
        let handlers = match self.handlers.read() {
            Ok(h) => h,
            Err(_) => return DispatchResult::error("Failed to acquire lock"),
        };

        // Process capture phase handlers first
        for entry in handlers.iter().filter(|h| h.type_id == type_id) {
            if entry.options.capture {
                meta.phase = DispatchPhase::Capture;
                let response = (entry.handler)(&event, &mut meta);
                handler_count += 1;

                if entry.options.once {
                    handlers_to_remove.push(entry.id);
                }

                if response.should_cancel() {
                    meta.cancel();
                }
                if response.should_stop() {
                    meta.stop_propagation();
                }
                if meta.is_propagation_stopped() || meta.is_immediate_propagation_stopped() {
                    break;
                }
            }
        }

        // Process target/bubble phase handlers
        if !meta.is_propagation_stopped() {
            for entry in handlers.iter().filter(|h| h.type_id == type_id) {
                if !entry.options.capture {
                    meta.phase = DispatchPhase::Target;
                    let response = (entry.handler)(&event, &mut meta);
                    handler_count += 1;

                    if entry.options.once {
                        handlers_to_remove.push(entry.id);
                    }

                    if response.should_cancel() {
                        meta.cancel();
                    }
                    if response.should_stop() {
                        meta.stop_propagation();
                    }
                    if meta.is_propagation_stopped() || meta.is_immediate_propagation_stopped() {
                        break;
                    }
                }
            }
        }

        // Drop the read lock before writing
        drop(handlers);

        // Remove one-time handlers
        if !handlers_to_remove.is_empty() {
            if let Ok(mut pending) = self.pending_removals.write() {
                pending.extend(handlers_to_remove);
            }
        }

        // Clean up pending removals
        self.cleanup_handlers();

        DispatchResult {
            event_id: meta.id,
            cancelled: meta.is_cancelled(),
            propagation_stopped: meta.is_propagation_stopped(),
            handler_count,
            error: None,
        }
    }

    /// Check if there are any handlers for an event type
    pub fn has_handlers<E: CustomEvent>(&self) -> bool {
        let type_id = TypeId::of::<E>();
        self.handlers
            .read()
            .map(|h| h.iter().any(|entry| entry.type_id == type_id))
            .unwrap_or(false)
    }

    /// Get the number of handlers for an event type
    pub fn handler_count<E: CustomEvent>(&self) -> usize {
        let type_id = TypeId::of::<E>();
        self.handlers
            .read()
            .map(|h| h.iter().filter(|entry| entry.type_id == type_id).count())
            .unwrap_or(0)
    }

    fn cleanup_handlers(&self) {
        let pending = {
            let mut pending = match self.pending_removals.write() {
                Ok(p) => p,
                Err(_) => return,
            };
            std::mem::take(&mut *pending)
        };

        if !pending.is_empty() {
            if let Ok(mut handlers) = self.handlers.write() {
                handlers.retain(|h| !pending.contains(&h.id));
            }
        }
    }
}

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

impl Clone for EventDispatcher {
    fn clone(&self) -> Self {
        Self {
            handlers: Arc::clone(&self.handlers),
            pending_removals: Arc::clone(&self.pending_removals),
        }
    }
}
