//! `json::` — JSON parse and stringify. Reuses the bridge functions in
//! `crate::sdk::bridge` so script-visible JSON has the same shape
//! (numbers, maps, arrays, nulls) as `ctx.request.body` already does.

use rhai::{Dynamic, Engine as RhaiEngine, EvalAltResult, Module};

use crate::sdk::bridge::{dynamic_to_json_capped, json_to_dynamic, MAX_JSON_MATERIALIZE_BYTES};

pub fn register(engine: &mut RhaiEngine) {
    let mut module = Module::new();
    register_parse(&mut module);
    register_stringify(&mut module);
    register_stringify_pretty(&mut module);
    engine.register_static_module("json", module.into());
}

fn register_parse(module: &mut Module) {
    module.set_native_fn("parse", |s: &str| -> Result<Dynamic, Box<EvalAltResult>> {
        let value: serde_json::Value =
            serde_json::from_str(s).map_err(|e| format!("json::parse: {e}"))?;
        Ok(json_to_dynamic(value))
    });
}

fn register_stringify(module: &mut Module) {
    module.set_native_fn(
        "stringify",
        |v: Dynamic| -> Result<String, Box<EvalAltResult>> {
            serde_json::to_string(&dynamic_to_json_capped(&v, MAX_JSON_MATERIALIZE_BYTES)?)
                .map_err(|e| format!("json::stringify: {e}").into())
        },
    );
}

fn register_stringify_pretty(module: &mut Module) {
    module.set_native_fn(
        "stringify_pretty",
        |v: Dynamic| -> Result<String, Box<EvalAltResult>> {
            serde_json::to_string_pretty(&dynamic_to_json_capped(&v, MAX_JSON_MATERIALIZE_BYTES)?)
                .map_err(|e| format!("json::stringify_pretty: {e}").into())
        },
    );
}
