use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum AstraGuardError {
#[error("network error: {0}")]
Network(#[from] reqwest::Error),
#[error("server error {status}: {body}")]
ServerError { status: u16, body: String },
#[error("json error: {0}")]
Json(#[from] serde_json::Error),
#[error("license rejected: {0}")]
LicenseRejected(String),
#[error("response signature mismatch - possible tampering detected")]
SignatureMismatch,
#[error("response auth key not configured - call with_response_auth() before validating")]
ResponseAuthNotConfigured,
#[error("failed to build HTTP client: {0}")]
Build(String),
}
pub type Result<T> = std::result::Result<T, AstraGuardError>;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LicenseResponse {
#[serde(default)]
pub valid: bool,
#[serde(default)]
pub success: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
#[serde(rename = "expiresAt", default, skip_serializing_if = "Option::is_none")]
pub expires_at: Option<String>,
#[serde(default)]
pub features: Vec<String>,
#[serde(default)]
pub variables: std::collections::HashMap<String, String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_offline_cache: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rt: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rts: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rn: Option<String>,
}
#[derive(Debug, Clone)]
pub struct LicenseDetails {
pub raw: LicenseResponse,
pub license_key: String,
pub expires_at: Option<std::time::SystemTime>,
pub is_offline: bool,
}
#[derive(Debug, Clone, Deserialize)]
pub struct UpdateCheckResponse {
#[serde(rename = "updateAvailable")]
pub has_update: bool,
#[serde(rename = "latestVersion", default)]
pub latest_version: Option<String>,
#[serde(
rename = "downloadUrl",
default,
skip_serializing_if = "Option::is_none"
)]
pub download_url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub changelog: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
}