"""
Frame Capture Stage Adapter

Wraps pipeline stages to capture frames for animation report generation.
"""

from typing import Any

from engine.display.backends.animation_report import AnimationReportDisplay
from engine.pipeline.core import PipelineContext, Stage


class FrameCaptureStage(Stage):
    """
    Wrapper stage that captures frames before and after a wrapped stage.

    This allows generating animation reports showing how each stage
    transforms the data.
    """

    def __init__(
        self,
        wrapped_stage: Stage,
        display: AnimationReportDisplay,
        name: str | None = None,
    ):
        """
        Initialize frame capture stage.

        Args:
            wrapped_stage: The stage to wrap and capture frames from
            display: The animation report display to send frames to
            name: Optional name for this capture stage
        """
        self._wrapped_stage = wrapped_stage
        self._display = display
        self.name = name or f"capture_{wrapped_stage.name}"
        self.category = wrapped_stage.category
        self.optional = wrapped_stage.optional

        # Capture state
        self._captured_input = False
        self._captured_output = False

    @property
    def stage_type(self) -> str:
        return self._wrapped_stage.stage_type

    @property
    def capabilities(self) -> set[str]:
        return self._wrapped_stage.capabilities

    @property
    def dependencies(self) -> set[str]:
        return self._wrapped_stage.dependencies

    @property
    def inlet_types(self) -> set:
        return self._wrapped_stage.inlet_types

    @property
    def outlet_types(self) -> set:
        return self._wrapped_stage.outlet_types

    def init(self, ctx: PipelineContext) -> bool:
        """Initialize the wrapped stage."""
        return self._wrapped_stage.init(ctx)

    def process(self, data: Any, ctx: PipelineContext) -> Any:
        """
        Process data through wrapped stage and capture frames.

        Args:
            data: Input data (typically a text buffer)
            ctx: Pipeline context

        Returns:
            Output data from wrapped stage
        """
        # Capture input frame (before stage processing)
        if isinstance(data, list) and all(isinstance(line, str) for line in data):
            self._display.start_stage(f"{self._wrapped_stage.name}_input")
            self._display.show(data)
            self._captured_input = True

        # Process through wrapped stage
        result = self._wrapped_stage.process(data, ctx)

        # Capture output frame (after stage processing)
        if isinstance(result, list) and all(isinstance(line, str) for line in result):
            self._display.start_stage(f"{self._wrapped_stage.name}_output")
            self._display.show(result)
            self._captured_output = True

        return result

    def cleanup(self) -> None:
        """Cleanup the wrapped stage."""
        self._wrapped_stage.cleanup()


class FrameCaptureController:
    """
    Controller for managing frame capture across the pipeline.

    This class provides an easy way to enable frame capture for
    specific stages or the entire pipeline.
    """

    def __init__(self, display: AnimationReportDisplay):
        """
        Initialize frame capture controller.

        Args:
            display: The animation report display to use for capture
        """
        self._display = display
        self._captured_stages: list[FrameCaptureStage] = []

    def wrap_stage(self, stage: Stage, name: str | None = None) -> FrameCaptureStage:
        """
        Wrap a stage with frame capture.

        Args:
            stage: The stage to wrap
            name: Optional name for the capture stage

        Returns:
            Wrapped stage that captures frames
        """
        capture_stage = FrameCaptureStage(stage, self._display, name)
        self._captured_stages.append(capture_stage)
        return capture_stage

    def wrap_stages(self, stages: dict[str, Stage]) -> dict[str, Stage]:
        """
        Wrap multiple stages with frame capture.

        Args:
            stages: Dictionary of stage names to stages

        Returns:
            Dictionary of stage names to wrapped stages
        """
        wrapped = {}
        for name, stage in stages.items():
            wrapped[name] = self.wrap_stage(stage, name)
        return wrapped

    def get_captured_stages(self) -> list[FrameCaptureStage]:
        """Get list of all captured stages."""
        return self._captured_stages

    def generate_report(self, title: str = "Pipeline Animation Report") -> str:
        """
        Generate the animation report.

        Args:
            title: Title for the report

        Returns:
            Path to the generated HTML file
        """
        report_path = self._display.generate_report(title)
        return str(report_path)
