#!/usr/bin/env python3
"""
CONTAINS 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 ContainsExecutor(AUniversalOperationExecutor):
    """Filter items where a field contains a substring. O(n)."""

    OPERATION_NAME = "CONTAINS"
    OPERATION_TYPE = OperationType.FILTERING
    SUPPORTED_NODE_TYPES = []

    def _do_execute(self, action: QueryAction, context: ExecutionContext) -> ExecutionResult:
        params = action.params
        field = params.get("field")
        value = params.get("value")
        case_sensitive = params.get("case_sensitive", True)
        path = params.get("path", None)

        if not field:
            return ExecutionResult(
                success=False,
                data=None,
                error=f"CONTAINS requires 'field'. Got: {action.params}",
                action_type=self.OPERATION_NAME,
            )

        if value is None:
            return ExecutionResult(
                success=False,
                data=None,
                error=f"CONTAINS requires 'value'. Got: {action.params}",
                action_type=self.OPERATION_NAME,
            )

        result_data = self._execute_contains(context.node, field, value, case_sensitive, path)
        return ExecutionResult(
            success=True,
            data=result_data,
            action_type=self.OPERATION_NAME,
            metadata={"matched_count": len(result_data.get("items", []))},
        )

    def _execute_contains(
        self,
        node: Any,
        field: str,
        value: Any,
        case_sensitive: bool,
        path: Optional[str],
    ) -> dict:
        if path:
            try:
                data = node.get(path, default=None)
            except Exception:
                data = None
        else:
            data = node

        items = extract_items(data)
        needle = str(value)
        if not case_sensitive:
            needle = needle.lower()

        matched_items = []
        for item in items:
            field_value = extract_field_value(item, field)
            if field_value is None:
                continue
            haystack = str(field_value)
            if not case_sensitive:
                haystack = haystack.lower()
            if needle in haystack:
                matched_items.append(item)

        return {
            "items": matched_items,
            "count": len(matched_items),
            "total_items": len(items),
            "field": field,
            "value": value,
            "case_sensitive": bool(case_sensitive),
        }


__all__ = ["ContainsExecutor"]
