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

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 ChooseExecutor(AUniversalOperationExecutor):
    """CHOOSE - Conditional graph branch routing."""
    OPERATION_NAME = "CHOOSE"
    OPERATION_TYPE = OperationType.GRAPH
    SUPPORTED_NODE_TYPES = []

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

    def _evaluate(self, item: Any, condition: Any) -> bool:
        if condition is None:
            return False
        if callable(condition):
            try:
                return bool(condition(item))
            except Exception:
                return False
        if isinstance(condition, dict):
            return all(extract_field_value(item, key) == value for key, value in condition.items())
        if isinstance(condition, str):
            return bool(extract_field_value(item, condition))
        return bool(condition)

    def _execute_choose(self, node: Any, params: dict, context: ExecutionContext) -> dict:
        items = extract_items(node)
        condition = params.get("condition")
        true_branch = params.get("true_branch", "true")
        false_branch = params.get("false_branch", "false")

        output = []
        true_count = 0
        false_count = 0
        for item in items:
            record = dict(item) if isinstance(item, dict) else {"value": item}
            is_true = self._evaluate(item, condition)
            record["_branch"] = true_branch if is_true else false_branch
            output.append(record)
            if is_true:
                true_count += 1
            else:
                false_count += 1

        return {
            "items": output,
            "count": len(output),
            "true_count": true_count,
            "false_count": false_count,
        }
