import json


def test_query_instances_injects_space_filter_and_formats_output(
    tools, cognite_client_mock, sample_config, make_dump_list
) -> None:
    cognite_client_mock.data_modeling.instances.query.return_value = {
        "orders": make_dump_list([{"externalId": "order-1"}], cursor="cursor-1")
    }

    query_definition = {
        "with": {
            "orders": {
                "nodes": {
                    "filter": {"equals": {"property": ["node", "externalId"], "value": "order-1"}},
                    "through": {
                        "source": {
                            "space": "cdf_idm",
                            "externalId": "CogniteOrder",
                            "version": "v1",
                        },
                        "identifier": "asset",
                    },
                    "limit": 5,
                }
            }
        },
        "select": {
            "orders": {
                "sources": [
                    {
                        "source": {
                            "space": "cdf_idm",
                            "externalId": "CogniteOrder",
                            "version": "v1",
                        },
                        "properties": ["name"],
                    }
                ]
            }
        },
    }
    payload = json.loads(tools["query_instances"](query_definition))

    query_object = cognite_client_mock.data_modeling.instances.query.call_args.args[0]
    node_expr = query_object.with_["orders"]
    filter_dump = node_expr.filter.dump()
    assert filter_dump["and"][0]["in"]["property"] == ["node", "space"]
    assert filter_dump["and"][0]["in"]["values"] == sample_config.instance_spaces
    assert node_expr.through.dump(camel_case=True)["source"]["type"] == "view"
    assert query_object.select["orders"].sources[0].properties == ["name"]

    assert payload["orders"]["count"] == 1
    assert payload["orders"]["cursor"] == "cursor-1"


def test_query_instances_handles_node_without_filter_and_edge_expression(
    tools, cognite_client_mock, sample_config, make_dump_list
) -> None:
    cognite_client_mock.data_modeling.instances.query.return_value = {"edges": make_dump_list([])}

    query_definition = {
        "with": {
            "start_nodes": {
                "nodes": {
                    "limit": 1,
                    "sort": [{"property": ["node", "createdTime"], "direction": "descending"}],
                }
            },
            "edges": {
                "edges": {
                    "from": "start_nodes",
                    "filter": {"exists": {"property": ["edge", "space"]}},
                    "direction": "inwards",
                    "chainTo": "source",
                    "limit": 3,
                    "maxDistance": 2,
                }
            },
        },
        "select": {
            "edges": {
                "sources": [
                    {
                        "source": {
                            "space": "cdf_idm",
                            "externalId": "CogniteOrder",
                            "version": "v1",
                        },
                        "properties": ["name"],
                    }
                ]
            }
        },
    }
    tools["query_instances"](query_definition)

    query_object = cognite_client_mock.data_modeling.instances.query.call_args.args[0]
    node_expr = query_object.with_["start_nodes"]
    edge_expr = query_object.with_["edges"]

    node_filter_dump = node_expr.filter.dump()
    assert node_filter_dump["in"]["property"] == ["node", "space"]
    assert node_filter_dump["in"]["values"] == sample_config.instance_spaces
    assert node_expr.sort[0].direction == "descending"

    edge_filter_dump = edge_expr.filter.dump()
    assert edge_filter_dump["and"][0]["in"]["property"] == ["edge", "space"]
    assert edge_expr.direction == "inwards"
    assert edge_expr.chain_to == "source"
    assert edge_expr.max_distance == 2
