#!/usr/bin/env python3
"""Tests for Story 1.02 (Track B): InterceptorChain"""
import asyncio
import sys
sys.path.insert(0, '/mnt/e/genesis-system')

def test_interceptor_chain():
    from core.interceptors.base_interceptor import BaseInterceptor, InterceptorMetadata
    from core.interceptors.interceptor_chain import InterceptorChain

    # Create test interceptors
    execution_order = []

    class TestInterceptorA(BaseInterceptor):
        metadata = InterceptorMetadata(name="alpha", priority=10)
        async def pre_execute(self, p):
            execution_order.append("A")
            p["alpha"] = True
            return p
        async def post_execute(self, r, p): pass
        async def on_error(self, e, p): return {"handler": "A"}
        async def on_correction(self, c): return c

    class TestInterceptorB(BaseInterceptor):
        metadata = InterceptorMetadata(name="beta", priority=5)
        async def pre_execute(self, p):
            execution_order.append("B")
            p["beta"] = True
            return p
        async def post_execute(self, r, p): pass
        async def on_error(self, e, p): return {"handler": "B"}
        async def on_correction(self, c): return c

    class TestInterceptorC(BaseInterceptor):
        metadata = InterceptorMetadata(name="gamma", priority=20, enabled=False)
        async def pre_execute(self, p):
            execution_order.append("C")
            p["gamma"] = True
            return p
        async def post_execute(self, r, p): pass
        async def on_error(self, e, p): return {"handler": "C"}
        async def on_correction(self, c): return c

    async def run_tests():
        chain = InterceptorChain()

        # Register out of order
        chain.register(TestInterceptorA())
        chain.register(TestInterceptorC())
        chain.register(TestInterceptorB())

        # BB1: Priority ordering — B(5) before A(10) before C(20)
        execution_order.clear()
        result = await chain.execute_pre({"start": True})
        assert execution_order == ["B", "A"], f"Expected ['B', 'A'], got {execution_order}"
        assert result["beta"] == True
        assert result["alpha"] == True
        assert "gamma" not in result  # C is disabled

        # BB2: Disabled interceptor skipped
        assert "gamma" not in result

        # BB3: get_chain_summary
        summary = chain.get_chain_summary()
        assert len(summary) == 3
        assert summary[0]["name"] == "beta"
        assert summary[0]["priority"] == 5
        assert summary[2]["enabled"] == False

        # WB1: _interceptors sorted after register
        priorities = [i.metadata.priority for i in chain._interceptors]
        assert priorities == sorted(priorities)

        # WB2: execute_post continues even if one raises
        class RaisingInterceptor(BaseInterceptor):
            metadata = InterceptorMetadata(name="raiser", priority=1)
            async def pre_execute(self, p): return p
            async def post_execute(self, r, p): raise RuntimeError("boom")
            async def on_error(self, e, p): return {}
            async def on_correction(self, c): return c

        chain2 = InterceptorChain()
        chain2.register(RaisingInterceptor())
        chain2.register(TestInterceptorA())
        # Should not raise
        await chain2.execute_post({"done": True}, {"start": True})

        # BB4: execute_error returns first handler's result
        error_result = await chain.execute_error(ValueError("test"), {})
        assert error_result["handler"] == "B"  # B has priority 5 (first enabled)

        # WB3: unregister
        removed = chain.unregister("beta")
        assert removed == True
        assert len(chain) == 2

        removed_again = chain.unregister("nonexistent")
        assert removed_again == False

    asyncio.run(run_tests())
    print("ALL TESTS PASSED — Story 1.02 (Track B)")

if __name__ == "__main__":
    test_interceptor_chain()
