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

pub struct FileExistsNode;

impl EvalImpl for FileExistsNode {
    fn evaluate(&self, graph: &NodeGraph, ctx: &mut RuntimeContext, node: &Node, _pin_id: usize) -> Result<RuntimeValue, String> {
        let path = eval_input_string(graph, ctx, node.id, "path")?;
        let exists = std::path::Path::new(&path).exists();
        Ok(RuntimeValue::Bool(exists))
    }
}

impl super::super::framework::NodeDescription for FileExistsNode {
    fn description(&self) -> &str {
        "Checks if a file exists at the specified path."
    }
}

fn eval_input_string(graph: &NodeGraph, ctx: &mut RuntimeContext, node_id: usize, pin_name: &str) -> Result<String, String> {
     let val = eval_input_local(graph, ctx, node_id, pin_name)?;
    Ok(val.as_string())
}

fn eval_input_local(graph: &NodeGraph, ctx: &mut RuntimeContext, node_id: usize, pin_name: &str) -> Result<RuntimeValue, String> {
    let node = graph.get_node(node_id).ok_or("Node not found")?;
    let input_pin = node.pins.iter().find(|p| p.is_input && p.name == pin_name)
        .ok_or_else(|| format!("Pin {} not found", pin_name))?;
    let connection = graph.connections.iter().find(|c| c.to_node == node_id && c.to_pin == input_pin.id);

    if let Some(conn) = connection {
        crate::gui_builder::interpreter::eval_node_output(graph, ctx, conn.from_node, conn.from_pin)
    } else {
        Ok(RuntimeValue::String(String::new()))
    }
}

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, "path"));
    *next_pin_id += 1;
    pins.push(Pin::new(*next_pin_id, PinType::Bool, false, "exists"));
    *next_pin_id += 1;
    pins
}

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

crate::register_node!(NodeSpec {
    id: "FileExists",
    display_name: "File Exists",
    documentation: "Checks if a file exists at the specified path.",
    category: NodeCategory::FileSystem,
    library: NodeLibrary::FileSystem,
    param_kind: ParamKind::None,
    default_params,
    pins,
    execute: None,
    evaluate: Some(evaluate),
});
