from typing import Any, Callable, List, Dict, Optional
from swarmauri_core.chains.ICallableChain import ICallableChain, CallableDefinition


class CallableChain(ICallableChain):
    def __init__(self, callables: Optional[List[CallableDefinition]] = None):
        self.callables = callables if callables is not None else []

    def __call__(self, *initial_args, **initial_kwargs):
        result = None
        for func, args, kwargs in self.callables:
            if result is not None:
                # If there was a previous result, use it as the first argument for the next function
                args = [result] + list(args)
            result = func(*args, **kwargs)
        return result

    def add_callable(
        self,
        func: Callable[[Any], Any],
        args: List[Any] = None,
        kwargs: Dict[str, Any] = None,
    ) -> None:
        # Add a new callable to the chain
        self.callables.append((func, args or [], kwargs or {}))

    def __or__(self, other: "CallableChain") -> "CallableChain":
        if not isinstance(other, CallableChain):
            raise TypeError("Operand must be an instance of CallableChain")

        new_chain = CallableChain(self.callables + other.callables)
        return new_chain
