use crate::AppState;
use anyhow::{anyhow, Result};
use serde_json::{json, Value};
use trusty_common::memory_core::store::wings::{
list_wings, rename_wing, resolve_or_create_wing, resolve_wing_selector, WingSummary,
};
use trusty_common::memory_core::PalaceHandle;
use uuid::Uuid;
use super::helpers::{open_palace_handle, resolve_palace};
use super::palace_index::{resolve_palace_or_index, PalaceScope};
fn wing_json(w: &WingSummary) -> Value {
json!({
"wing_id": w.id.to_string(),
"label": w.label,
"description": w.description,
"room_count": w.room_count,
"is_default": w.is_default,
"created_at": chrono::DateTime::from_timestamp_millis(w.created_at_ms)
.map(|t| t.to_rfc3339()),
})
}
pub(crate) fn resolve_wing_arg(
handle: &PalaceHandle,
args: &Value,
tool: &str,
) -> Result<Option<Uuid>> {
let Some(selector) = args.get("wing").and_then(|v| v.as_str()) else {
return Ok(None);
};
if selector.trim().is_empty() {
return Ok(None);
}
resolve_wing_selector(&handle.kg, selector)
.map_err(|e| anyhow!("{tool}: resolve wing {selector:?}: {e:#}"))?
.map(Some)
.ok_or_else(|| anyhow!("{tool}: unknown wing {selector:?} (try wing_list)"))
}
pub(crate) async fn handle_wing_list(state: &AppState, args: Value) -> Result<Value> {
let palace = match resolve_palace_or_index(state, &args, "wing_list").await? {
PalaceScope::Palace(p) => p,
PalaceScope::Index(index) => return Ok(index),
};
let handle = open_palace_handle(state, &palace)?;
let wings = list_wings(&handle.kg).map_err(|e| anyhow!("wing_list: {e:#}"))?;
let payload: Vec<Value> = wings.iter().map(wing_json).collect();
Ok(json!({ "palace": palace, "wings": payload }))
}
pub(crate) async fn handle_wing_create(state: &AppState, args: Value) -> Result<Value> {
let palace = resolve_palace(state, &args, "wing_create")?;
let label = args
.get("label")
.and_then(|v| v.as_str())
.map(str::trim)
.filter(|s| !s.is_empty())
.ok_or_else(|| anyhow!("wing_create: missing or blank 'label'"))?;
let handle = open_palace_handle(state, &palace)?;
let (id, created) = resolve_or_create_wing(&handle.kg, label)
.await
.map_err(|e| anyhow!("wing_create: {e:#}"))?;
Ok(json!({
"palace": palace,
"wing_id": id.to_string(),
"label": label,
"created": created,
}))
}
pub(crate) async fn handle_wing_rename(state: &AppState, args: Value) -> Result<Value> {
let palace = resolve_palace(state, &args, "wing_rename")?;
let new_label = args
.get("new_label")
.and_then(|v| v.as_str())
.map(str::trim)
.filter(|s| !s.is_empty())
.ok_or_else(|| anyhow!("wing_rename: missing or blank 'new_label'"))?;
let handle = open_palace_handle(state, &palace)?;
let id = resolve_wing_arg(&handle, &args, "wing_rename")?
.ok_or_else(|| anyhow!("wing_rename: missing 'wing'"))?;
let summary = rename_wing(&handle.kg, id, new_label)
.await
.map_err(|e| anyhow!("wing_rename: {e:#}"))?;
Ok(json!({ "palace": palace, "wing": wing_json(&summary) }))
}