/*
 * Hotdata API
 *
 * Powerful data platform API for datasets, queries, and analytics.
 *
 * The version of the OpenAPI document: 1.0.0
 * Contact: developers@hotdata.dev
 * Generated by: https://openapi-generator.tech
 */

use std::collections::HashMap;

#[derive(Debug, Clone)]
pub struct Configuration {
    pub base_path: String,
    pub user_agent: Option<String>,
    pub client: reqwest::Client,
    pub basic_auth: Option<BasicAuth>,
    pub oauth_access_token: Option<String>,
    pub bearer_access_token: Option<String>,
    pub token_provider: Option<std::sync::Arc<dyn crate::auth::BearerTokenProvider>>,
    pub api_keys: HashMap<String, ApiKey>,
}

pub type BasicAuth = (String, Option<String>);

#[derive(Debug, Clone)]
pub struct ApiKey {
    pub prefix: Option<String>,
    pub key: String,
}

impl Configuration {
    pub fn new() -> Configuration {
        Configuration::default()
    }

    /// Resolve the bearer token for a request, preferring a pluggable
    /// async token provider (e.g. the hand-written TokenManager) and
    /// falling back to the static bearer_access_token when none is set.
    ///
    /// If a provider is configured but errors (e.g. an API-token -> JWT
    /// exchange fails), the error is logged via the `log` facade and `None`
    /// is returned. The request then proceeds unauthenticated and the server
    /// replies 401; logging the cause keeps that 401 diagnosable instead of
    /// silently swallowing the real failure.
    pub async fn resolve_bearer_token(&self) -> Option<String> {
        if let Some(ref provider) = self.token_provider {
            match provider.bearer_value().await {
                Ok(token) => return Some(token),
                Err(e) => {
                    log::warn!(
                        "hotdata: bearer token resolution failed; \
                         sending request unauthenticated: {e}"
                    );
                    return None;
                }
            }
        }
        self.bearer_access_token.clone()
    }
}

impl Default for Configuration {
    fn default() -> Self {
        Configuration {
            base_path: "https://api.hotdata.dev".to_owned(),
            user_agent: Some("hotdata-rust/0.1.2".to_owned()),
            client: reqwest::Client::new(),
            basic_auth: None,
            oauth_access_token: None,
            bearer_access_token: None,
            token_provider: None,
            api_keys: HashMap::new(),
        }
    }
}
