#!/usr/bin/env python3
"""
COALESCE_STEP Executor
Company: eXonware.com
Author: eXonware Backend Team
Email: connect@exonware.com
Version: 0.0.1.8
"""

from typing import Any, Optional
from ..base import AUniversalOperationExecutor
from ....contracts import QueryAction, ExecutionContext, ExecutionResult
from ....defs import OperationType
from ..utils import extract_items, extract_field_value


class CoalesceStepExecutor(AUniversalOperationExecutor):
    """COALESCE_STEP - Return first successful traversal alternative."""
    OPERATION_NAME = "COALESCE_STEP"
    OPERATION_TYPE = OperationType.GRAPH
    SUPPORTED_NODE_TYPES = []

    def _do_execute(self, action: QueryAction, context: ExecutionContext) -> ExecutionResult:
        params = action.params
        result_data = self._execute_coalesce_step(context.node, params, context)
        return ExecutionResult(
            success=True,
            data=result_data,
            action_type=self.OPERATION_NAME,
            metadata={"operation": self.OPERATION_NAME},
        )

    def _normalize_action(self, candidate: Any) -> Optional[QueryAction]:
        if isinstance(candidate, QueryAction):
            return candidate
        if isinstance(candidate, dict):
            action_type = candidate.get("type", candidate.get("operation"))
            if action_type:
                return QueryAction(type=action_type, params=candidate.get("params", {}))
        if isinstance(candidate, str):
            return QueryAction(type=candidate, params={})
        return None

    def _execute_coalesce_step(self, node: Any, params: dict, context: ExecutionContext) -> dict:
        alternatives = params.get("alternatives", [])
        engine = context.metadata.get("engine") if isinstance(context.metadata, dict) else None

        for index, alternative in enumerate(alternatives):
            alt_action = self._normalize_action(alternative)
            if alt_action is None:
                continue
            if engine is None:
                continue
            alt_context = ExecutionContext(
                node=node,
                variables=dict(context.variables),
                options=dict(context.options),
                parent_context=context,
                metadata=dict(context.metadata),
                engine_type=context.engine_type,
            )
            alt_result = engine.execute_tree(alt_action, alt_context)
            alt_items = extract_items(alt_result.data) if alt_result.success else []
            if alt_result.success and alt_items:
                return {
                    "items": alt_items,
                    "count": len(alt_items),
                    "selected_alternative": index,
                }

        return {"items": [], "count": 0, "selected_alternative": None}
