import pytest

from test.stack.test_helpers import (
    count_defs_refs,
    find_symbol_nodes,
    resolve_symbol,
    setup_stack_resolution,
)


@pytest.mark.blends_test_group("stack_unittesting")
def test_tuple_unpacking() -> None:
    view, record = setup_stack_resolution("case_tuple_unpacking.py")
    for symbol in ["a", "b"]:
        defs, refs = count_defs_refs(view, symbol)
        assert defs == 1, f"Expected 1 def of '{symbol}', got {defs}"
        assert refs == 1, f"Expected 1 ref to '{symbol}', got {refs}"
        result = resolve_symbol(view, record, symbol)
        assert len(result) == 1, f"Expected '{symbol}' to resolve to 1 def, got {len(result)}"
        symbol_id = view.symbols.symbol_to_id.get(symbol)
        assert symbol_id is not None
        def_nodes = find_symbol_nodes(view, symbol_id=symbol_id, is_definition=True)
        assert result == def_nodes, f"'{symbol}' should resolve to its tuple-unpacking definition"


@pytest.mark.blends_test_group("stack_unittesting")
def test_for_tuple_unpack() -> None:
    view, record = setup_stack_resolution("case_for_tuple_unpack.py")
    for symbol in ["a", "b"]:
        defs, refs = count_defs_refs(view, symbol)
        assert defs == 1, f"Expected 1 def of '{symbol}', got {defs}"
        assert refs == 1, f"Expected 1 ref to '{symbol}', got {refs}"
        result = resolve_symbol(view, record, symbol)
        assert len(result) == 1, f"Expected '{symbol}' to resolve to 1 def, got {len(result)}"
        symbol_id = view.symbols.symbol_to_id.get(symbol)
        assert symbol_id is not None
        def_nodes = find_symbol_nodes(view, symbol_id=symbol_id, is_definition=True)
        assert result == def_nodes, f"'{symbol}' should resolve to its for-loop pattern definition"


@pytest.mark.blends_test_group("stack_unittesting")
def test_nested_unpacking() -> None:
    view, record = setup_stack_resolution("case_nested_unpacking.py")
    for symbol in ["a", "b", "c"]:
        defs, refs = count_defs_refs(view, symbol)
        assert defs == 1, f"Expected 1 def of '{symbol}', got {defs}"
        assert refs == 1, f"Expected 1 ref to '{symbol}', got {refs}"
        result = resolve_symbol(view, record, symbol)
        assert len(result) == 1, f"Expected '{symbol}' to resolve to 1 def, got {len(result)}"
        symbol_id = view.symbols.symbol_to_id.get(symbol)
        assert symbol_id is not None
        def_nodes = find_symbol_nodes(view, symbol_id=symbol_id, is_definition=True)
        assert result == def_nodes, f"'{symbol}' should resolve to its nested-unpacking definition"


@pytest.mark.blends_test_group("stack_unittesting")
def test_star_unpacking() -> None:
    view, record = setup_stack_resolution("case_star_unpacking.py")
    for symbol in ["first", "rest", "last"]:
        defs, refs = count_defs_refs(view, symbol)
        assert defs == 1, f"Expected 1 def of '{symbol}', got {defs}"
        assert refs == 1, f"Expected 1 ref to '{symbol}', got {refs}"
        result = resolve_symbol(view, record, symbol)
        assert len(result) == 1, f"Expected '{symbol}' to resolve to 1 def, got {len(result)}"
        symbol_id = view.symbols.symbol_to_id.get(symbol)
        assert symbol_id is not None
        def_nodes = find_symbol_nodes(view, symbol_id=symbol_id, is_definition=True)
        assert result == def_nodes, f"'{symbol}' should resolve to its star-unpacking definition"
