use crate::consistency::{ConsistencyEngine, EntityState};
use serde_json::Value;
#[cfg(feature = "persona-graph")]
pub async fn enrich_user_response(
engine: &ConsistencyEngine,
workspace_id: &str,
user_id: &str,
response: &mut Value,
) {
let state = match engine.get_state(workspace_id).await {
Some(s) => s,
None => {
tracing::debug!("No unified state found for workspace: {}", workspace_id);
return;
}
};
let graph = match state.persona_graph() {
Some(g) => g,
None => {
tracing::debug!("No persona graph found for workspace: {}", workspace_id);
return;
}
};
let user_persona_id = format!("user:{}", user_id);
let related_order_ids =
graph.find_related_by_entity_type(&user_persona_id, "order", Some("has_orders"));
if let Some(obj) = response.as_object_mut() {
if !related_order_ids.is_empty() {
let order_ids: Vec<String> = related_order_ids
.iter()
.filter_map(|pid| pid.strip_prefix("order:").map(|s| s.to_string()))
.collect();
obj.insert(
"order_ids".to_string(),
Value::Array(order_ids.iter().map(|id| Value::String(id.clone())).collect()),
);
obj.insert("order_count".to_string(), Value::Number(order_ids.len().into()));
}
let related_account_ids =
graph.find_related_by_entity_type(&user_persona_id, "account", Some("has_accounts"));
if !related_account_ids.is_empty() {
let account_ids: Vec<String> = related_account_ids
.iter()
.filter_map(|pid| pid.strip_prefix("account:").map(|s| s.to_string()))
.collect();
obj.insert(
"account_ids".to_string(),
Value::Array(account_ids.iter().map(|id| Value::String(id.clone())).collect()),
);
}
}
}
#[cfg(feature = "persona-graph")]
pub async fn get_user_orders_via_graph(
engine: &ConsistencyEngine,
workspace_id: &str,
user_id: &str,
) -> Vec<EntityState> {
let state = match engine.get_state(workspace_id).await {
Some(s) => s,
None => {
tracing::debug!("No unified state found for workspace: {}", workspace_id);
return Vec::new();
}
};
let graph = match state.persona_graph() {
Some(g) => g,
None => {
tracing::debug!("No persona graph found for workspace: {}", workspace_id);
return Vec::new();
}
};
let user_persona_id = format!("user:{}", user_id);
let related_order_persona_ids =
graph.find_related_by_entity_type(&user_persona_id, "order", Some("has_orders"));
let mut orders = Vec::new();
for order_persona_id in related_order_persona_ids {
if let Some((_, order_id)) = order_persona_id.split_once(':') {
if let Some(entity) = state.get_entity("order", order_id) {
orders.push(entity.clone());
} else {
if let Some(entity) = engine.get_entity(workspace_id, "order", order_id).await {
orders.push(entity);
}
}
}
}
orders
}
#[cfg(feature = "persona-graph")]
pub async fn enrich_order_response(
engine: &ConsistencyEngine,
workspace_id: &str,
order_id: &str,
response: &mut Value,
) {
let state = match engine.get_state(workspace_id).await {
Some(s) => s,
None => {
tracing::debug!("No unified state found for workspace: {}", workspace_id);
return;
}
};
let graph = match state.persona_graph() {
Some(g) => g,
None => {
tracing::debug!("No persona graph found for workspace: {}", workspace_id);
return;
}
};
let order_persona_id = format!("order:{}", order_id);
let related_payment_ids =
graph.find_related_by_entity_type(&order_persona_id, "payment", Some("has_payments"));
if let Some(obj) = response.as_object_mut() {
if !related_payment_ids.is_empty() {
let payment_ids: Vec<String> = related_payment_ids
.iter()
.filter_map(|pid| pid.strip_prefix("payment:").map(|s| s.to_string()))
.collect();
obj.insert(
"payment_ids".to_string(),
Value::Array(payment_ids.iter().map(|id| Value::String(id.clone())).collect()),
);
}
let edges_to = graph.get_edges_to(&order_persona_id);
for edge in edges_to {
if edge.relationship_type == "has_orders" {
if let Some((entity_type, user_id)) = edge.from.split_once(':') {
if entity_type == "user" {
obj.insert("user_id".to_string(), Value::String(user_id.to_string()));
if let Some(user_entity) = state.get_entity("user", user_id) {
if let Some(user_data) = user_entity.data.as_object() {
if let Some(name) = user_data.get("name") {
obj.insert("user_name".to_string(), name.clone());
}
if let Some(email) = user_data.get("email") {
obj.insert("user_email".to_string(), email.clone());
}
}
}
break;
}
}
}
}
}
}
#[cfg(feature = "persona-graph")]
pub async fn enrich_response_via_graph(
engine: &ConsistencyEngine,
workspace_id: &str,
path: &str,
entity_id: Option<&str>,
response: &mut Value,
) {
let path_lower = path.to_lowercase();
if path_lower.contains("/users/") {
if let Some(id) = entity_id {
enrich_user_response(engine, workspace_id, id, response).await;
}
} else if path_lower.contains("/orders/") {
if let Some(id) = entity_id {
enrich_order_response(engine, workspace_id, id, response).await;
}
}
}
#[cfg(not(feature = "persona-graph"))]
pub async fn enrich_user_response(
_engine: &ConsistencyEngine,
_workspace_id: &str,
_user_id: &str,
_response: &mut Value,
) {
}
#[cfg(not(feature = "persona-graph"))]
pub async fn get_user_orders_via_graph(
_engine: &ConsistencyEngine,
_workspace_id: &str,
_user_id: &str,
) -> Vec<EntityState> {
Vec::new()
}
#[cfg(not(feature = "persona-graph"))]
pub async fn enrich_order_response(
_engine: &ConsistencyEngine,
_workspace_id: &str,
_order_id: &str,
_response: &mut Value,
) {
}
#[cfg(not(feature = "persona-graph"))]
pub async fn enrich_response_via_graph(
_engine: &ConsistencyEngine,
_workspace_id: &str,
_path: &str,
_entity_id: Option<&str>,
_response: &mut Value,
) {
}