use super::super::framework::{EvalImpl, eval_input_string};
use crate::gui_builder::node_registry::{NodeSpec, ParamKind};
use crate::gui_builder::nodes::{Node, NodeCategory, NodeGraph, NodeLibrary, NodeParams, Pin, PinType};
use crate::gui_builder::runtime::{ComponentContext, RuntimeContext, RuntimeValue};

pub struct BuildJsonNode;

impl EvalImpl for BuildJsonNode {
    fn evaluate(&self, graph: &NodeGraph, ctx: &mut RuntimeContext, node: &Node, _pin_id: usize) -> Result<RuntimeValue, String> {
        let key1 = eval_input_string(graph, ctx, node.id, "key1")?;
        let val1 = eval_input_string(graph, ctx, node.id, "value1")?;
        let key2 = eval_input_string(graph, ctx, node.id, "key2")?;
        let val2 = eval_input_string(graph, ctx, node.id, "value2")?;
        
        // This relies on ctx.build_json(&[(k, v), ...])
        let pairs = [
            (key1.as_str(), val1.as_str()),
            (key2.as_str(), val2.as_str()),
        ];
        
        let val = ctx.build_json(&pairs).unwrap_or_default();
        Ok(RuntimeValue::String(val))
    }
}

impl super::super::framework::NodeDescription for BuildJsonNode {
    fn description(&self) -> &str {
        "Builds a JSON string from key/value inputs."
    }
}

fn default_params() -> NodeParams {
    NodeParams::None
}

fn pins(next_pin_id: &mut usize) -> Vec<Pin> {
    let mut pins = Vec::new();
    pins.push(Pin::new(*next_pin_id, PinType::String, true, "key1"));
    *next_pin_id += 1;
    pins.push(Pin::new(*next_pin_id, PinType::String, true, "value1"));
    *next_pin_id += 1;
    pins.push(Pin::new(*next_pin_id, PinType::String, true, "key2"));
    *next_pin_id += 1;
    pins.push(Pin::new(*next_pin_id, PinType::String, true, "value2"));
    *next_pin_id += 1;
    pins.push(Pin::new(*next_pin_id, PinType::String, false, "json"));
    *next_pin_id += 1;
    pins
}

fn eval(graph: &NodeGraph, ctx: &mut RuntimeContext, node: &Node, pin_id: usize) -> Result<RuntimeValue, String> {
    BuildJsonNode.evaluate(graph, ctx, node, pin_id)
}

crate::register_node!(NodeSpec {
    id: "BuildJson",
    display_name: "Build JSON",
    documentation: "Builds a JSON string from key/value inputs.",
    category: NodeCategory::Network,
    library: NodeLibrary::Http,
    param_kind: ParamKind::None,
    default_params,
    pins,
    execute: None,
    evaluate: Some(eval),
});
