//! Utility functions for HTML scraping

use crate::error::{HHError, Result};
use scraper::{Html, Selector};

/// Parse HTML and extract text from elements matching a CSS selector
pub fn extract_text(html: &str, selector_str: &str) -> Result<Vec<String>> {
    let document = Html::parse_document(html);
    let selector = Selector::parse(selector_str)
        .map_err(|e| HHError::ParseError(format!("Invalid selector: {:?}", e)))?;

    let texts: Vec<String> = document
        .select(&selector)
        .map(|element| element.text().collect::<String>().trim().to_string())
        .filter(|text| !text.is_empty())
        .collect();

    Ok(texts)
}

/// Extract the first text matching a selector
pub fn extract_first_text(html: &str, selector_str: &str) -> Result<Option<String>> {
    let texts = extract_text(html, selector_str)?;
    Ok(texts.into_iter().next())
}

/// Extract attribute values from elements
pub fn extract_attributes(html: &str, selector_str: &str, attr: &str) -> Result<Vec<String>> {
    let document = Html::parse_document(html);
    let selector = Selector::parse(selector_str)
        .map_err(|e| HHError::ParseError(format!("Invalid selector: {:?}", e)))?;

    let attrs: Vec<String> = document
        .select(&selector)
        .filter_map(|element| element.value().attr(attr))
        .map(|s| s.to_string())
        .collect();

    Ok(attrs)
}

/// Clean up text by removing extra whitespace
pub fn clean_text(text: &str) -> String {
    text.split_whitespace()
        .collect::<Vec<_>>()
        .join(" ")
        .trim()
        .to_string()
}

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

    #[test]
    fn test_extract_text() {
        let html = r#"
            <html>
                <body>
                    <p class="test">Hello</p>
                    <p class="test">World</p>
                </body>
            </html>
        "#;

        let texts = extract_text(html, "p.test").unwrap();
        assert_eq!(texts, vec!["Hello", "World"]);
    }

    #[test]
    fn test_extract_first_text() {
        let html = r#"
            <html>
                <body>
                    <h1>Title</h1>
                </body>
            </html>
        "#;

        let text = extract_first_text(html, "h1").unwrap();
        assert_eq!(text, Some("Title".to_string()));
    }

    #[test]
    fn test_clean_text() {
        let text = "  Hello   World  \n  Test  ";
        let cleaned = clean_text(text);
        assert_eq!(cleaned, "Hello World Test");
    }
}
