"""
Lambda Calculus runtime executor.

Executes λ-calculus operations (α-β-η conversions) on MCard-stored terms.
"""

from typing import Any

from mcard import MCard

from .base import RuntimeExecutor


class LambdaRuntimeExecutor(RuntimeExecutor):
    """Lambda Calculus runtime executor.

    Executes λ-calculus operations (α-β-η conversions) on MCard-stored terms.
    """

    def __init__(self, collection=None):
        super().__init__()
        self.collection = collection
        self._lambda_runtime = None

    def _get_runtime(self):
        """Lazy initialization of LambdaRuntime."""
        if self._lambda_runtime is None:
            from mcard.model.card_collection import CardCollection
            from mcard.ptr.lambda_calc import LambdaRuntime

            if self.collection is None:
                self.collection = CardCollection(db_path=":memory:")
            self._lambda_runtime = LambdaRuntime(self.collection)
        return self._lambda_runtime

    def execute(self, impl: dict[str, Any], target: MCard, ctx: dict[str, Any]) -> Any:
        """Execute Lambda Calculus operation."""
        runtime = self._get_runtime()

        # Build context from concrete implementation and context
        # Prioritize ctx override, then 'process', then 'action', then 'operation'
        operation = ctx.get('operation',
                           impl.get('process',
                                   impl.get('action',
                                           impl.get('operation', 'normalize'))))
        strategy = ctx.get('strategy', impl.get('strategy', 'normal'))
        max_steps = ctx.get('max_steps', ctx.get('maxSteps', impl.get('max_steps', impl.get('maxSteps', 100))))

        # Get expression from context or target
        expression = ctx.get('expression')
        if not expression:
            # Try to get from balanced input arguments
            balanced = ctx.get('balanced', {})
            input_args = balanced.get('input_arguments', {})
            expression = input_args.get('expression') or input_args.get('numeral')

        if not expression or expression == 'dummy_target':
            # Check if target content looks like a Lambda expression
            target_content = target.get_content().decode('utf-8', errors='ignore')
            if target_content and ('λ' in target_content or '\\' in target_content):
                expression = target_content
            elif operation in ('check-readiness', 'num-add', 'num-sub', 'num-mul', 'num-div', 'http-request'):
                expression = 'builtin' # Placeholder
            else:
                return "Error: No Lambda expression provided"

        # Execute through LambdaRuntime
        # Create a full context by merging ctx and any other needed fields
        full_ctx = ctx.copy()
        full_ctx['expression'] = expression

        # Get io_effects from context (override) or concrete implementation config
        io_effects = impl.get('io_effects', {}).copy()
        if isinstance(ctx.get('io_effects'), dict):
            io_effects.update(ctx.get('io_effects'))

        result = runtime.execute(
            expression,
            full_ctx,
            {
                'operation': operation,
                'strategy': strategy,
                'max_steps': max_steps,
                'io_effects': io_effects
            },
            ''
        )

        if result.success:
            # Return appropriate result based on operation
            if result.pretty_print:
                return result.pretty_print
            elif result.is_closed is not None:
                return result.is_closed
            elif result.free_variables is not None:
                return result.free_variables
            else:
                return result.term_hash
        else:
            return f"Error: {result.error}"

    def validate_environment(self) -> bool:
        """Lambda runtime is always available (pure Python)."""
        return True

    def get_runtime_status(self) -> dict[str, Any]:
        return {
            'available': True,
            'version': '1.0.0',
            'command': 'lambda',
            'details': 'Lambda Calculus α-β-η converter'
        }
