#!/usr/bin/env python3
"""
ARRAY_SORT 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 ArraySortExecutor(AUniversalOperationExecutor):
    """ARRAY_SORT - Sort an array field using Python sorted()."""
    OPERATION_NAME = "ARRAY_SORT"
    OPERATION_TYPE = OperationType.ARRAY
    SUPPORTED_NODE_TYPES = []

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

    def _execute_op(self, node: Any, params: dict, context: ExecutionContext) -> dict:
        field: Optional[str] = params.get("field")
        reverse: bool = bool(params.get("reverse", False))
        key_field: Optional[str] = params.get("key")
        as_field: str = params.get("as_field", field or "_array_sorted")
        items = extract_items(node)

        result_items = []
        for item in items:
            item_copy = item.copy() if isinstance(item, dict) else {"value": item}
            array_value = extract_field_value(item, field) if field else None
            if isinstance(array_value, list):
                item_copy[as_field] = self._sort_array(array_value, reverse, key_field)
            else:
                item_copy[as_field] = []
            result_items.append(item_copy)

        return {
            "items": result_items,
            "count": len(result_items),
            "total_items": len(items),
            "field": field,
            "reverse": reverse,
            "key": key_field,
            "as_field": as_field,
        }

    def _sort_array(self, values: list[Any], reverse: bool, key_field: Optional[str]) -> list[Any]:
        key_func = (lambda entry: extract_field_value(entry, key_field)) if key_field else (lambda entry: entry)
        try:
            return sorted(values, key=key_func, reverse=reverse)
        except TypeError:
            return sorted(values, key=lambda entry: str(key_func(entry)), reverse=reverse)


__all__ = ["ArraySortExecutor"]
