use serde::Deserialize;

use crate::services::search::SearchResult;

const BRAVE_SEARCH_URL: &str = "https://api.search.brave.com/res/v1/web/search";

/// Partial Brave API response containing only the fields this app needs.
#[derive(Debug, Deserialize)]
struct BraveResponse {
    web: Option<BraveWebResults>,
}

#[derive(Debug, Deserialize)]
struct BraveWebResults {
    results: Vec<BraveResult>,
}

#[derive(Debug, Deserialize)]
struct BraveResult {
    title: String,
    url: String,
    #[serde(default)]
    description: String,
    age: Option<String>,
    #[serde(default)]
    extra_snippets: Option<Vec<String>>,
}

/// Search the web using the Brave Search API.
/// Returns a list of simplified search results.
pub async fn search(query: &str, api_key: &str, count: u8) -> Result<Vec<SearchResult>, String> {
    let count = count.clamp(1, 10);

    let client = reqwest::Client::new();

    let response = client
        .get(BRAVE_SEARCH_URL)
        .header("X-Subscription-Token", api_key)
        .header("Accept", "application/json")
        .header("Accept-Encoding", "gzip")
        .query(&[("q", query), ("count", &count.to_string())])
        .send()
        .await
        .map_err(|e| format!("Brave search request failed: {}", e))?;

    if !response.status().is_success() {
        let status = response.status();
        let body = response.text().await.unwrap_or_default();
        return Err(format!("Brave search error {}: {}", status, body));
    }

    let brave_response: BraveResponse = response
        .json()
        .await
        .map_err(|e| format!("Failed to parse Brave response: {}", e))?;

    let results = match brave_response.web {
        Some(web) => web
            .results
            .into_iter()
            .map(|r| {
                // Combine description with extra snippets for richer context
                let mut desc = r.description;
                if let Some(snippets) = r.extra_snippets {
                    for snippet in snippets.iter().take(2) {
                        desc.push_str(" ");
                        desc.push_str(snippet);
                    }
                }

                SearchResult {
                    title: r.title,
                    url: r.url,
                    description: desc,
                    age: r.age,
                }
            })
            .collect(),
        None => vec![],
    };

    Ok(results)
}
