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_parameter_annotation_emits_ref_node() -> None:
    view, record = setup_stack_resolution("case_param_annotation_ref.py")
    defs, refs = count_defs_refs(view, "MyError")
    assert refs >= 1, f"Expected >= 1 ref to 'MyError', got {refs}"
    assert defs >= 1, f"Expected >= 1 def of 'MyError', got {defs}"

    symbol_id = view.symbols.symbol_to_id.get("MyError")
    assert symbol_id is not None
    def_nodes = find_symbol_nodes(view, symbol_id=symbol_id, is_definition=True)

    result = resolve_symbol(view, record, "MyError")
    assert result == def_nodes, f"Annotation ref should resolve to class def, got {result}"


@pytest.mark.blends_test_group("stack_unittesting")
def test_return_annotation_emits_ref_node() -> None:
    view, record = setup_stack_resolution("case_return_annotation_ref.py")
    defs, refs = count_defs_refs(view, "MyResult")
    assert refs >= 1, f"Expected >= 1 ref to 'MyResult', got {refs}"
    assert defs >= 1, f"Expected >= 1 def of 'MyResult', got {defs}"

    symbol_id = view.symbols.symbol_to_id.get("MyResult")
    assert symbol_id is not None
    def_nodes = find_symbol_nodes(view, symbol_id=symbol_id, is_definition=True)

    result = resolve_symbol(view, record, "MyResult")
    assert result == def_nodes, f"Return annotation ref should resolve to class def, got {result}"


@pytest.mark.blends_test_group("stack_unittesting")
def test_annotated_assignment_emits_ref_node() -> None:
    view, record = setup_stack_resolution("case_annotated_assign_ref.py")
    defs, refs = count_defs_refs(view, "Config")
    assert refs >= 1, f"Expected >= 1 ref to 'Config', got {refs}"
    assert defs >= 1, f"Expected >= 1 def of 'Config', got {defs}"

    symbol_id = view.symbols.symbol_to_id.get("Config")
    assert symbol_id is not None
    def_nodes = find_symbol_nodes(view, symbol_id=symbol_id, is_definition=True)

    result = resolve_symbol(view, record, "Config")
    assert result == def_nodes, f"Annotated assign ref should resolve to class def, got {result}"


@pytest.mark.blends_test_group("stack_unittesting")
def test_subscript_annotation_emits_ref_node() -> None:
    view, record = setup_stack_resolution("case_param_annotation_ref.py")
    defs, refs = count_defs_refs(view, "MyError")
    assert refs >= 2, f"Expected >= 2 refs to 'MyError' (plain + subscript), got {refs}"  # noqa: PLR2004
    assert defs >= 1, f"Expected >= 1 def of 'MyError', got {defs}"

    symbol_id = view.symbols.symbol_to_id.get("MyError")
    assert symbol_id is not None
    def_nodes = find_symbol_nodes(view, symbol_id=symbol_id, is_definition=True)

    for i in range(refs):
        result = resolve_symbol(view, record, "MyError", ref_index=i)
        assert result == def_nodes, (
            f"Subscript annotation ref[{i}] should resolve to class def, got {result}"
        )
