use std::collections::HashMap;
use std::time::Duration;
use crate::error::Error;
const DEFAULT_BASE_URL: &str = "https://api.invoance.com";
const DEFAULT_TIMEOUT_MS: u64 = 30_000;
const ENV_API_KEY: &str = "INVOANCE_API_KEY";
const ENV_BASE_URL: &str = "INVOANCE_BASE_URL";
#[derive(Debug, Clone, Default)]
pub struct ClientConfig {
pub api_key: Option<String>,
pub base_url: Option<String>,
pub api_version: Option<String>,
pub timeout: Option<Duration>,
pub idempotency_key: Option<String>,
pub extra_headers: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub(crate) struct ResolvedConfig {
pub api_key: String,
pub base_url: String,
pub api_version: String,
pub timeout: Duration,
pub idempotency_key: Option<String>,
pub extra_headers: HashMap<String, String>,
}
pub(crate) fn resolve_config(cfg: ClientConfig) -> Result<ResolvedConfig, Error> {
let api_key = cfg
.api_key
.filter(|k| !k.is_empty())
.or_else(|| std::env::var(ENV_API_KEY).ok().filter(|k| !k.is_empty()))
.ok_or_else(|| {
Error::validation(format!(
"api_key is required. Pass it explicitly or set the {ENV_API_KEY} environment variable."
))
})?;
let base_url = cfg
.base_url
.filter(|u| !u.is_empty())
.or_else(|| std::env::var(ENV_BASE_URL).ok().filter(|u| !u.is_empty()))
.unwrap_or_else(|| DEFAULT_BASE_URL.to_string());
let base_url = base_url.trim_end_matches('/').to_string();
let api_version = cfg
.api_version
.unwrap_or_else(|| "v1".to_string())
.trim_matches('/')
.to_string();
Ok(ResolvedConfig {
api_key,
base_url,
api_version,
timeout: cfg
.timeout
.unwrap_or_else(|| Duration::from_millis(DEFAULT_TIMEOUT_MS)),
idempotency_key: cfg.idempotency_key,
extra_headers: cfg.extra_headers,
})
}