use leptos::children::Children;
use leptos::prelude::*;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = window)]
    fn highlightCode();

    #[wasm_bindgen(js_namespace = window)]
    fn highlightContainer(container: &str);
}

/// Utility functions for managing highlight.js in dynamic content
pub struct HighlightManager;

impl HighlightManager {
    /// Trigger highlighting for all new, unhighlighted code blocks
    pub fn highlight_all() {
        #[cfg(target_arch = "wasm32")]
        {
            highlightCode();
        }
    }

    /// Trigger highlighting for code blocks within a specific container
    #[allow(unused_variables)]
    pub fn highlight_container(selector: &str) {
        #[cfg(target_arch = "wasm32")]
        {
            highlightContainer(selector);
        }
    }

    /// Dispatch a custom event to trigger highlighting
    #[allow(unused_variables)]
    pub fn dispatch_highlight_event(container: Option<&str>) {
        #[cfg(target_arch = "wasm32")]
        {
            // Simplified version - just trigger highlighting without custom events
            if let Some(container_sel) = container {
                Self::highlight_container(container_sel);
            } else {
                Self::highlight_all();
            }
        }
    }
}

/// Leptos effect to trigger highlighting when content changes
#[allow(unused_variables)]
pub fn use_highlight_effect<F>(content_signal: F)
where
    F: Fn() -> String + 'static,
{
    #[cfg(target_arch = "wasm32")]
    Effect::new(move |_| {
        let _content = content_signal();
        // Small delay to ensure DOM is updated
        set_timeout(
            move || {
                HighlightManager::highlight_all();
            },
            std::time::Duration::from_millis(100),
        );
    });
}

/// Hook for components that load dynamic content with code
#[component]
pub fn WithHighlighting(
    children: Children,
    #[prop(optional)] container_id: String,
) -> impl IntoView {
    let container_class = if container_id.is_empty() {
        "highlight-container dynamic-content".to_string()
    } else {
        format!("highlight-container {container_id}")
    };

    #[cfg(target_arch = "wasm32")]
    let container_class_for_effect = container_class.clone();

    // Effect to highlight content after mount
    #[cfg(target_arch = "wasm32")]
    Effect::new(move |_| {
        let container_selector = format!(".{}", container_class_for_effect);
        set_timeout(
            move || {
                HighlightManager::highlight_container(&container_selector);
            },
            std::time::Duration::from_millis(50),
        );
    });

    view! {
        <div class=container_class>
            {children()}
        </div>
    }
}

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

    #[test]
    fn test_highlight_manager_methods() {
        // These functions should not panic when called
        HighlightManager::highlight_all();
        HighlightManager::highlight_container(".test");
        HighlightManager::dispatch_highlight_event(Some(".test"));
        HighlightManager::dispatch_highlight_event(None);
    }
}
