"""Tests for topological ordering (Kahn's algorithm)."""

import textwrap


def test_ordering_preserves_non_imply_tests(pytester):
    """Tests without implication markers keep their original order."""
    pytester.makepyfile(textwrap.dedent("""\
        import pytest

        order = []

        def test_a():
            order.append("a")

        def test_b():
            order.append("b")

        def test_c():
            order.append("c")

        def test_check():
            assert order == ["a", "b", "c"]
    """))
    result = pytester.runpytest("-v")
    result.assert_outcomes(passed=4)


def test_ordering_mixed_imply_and_plain(pytester):
    """Plain tests interleave correctly with implies/implied_by."""
    pytester.makepyfile(textwrap.dedent("""\
        import pytest

        order = []

        def test_first():
            order.append("first")

        @pytest.mark.implied_by("strong")
        def test_consumer():
            order.append("consumer")

        def test_middle():
            order.append("middle")

        @pytest.mark.implies("strong")
        def test_provider():
            order.append("provider")

        def test_last():
            order.append("last")

        def test_check():
            # provider must precede consumer; consumer is implied
            assert "provider" in order
            assert "consumer" not in order
    """))
    result = pytester.runpytest("-v")
    result.assert_outcomes(passed=6)


def test_diamond_dependency(pytester):
    """Diamond-shaped dependencies with transitive propagation."""
    pytester.makepyfile(textwrap.dedent("""\
        import pytest

        order = []

        @pytest.mark.implies("tok_a", "tok_b")
        def test_root():
            order.append("root")

        @pytest.mark.implied_by("tok_a")
        @pytest.mark.implies("tok_c")
        def test_left():
            order.append("left")
            raise RuntimeError("should not run")

        @pytest.mark.implied_by("tok_b")
        @pytest.mark.implies("tok_c")
        def test_right():
            order.append("right")
            raise RuntimeError("should not run")

        @pytest.mark.implied_by("tok_c")
        def test_bottom():
            order.append("bottom")
            raise RuntimeError("should not run")

        def test_check():
            # root passes → left, right implied (tok_a, tok_b)
            # left/right imply tok_c via transitive propagation
            # → bottom is also implied
            assert order == ["root"]
    """))
    result = pytester.runpytest("-v")
    result.assert_outcomes(passed=5)


def test_cycle_does_not_crash(pytester):
    """Circular implies/implied_by degrades gracefully with a warning."""
    pytester.makepyfile(textwrap.dedent("""\
        import pytest

        @pytest.mark.implies("tok_a")
        @pytest.mark.implied_by("tok_b")
        def test_x():
            assert True

        @pytest.mark.implies("tok_b")
        @pytest.mark.implied_by("tok_a")
        def test_y():
            assert True
    """))
    result = pytester.runpytest("-v")
    # Both should run (cycle fallback); no crash
    result.assert_outcomes(passed=2)
    result.stdout.fnmatch_lines(["*dependency cycle detected*"])
