//! Anthropic I/O — the ONLY place in `service/anthropic/` that may perform
//! network requests or store operations.
//!
//! Every function here is a thin adapter that converts lower-level errors
//! into the typed [`super::Error`] variants. No business logic or branching
//! lives here; that belongs in `mod.rs`.

use super::{Error, ModelSummary, ModelsResponse};
use crate::store::StoreOps;
use reqwest::header::{HeaderMap, HeaderValue};

/// Store key for the Anthropic API key — shared with `llm::chat`.
pub(crate) const KEY_ANTHROPIC_API_KEY: &str = "anthropic_api_key";

const ANTHROPIC_VERSION: &str = "2023-06-01";

/// Return whether a non-empty API key is stored.
pub(super) fn api_key_exists(store: &dyn StoreOps) -> bool {
    match store.get(KEY_ANTHROPIC_API_KEY) {
        Some(value) => value.as_str().map(|k| !k.is_empty()).unwrap_or(false),
        None => false,
    }
}

/// Read the stored API key, returning a typed error when absent or invalid.
pub(super) fn get_api_key(store: &dyn StoreOps) -> Result<String, Error> {
    match store.get(KEY_ANTHROPIC_API_KEY) {
        Some(value) => {
            if let Some(key) = value.as_str() {
                if key.is_empty() {
                    Err(Error::Validation(
                        "Anthropic API key is empty. Please set your API key.".to_string(),
                    ))
                } else {
                    Ok(key.to_string())
                }
            } else {
                Err(Error::Validation(
                    "Stored API key is not a string".to_string(),
                ))
            }
        }
        None => Err(Error::Validation(
            "Anthropic API key not found. Please set your API key.".to_string(),
        )),
    }
}

/// Persist a new API key to the store.
pub(super) fn save_api_key(store: &dyn StoreOps, api_key: &str) -> Result<(), String> {
    store.set(KEY_ANTHROPIC_API_KEY, serde_json::json!(api_key));
    store.save()
}

/// Fetch models from the Anthropic API at `url`.
pub(super) async fn fetch_models(api_key: &str, url: &str) -> Result<Vec<ModelSummary>, Error> {
    let client = reqwest::Client::new();
    let mut headers = HeaderMap::new();
    headers.insert(
        "x-api-key",
        HeaderValue::from_str(api_key)
            .map_err(|e| Error::Validation(format!("Invalid API key header value: {e}")))?,
    );
    headers.insert(
        "anthropic-version",
        HeaderValue::from_static(ANTHROPIC_VERSION),
    );

    let response = client
        .get(url)
        .headers(headers)
        .send()
        .await
        .map_err(|e| Error::UpstreamApi(e.to_string()))?;

    if !response.status().is_success() {
        let status = response.status();
        let error_text = response
            .text()
            .await
            .unwrap_or_else(|_| "Unknown error".to_string());
        return Err(Error::UpstreamApi(format!(
            "Anthropic API error {status}: {error_text}"
        )));
    }

    let body = response
        .json::<ModelsResponse>()
        .await
        .map_err(|e| Error::Internal(format!("Failed to parse response: {e}")))?;

    Ok(body
        .data
        .into_iter()
        .map(|m| ModelSummary {
            id: m.id,
            context_window: m.context_window,
        })
        .collect())
}
