use crate::types::{DeltaRequest, DeltaResponse, ValidationResponse};
use crate::{Error, Result};
use reqwest::{Client as HttpClient, StatusCode};
use uuid::Uuid;
pub struct Client {
http_client: HttpClient,
api_key: String,
base_url: String,
}
impl Client {
pub fn new(api_key: impl Into<String>, base_url: impl Into<String>) -> Self {
Self {
http_client: HttpClient::new(),
api_key: api_key.into(),
base_url: base_url.into(),
}
}
pub async fn compute_delta(&self, source: &str, target: &str) -> Result<DeltaResponse> {
let request = DeltaRequest {
source: source.to_string(),
target: target.to_string(),
};
let url = format!("{}/api/delta", self.base_url);
let request_id = Uuid::new_v4().to_string();
let response = self
.http_client
.post(&url)
.header("X-API-Key", &self.api_key)
.header("X-Request-ID", &request_id)
.header("Content-Type", "application/json")
.json(&request)
.send()
.await?;
match response.status() {
StatusCode::OK => response
.json::<DeltaResponse>()
.await
.map_err(|e| Error::InvalidResponse(e.to_string())),
StatusCode::UNAUTHORIZED => Err(Error::Unauthorized),
StatusCode::TOO_MANY_REQUESTS => Err(Error::RateLimitExceeded),
StatusCode::PAYMENT_REQUIRED => Err(Error::QuotaExceeded),
status => Err(Error::Api(format!("API returned: {}", status))),
}
}
pub async fn validate_key(&self) -> Result<ValidationResponse> {
let url = format!("{}/api/validate", self.base_url);
let response = self
.http_client
.get(&url)
.header("X-API-Key", &self.api_key)
.send()
.await?;
match response.status() {
StatusCode::OK => response
.json::<ValidationResponse>()
.await
.map_err(|e| Error::InvalidResponse(e.to_string())),
StatusCode::UNAUTHORIZED => Err(Error::InvalidApiKey),
status => Err(Error::Api(format!("API returned: {}", status))),
}
}
pub fn set_api_key(&mut self, api_key: impl Into<String>) {
self.api_key = api_key.into();
}
pub fn base_url(&self) -> &str {
&self.base_url
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_client_creation() {
let client = Client::new("test-key", "https://example.com");
assert_eq!(client.base_url(), "https://example.com");
}
#[test]
fn test_set_api_key() {
let mut client = Client::new("old-key", "https://example.com");
client.set_api_key("new-key");
assert_eq!(client.api_key, "new-key");
}
#[test]
fn test_client_url_normalization() {
let client = Client::new("key", "https://example.com/");
assert_eq!(client.base_url(), "https://example.com/");
}
}