use super::*;
use jellyflow_core::core::{
    Edge, EdgeId, EdgeKind, Graph, GraphBuilder, GraphId, NodeId, Port, PortCapacity,
    PortDirection, PortId, PortKey, PortKind,
};

#[test]
fn view_state_sanitize_removes_stale_ids() {
    let graph_id = GraphId::new();
    let mut graph = GraphBuilder::new(graph_id);

    let keep_node = NodeId::new();
    graph.insert_node(
        keep_node,
        jellyflow_core::core::Node {
            kind: jellyflow_core::core::NodeKindKey::new("test"),
            kind_version: 1,
            pos: jellyflow_core::core::CanvasPoint { x: 0.0, y: 0.0 },
            origin: None,
            selectable: None,
            focusable: None,
            draggable: None,
            connectable: None,
            deletable: None,
            parent: None,
            extent: None,
            expand_parent: None,
            size: None,
            hidden: false,
            collapsed: false,
            ports: Vec::new(),
            data: serde_json::Value::Null,
        },
    );
    let from_port = PortId::new();
    let to_port = PortId::new();
    let hidden_edge = EdgeId::new();
    let keep_edge = EdgeId::new();
    graph.insert_port(
        from_port,
        Port {
            node: keep_node,
            key: PortKey::new("from"),
            dir: PortDirection::Out,
            kind: PortKind::Data,
            capacity: PortCapacity::Multi,
            connectable: None,
            connectable_start: None,
            connectable_end: None,
            ty: None,
            data: serde_json::Value::Null,
        },
    );
    graph.insert_port(
        to_port,
        Port {
            node: keep_node,
            key: PortKey::new("to"),
            dir: PortDirection::In,
            kind: PortKind::Data,
            capacity: PortCapacity::Multi,
            connectable: None,
            connectable_start: None,
            connectable_end: None,
            ty: None,
            data: serde_json::Value::Null,
        },
    );
    graph.insert_edge(
        hidden_edge,
        Edge {
            hidden: true,
            ..Edge::new(EdgeKind::Data, from_port, to_port)
        },
    );
    graph.insert_edge(keep_edge, Edge::new(EdgeKind::Data, from_port, to_port));

    let mut state = NodeGraphViewState {
        selected_nodes: vec![keep_node, NodeId::new()],
        selected_edges: vec![hidden_edge, keep_edge],
        draw_order: vec![NodeId::new(), keep_node],
        edge_draw_order: vec![EdgeId::new(), hidden_edge, keep_edge],
        ..NodeGraphViewState::default()
    };

    state.sanitize_for_graph(&graph);
    assert_eq!(state.selected_nodes, vec![keep_node]);
    assert_eq!(state.selected_edges, vec![keep_edge]);
    assert_eq!(state.draw_order, vec![keep_node]);
    assert_eq!(state.edge_draw_order, vec![keep_edge]);
}

#[test]
fn view_state_sanitize_normalizes_invalid_viewport() {
    let graph = Graph::new(GraphId::new());
    let mut state = NodeGraphViewState {
        pan: jellyflow_core::core::CanvasPoint {
            x: f32::INFINITY,
            y: 10.0,
        },
        zoom: -1.0,
        ..NodeGraphViewState::default()
    };

    state.sanitize_for_graph(&graph);

    assert_eq!(state.pan, jellyflow_core::core::CanvasPoint::default());
    assert_eq!(state.zoom, NodeGraphViewState::default().zoom);

    state.set_viewport(
        jellyflow_core::core::CanvasPoint {
            x: 1.0,
            y: f32::NAN,
        },
        f32::NAN,
    );

    assert_eq!(state.pan, jellyflow_core::core::CanvasPoint::default());
    assert_eq!(state.zoom, NodeGraphViewState::default().zoom);
}
