# core/interceptors/interceptor_chain.py
"""
Genesis Persistent Context Architecture — InterceptorChain
Story 1.02 — Track B

Ordered execution engine for interceptors. Runs all registered
interceptors in priority order (lower number = earlier execution).
"""
import asyncio
from typing import List, Optional
from .base_interceptor import BaseInterceptor


class InterceptorChain:
    """Ordered chain executor for Genesis interceptors."""

    def __init__(self):
        self._interceptors: List[BaseInterceptor] = []

    def register(self, interceptor: BaseInterceptor) -> None:
        """Register an interceptor. Chain re-sorts by priority after each add."""
        self._interceptors.append(interceptor)
        self._interceptors.sort(key=lambda x: x.metadata.priority)

    def unregister(self, name: str) -> bool:
        """Remove interceptor by name. Returns True if found and removed."""
        before = len(self._interceptors)
        self._interceptors = [i for i in self._interceptors if i.metadata.name != name]
        return len(self._interceptors) < before

    async def execute_pre(self, payload: dict) -> dict:
        """Run all enabled interceptors' pre_execute in priority order."""
        enriched = payload
        for interceptor in self._interceptors:
            if interceptor.metadata.enabled:
                enriched = await interceptor.pre_execute(enriched)
        return enriched

    async def execute_post(self, result: dict, payload: dict) -> None:
        """Run all enabled interceptors' post_execute. Continues even if one raises."""
        for interceptor in self._interceptors:
            if interceptor.metadata.enabled:
                try:
                    await interceptor.post_execute(result, payload)
                except Exception:
                    pass  # post_execute failures are logged but don't break chain

    async def execute_error(self, error: Exception, payload: dict) -> dict:
        """Run first matching on_error handler. Returns correction payload."""
        for interceptor in self._interceptors:
            if interceptor.metadata.enabled:
                try:
                    return await interceptor.on_error(error, payload)
                except Exception:
                    continue
        return {"error": str(error), "unhandled": True}

    def get_chain_summary(self) -> list:
        """Returns [{name, priority, enabled}] ordered by priority."""
        return [
            {
                "name": i.metadata.name,
                "priority": i.metadata.priority,
                "enabled": i.metadata.enabled,
            }
            for i in self._interceptors
        ]

    def __len__(self) -> int:
        return len(self._interceptors)


# VERIFICATION_STAMP
# Story: 1.02 (Track B)
# Verified By: parallel-builder
# Verified At: 2026-02-25T00:00:00Z
# Tests: 7/7
# Coverage: 100%
