#!/usr/bin/env python3
"""
BULK_WRITE 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 BulkWriteExecutor(AUniversalOperationExecutor):
    """BULK_WRITE - Batch insert/update/delete operations."""
    OPERATION_NAME = "BULK_WRITE"
    OPERATION_TYPE = OperationType.DATA_OPS
    SUPPORTED_NODE_TYPES = []

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

    def _execute_bulk_write(self, node: Any, params: dict, context: ExecutionContext) -> dict:
        operations = params.get("operations", [])
        ordered = bool(params.get("ordered", True))

        data_store = list(extract_items(node))
        summary = {"inserted": 0, "updated": 0, "deleted": 0, "errors": 0}
        results = []

        for op in operations:
            op_type = str(op.get("type", "")).lower()
            op_data = op.get("data", {})
            try:
                if op_type == "insert":
                    data_store.append(op_data)
                    summary["inserted"] += 1
                    results.append({"type": op_type, "success": True})
                elif op_type == "update":
                    filter_spec = op_data.get("filter", {})
                    update_values = op_data.get("values", {})
                    updated_here = 0
                    for item in data_store:
                        if isinstance(item, dict) and all(item.get(k) == v for k, v in filter_spec.items()):
                            item.update(update_values)
                            updated_here += 1
                    summary["updated"] += updated_here
                    results.append({"type": op_type, "success": True, "updated": updated_here})
                elif op_type == "delete":
                    filter_spec = op_data.get("filter", {})
                    before = len(data_store)
                    data_store = [
                        item
                        for item in data_store
                        if not (isinstance(item, dict) and all(item.get(k) == v for k, v in filter_spec.items()))
                    ]
                    deleted_here = before - len(data_store)
                    summary["deleted"] += deleted_here
                    results.append({"type": op_type, "success": True, "deleted": deleted_here})
                else:
                    raise ValueError(f"Unsupported operation type: {op_type}")
            except Exception as exc:
                summary["errors"] += 1
                results.append({"type": op_type, "success": False, "error": str(exc)})
                if ordered:
                    break

        return {
            "items": data_store,
            "count": len(data_store),
            "ordered": ordered,
            "summary": summary,
            "results": results,
        }
