import pytest

from blends.models import (
    SyntaxGraph,
)
from blends.stack.edges import (
    Edge,
    add_edge,
)


@pytest.mark.blends_test_group("stack_unittesting")
def test_add_edge_from_reference_to_scope() -> None:
    graph = SyntaxGraph()
    graph.add_node(1, label_type="SymbolLookup", symbol="x")
    graph.add_node(2, label_type="File")

    add_edge(graph, Edge(source=1, sink=2, precedence=0))

    assert graph.has_edge(1, 2)
    edge_data = graph[1][2]
    assert edge_data["precedence"] == 0
    assert "label_stack" not in edge_data
    assert "symbol" not in edge_data


@pytest.mark.blends_test_group("stack_unittesting")
def test_add_edge_from_scope_to_definition() -> None:
    graph = SyntaxGraph()
    graph.add_node(1, label_type="File")
    graph.add_node(2, label_type="VariableDeclaration", variable="x")

    add_edge(graph, Edge(source=1, sink=2, precedence=0))

    assert graph.has_edge(1, 2)
    edge_data = graph[1][2]
    assert edge_data["precedence"] == 0
    assert "label_stack" not in edge_data
    assert "symbol" not in edge_data


@pytest.mark.blends_test_group("stack_unittesting")
def test_add_lookup_edge() -> None:
    graph = SyntaxGraph()
    graph.add_node(1, label_type="MethodDeclaration")
    graph.add_node(2, label_type="File")

    add_edge(graph, Edge(source=1, sink=2, precedence=0))

    assert graph.has_edge(1, 2)
    edge_data = graph[1][2]
    assert edge_data["precedence"] == 0
    assert "label_stack" not in edge_data
    assert "symbol" not in edge_data


@pytest.mark.blends_test_group("stack_unittesting")
def test_add_edge_from_reference_to_scope_with_precedence() -> None:
    graph = SyntaxGraph()
    graph.add_node(1, label_type="SymbolLookup", symbol="x")
    graph.add_node(2, label_type="File")

    add_edge(graph, Edge(source=1, sink=2, precedence=5))

    edge_data = graph[1][2]
    assert edge_data["precedence"] == 5  # noqa: PLR2004


@pytest.mark.blends_test_group("stack_unittesting")
def test_add_edge_from_scope_to_definition_with_precedence() -> None:
    graph = SyntaxGraph()
    graph.add_node(1, label_type="MethodDeclaration")
    graph.add_node(2, label_type="VariableDeclaration", variable="x")

    add_edge(graph, Edge(source=1, sink=2, precedence=10))

    edge_data = graph[1][2]
    assert edge_data["precedence"] == 10  # noqa: PLR2004


@pytest.mark.blends_test_group("stack_unittesting")
def test_multiple_edges_from_scope_to_definitions() -> None:
    graph = SyntaxGraph()
    graph.add_node(1, label_type="File")
    graph.add_node(2, label_type="VariableDeclaration", variable="x")
    graph.add_node(3, label_type="VariableDeclaration", variable="y")

    add_edge(graph, Edge(source=1, sink=2, precedence=0))
    add_edge(graph, Edge(source=1, sink=3, precedence=0))

    assert graph.has_edge(1, 2)
    assert graph.has_edge(1, 3)
    assert graph[1][2]["precedence"] == 0
    assert graph[1][3]["precedence"] == 0


@pytest.mark.blends_test_group("stack_unittesting")
def test_scope_hierarchy_with_lookup_edges() -> None:
    graph = SyntaxGraph()
    graph.add_node(1, label_type="File")
    graph.add_node(2, label_type="Class")
    graph.add_node(3, label_type="MethodDeclaration")

    add_edge(graph, Edge(source=2, sink=1, precedence=0))
    add_edge(graph, Edge(source=3, sink=2, precedence=0))

    assert graph.has_edge(2, 1)
    assert graph.has_edge(3, 2)
    assert graph[2][1]["precedence"] == 0
    assert graph[3][2]["precedence"] == 0
