use async_trait::async_trait;
use reqwest::Client;
use serde::Deserialize;
use tracing::instrument;

use crate::types::Claim;

use super::{
    client::{LlmClient, LlmConfig},
    error::{LlmError, Result},
    prompt,
    response::handle_api_response,
};

pub struct AnthropicClient {
    client: Client,
    config: LlmConfig,
}

#[derive(Debug, Deserialize)]
struct AnthropicResponse {
    content: Vec<ContentBlock>,
}

#[derive(Debug, Deserialize)]
struct ContentBlock {
    text: Option<String>,
}

impl AnthropicClient {
    pub fn new(config: LlmConfig) -> Self {
        let client = Client::builder()
            .timeout(std::time::Duration::from_secs(config.timeout_secs))
            .build()
            .unwrap_or_default();
        Self { client, config }
    }
}

#[async_trait]
impl LlmClient for AnthropicClient {
    #[instrument(skip(self), fields(text_len = text.len()))]
    async fn extract_claims(&self, text: &str) -> Result<Vec<Claim>> {
        let response = self
            .client
            .post("https://api.anthropic.com/v1/messages")
            .header("x-api-key", &self.config.api_key)
            .header("anthropic-version", "2023-06-01")
            .json(&serde_json::json!({
                "model": "claude-sonnet-4-20250514",
                "max_tokens": 4096,
                "system": prompt::EXTRACTION_SYSTEM_PROMPT,
                "messages": [{"role": "user", "content": prompt::build_extraction_message(text)}]
            }))
            .send()
            .await
            .map_err(|e| LlmError::from_reqwest(&e, self.config.timeout_secs))?;

        handle_api_response::<AnthropicResponse, _>(response, |body| {
            body.content.first().and_then(|c| c.text.clone())
        })
        .await
    }

    async fn test_connection(&self) -> Result<()> {
        // Send minimal request to verify API key
        let response = self
            .client
            .post("https://api.anthropic.com/v1/messages")
            .header("x-api-key", &self.config.api_key)
            .header("anthropic-version", "2023-06-01")
            .json(&serde_json::json!({
                "model": "claude-sonnet-4-20250514",
                "max_tokens": 10,
                "messages": [{"role": "user", "content": "Hi"}]
            }))
            .send()
            .await
            .map_err(|e| LlmError::from_reqwest(&e, self.config.timeout_secs))?;

        match response.status().as_u16() {
            200 => Ok(()),
            401 => Err(LlmError::AuthenticationFailed),
            _ => Err(LlmError::ServiceUnavailable(response.status().to_string())),
        }
    }
}
