use serde::Deserialize;

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

const TAVILY_SEARCH_URL: &str = "https://api.tavily.com/search";

#[derive(Debug, Deserialize)]
struct TavilyResponse {
    #[serde(default)]
    answer: Option<String>,
    #[serde(default)]
    results: Vec<TavilyResult>,
}

#[derive(Debug, Deserialize)]
struct TavilyResult {
    title: String,
    url: String,
    #[serde(default)]
    content: String,
    #[serde(default)]
    #[serde(alias = "publishedDate")]
    published_date: Option<String>,
}

pub async fn search(query: &str, api_key: &str, count: u8) -> Result<Vec<SearchResult>, String> {
    let max_results = count.clamp(1, 10);
    let client = reqwest::Client::new();

    let response = client
        .post(TAVILY_SEARCH_URL)
        .header("Authorization", format!("Bearer {}", api_key))
        .header("Content-Type", "application/json")
        .json(&serde_json::json!({
            "query": query,
            "topic": "general",
            "search_depth": "advanced",
            "include_answer": true,
            "include_raw_content": false,
            "max_results": max_results,
        }))
        .send()
        .await
        .map_err(|e| format!("Tavily search request failed: {}", e))?;

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

    let tavily_response: TavilyResponse = response
        .json()
        .await
        .map_err(|e| format!("Failed to parse Tavily response: {}", e))?;

    let answer = tavily_response.answer.unwrap_or_default();
    let mut results: Vec<SearchResult> = tavily_response
        .results
        .into_iter()
        .map(|result| SearchResult {
            title: result.title,
            url: result.url,
            description: result.content,
            age: result.published_date,
        })
        .collect();

    if !answer.is_empty() {
        if let Some(first) = results.first_mut() {
            if first.description.is_empty() {
                first.description = format!("AI summary: {}", answer);
            } else {
                first.description = format!(
                    "AI summary: {}\nSource excerpt: {}",
                    answer, first.description
                );
            }
        } else {
            results.push(SearchResult {
                title: "AI Summary".to_string(),
                url: String::new(),
                description: answer,
                age: None,
            });
        }
    }

    Ok(results)
}
