//! Shared HTTP response handling for LLM API calls.

use super::error::{LlmError, Result};
use super::parser::parse_claims_json;
use crate::types::Claim;

/// Handle an LLM API response generically.
///
/// # Type Parameters
/// - `T`: The provider-specific response type
/// - `F`: A function that extracts the text content from the response body
pub async fn handle_api_response<T, F>(response: reqwest::Response, extract_text: F) -> Result<Vec<Claim>>
where
    T: for<'de> serde::Deserialize<'de>,
    F: FnOnce(T) -> Option<String>,
{
    match response.status().as_u16() {
        200 => {
            let body: T = response
                .json()
                .await
                .map_err(|e| LlmError::InvalidResponse(e.to_string()))?;
            let text = extract_text(body)
                .ok_or_else(|| LlmError::InvalidResponse("Empty response".into()))?;
            parse_claims_json(&text)
        }
        401 => Err(LlmError::AuthenticationFailed),
        429 => {
            let retry_after = response
                .headers()
                .get("retry-after")
                .and_then(|v| v.to_str().ok())
                .and_then(|s| s.parse().ok())
                .unwrap_or(60);
            Err(LlmError::RateLimited { retry_after_secs: retry_after })
        }
        503 => Err(LlmError::ServiceUnavailable("API overloaded".into())),
        _ => {
            let text = response.text().await.unwrap_or_default();
            Err(LlmError::InvalidResponse(text))
        }
    }
}
