use std::sync::OnceLock;
use car_a2ui::{A2uiEnvelope, A2uiSurfaceStore};
use serde_json::Value;
fn store() -> &'static A2uiSurfaceStore {
static STORE: OnceLock<A2uiSurfaceStore> = OnceLock::new();
STORE.get_or_init(A2uiSurfaceStore::new)
}
pub fn capabilities() -> Result<String, String> {
serde_json::to_string(&store().capabilities()).map_err(|e| e.to_string())
}
pub async fn apply(envelope_json: &str) -> Result<String, String> {
let envelope: A2uiEnvelope =
serde_json::from_str(envelope_json).map_err(|e| format!("invalid A2UI envelope: {e}"))?;
let result = store().apply(envelope).await.map_err(|e| e.to_string())?;
serde_json::to_string(&result).map_err(|e| e.to_string())
}
pub async fn ingest(payload_json: &str) -> Result<String, String> {
let value: Value =
serde_json::from_str(payload_json).map_err(|e| format!("invalid JSON payload: {e}"))?;
let s = store();
s.validate_payload(&value).map_err(|e| e.to_string())?;
let envelopes = car_a2ui::envelopes_from_value(&value).map_err(|e| e.to_string())?;
if envelopes.is_empty() {
return Err("no A2UI envelopes found in payload".into());
}
let owner = car_a2ui::owner_from_value(&value);
let mut applied = Vec::with_capacity(envelopes.len());
for envelope in envelopes {
let result = s
.apply_with_owner(envelope, owner.clone())
.await
.map_err(|e| e.to_string())?;
applied.push(result);
}
serde_json::to_string(&serde_json::json!({ "applied": applied })).map_err(|e| e.to_string())
}
pub async fn surfaces() -> Result<String, String> {
serde_json::to_string(&store().list().await).map_err(|e| e.to_string())
}
pub async fn get(surface_id: &str) -> Result<String, String> {
serde_json::to_string(&store().get(surface_id).await).map_err(|e| e.to_string())
}
pub async fn reap() -> Result<String, String> {
let removed = store().reap_expired(chrono::Utc::now()).await;
serde_json::to_string(&serde_json::json!({ "removed": removed })).map_err(|e| e.to_string())
}
pub fn validate_payload(value_json: &str) -> Result<String, String> {
let value: Value =
serde_json::from_str(value_json).map_err(|e| format!("invalid JSON payload: {e}"))?;
store()
.validate_payload(&value)
.map_err(|e| e.to_string())?;
Ok("null".to_string())
}