"""Digital Employee Pipeline Builder.

This module provides the DigitalEmployeePipelineBuilder class for creating
Pipeline instances with steps for DigitalEmployee.

Authors:
    Immanuel Rhesa (immanuel.rhesa@gdplabs.id)

References:
    NONE
"""

from dataclasses import dataclass, field
from typing import Self

from gllm_pipeline.pipeline.pipeline import Pipeline
from gllm_pipeline.steps import ComponentStep

from digital_employee_core.digital_employee.builders.step_builder import StepBuilder
from digital_employee_core.digital_employee.config import DigitalEmployeeConfig
from digital_employee_core.digital_employee.core import DigitalEmployeeState
from digital_employee_core.identity.identity import DigitalEmployeeIdentity


@dataclass
class DigitalEmployeePipelineBuilder:
    """Builder for creating Pipeline with steps for DigitalEmployee.

    This builder allows adding steps that can be built from various builders
    (e.g., DigitalEmployeeAgentBuilder, GuardrailsBuilder) or directly from ComponentStep.

    Attributes:
        _step_items (list[ComponentStep | StepBuilder]): Ordered list of steps and
            step builders, maintaining insertion order.

    Example:
        pipeline = (
            DigitalEmployeePipelineBuilder()
            .add_step(GuardrailsBuilder())
            .add_step(DigitalEmployeeAgentBuilder().mcps(["google"]))
            .build(identity, configurations)
        )
    """

    _step_items: list[ComponentStep | StepBuilder] = field(default_factory=list, init=False)

    def add_step(self, step_input: ComponentStep | StepBuilder) -> Self:
        """Add a step to the pipeline.

        Args:
            step_input (ComponentStep | StepBuilder): A ComponentStep or a StepBuilder instance.

        Returns:
            Self: The builder instance for chaining.
        """
        self._step_items.append(step_input)
        return self

    def build(
        self,
        identity: DigitalEmployeeIdentity,
        configs: list[DigitalEmployeeConfig],
        state_type: type = DigitalEmployeeState,
    ) -> Pipeline:
        """Build the Pipeline instance with identity propagation to step builders.

        This method builds all step builders by passing identity and configurations
        via kwargs, allowing builders like DigitalEmployeeAgentBuilder to create
        their steps with the required context. Steps maintain their insertion order.

        Args:
            identity (DigitalEmployeeIdentity): The identity to propagate to step builders.
            configs (list[DigitalEmployeeConfig]): The configurations to propagate.
            state_type (type, optional): The state type for the pipeline.
                Defaults to DigitalEmployeeState.

        Returns:
            Pipeline: The built pipeline instance with all steps in insertion order.
        """
        steps = []

        for item in self._step_items:
            if isinstance(item, ComponentStep):
                steps.append(item)
            elif isinstance(item, StepBuilder):
                step = item.build_step(identity=identity, configs=configs)
                steps.append(step)

        return Pipeline(steps=steps, state_type=state_type)

    def get_steps(self) -> list[ComponentStep]:
        """Get the list of pre-built ComponentStep items without building the pipeline.

        Note: This does not include steps from step builders.

        Returns:
            list[ComponentStep]: The list of ComponentStep items.
        """
        return [item for item in self._step_items if isinstance(item, ComponentStep)]
