use fusabi_host::{ExecutionContext, Result, Value};
use sigilforge_client::{SigilforgeClient, TokenProvider};
use std::sync::OnceLock;
static CLIENT: OnceLock<SigilforgeClient> = OnceLock::new();
fn get_client() -> &'static SigilforgeClient {
CLIENT.get_or_init(SigilforgeClient::new)
}
pub fn get_token(args: &[Value], _ctx: &ExecutionContext) -> Result<Value> {
let service = args.first().and_then(|v| v.as_str()).ok_or_else(|| {
fusabi_host::Error::host_function("sigilforge.get_token: service must be a string")
})?;
let account = args.get(1).and_then(|v| v.as_str()).ok_or_else(|| {
fusabi_host::Error::host_function("sigilforge.get_token: account must be a string")
})?;
let rt = tokio::runtime::Handle::try_current()
.map_err(|_| fusabi_host::Error::runtime("no tokio runtime available"))?;
let result = rt.block_on(async { get_client().get_token(service, account).await });
match result {
Ok(token) => Ok(Value::String(token.token)),
Err(e) => Err(fusabi_host::Error::runtime(e.to_string())),
}
}
pub fn ensure_token(args: &[Value], _ctx: &ExecutionContext) -> Result<Value> {
let service = args.first().and_then(|v| v.as_str()).ok_or_else(|| {
fusabi_host::Error::host_function("sigilforge.ensure_token: service must be a string")
})?;
let account = args.get(1).and_then(|v| v.as_str()).ok_or_else(|| {
fusabi_host::Error::host_function("sigilforge.ensure_token: account must be a string")
})?;
let rt = tokio::runtime::Handle::try_current()
.map_err(|_| fusabi_host::Error::runtime("no tokio runtime available"))?;
let result = rt.block_on(async { get_client().ensure_token(service, account).await });
match result {
Ok(token) => Ok(Value::String(token.token)),
Err(e) => Err(fusabi_host::Error::runtime(e.to_string())),
}
}
pub fn resolve(args: &[Value], _ctx: &ExecutionContext) -> Result<Value> {
let reference = args.first().and_then(|v| v.as_str()).ok_or_else(|| {
fusabi_host::Error::host_function("sigilforge.resolve: reference must be a string")
})?;
let rt = tokio::runtime::Handle::try_current()
.map_err(|_| fusabi_host::Error::runtime("no tokio runtime available"))?;
let result = rt.block_on(async { get_client().resolve(reference).await });
match result {
Ok(secret) => Ok(Value::String(secret.value)),
Err(e) => Err(fusabi_host::Error::runtime(e.to_string())),
}
}
pub fn is_available(_args: &[Value], _ctx: &ExecutionContext) -> Result<Value> {
let rt = tokio::runtime::Handle::try_current()
.map_err(|_| fusabi_host::Error::runtime("no tokio runtime available"))?;
let available = rt.block_on(async { get_client().is_daemon_available().await });
Ok(Value::Bool(available))
}