"""Node operations tool -- batch node editing with undo/redo support."""

from __future__ import annotations

from godotiq.bridge.session import get_bridge
from godotiq.tools.bridge.spatial_validator import validate_move, validate_scale

MAX_OPERATIONS = 50


async def node_ops(operations: list[dict], scene_data: dict | None = None) -> dict:
    """Execute batch node operations with optional spatial validation.

    When scene_data is provided and an operation has validate:true,
    the operation is checked against scene spatial context before execution.

    Each operation is a dict with an 'op' key and operation-specific params.
    All operations are grouped as a single undo action in the editor.

    Supported operations:
        move, rotate, scale, set_property, add_child, delete, duplicate, reparent

    Args:
        operations: List of operation dicts. Must be non-empty and at most 50 items.
        scene_data: Optional scene spatial data for validation. When None, validation
            is skipped even if operations have validate:true.

    Returns:
        Dict with 'results' list containing per-operation status dicts.
        If validation blocks, returns dict with 'status': 'BLOCKED' instead.

    Raises:
        ValueError: If operations list is empty or exceeds the 50-operation limit.
    """
    if not operations:
        raise ValueError("No operations provided; at least one operation is required.")
    if len(operations) > MAX_OPERATIONS:
        raise ValueError(
            f"Too many operations ({len(operations)}); limit is {MAX_OPERATIONS} per call."
        )

    # Validation
    validations: list[dict] = []
    has_validate = scene_data is not None and any(op.get("validate") for op in operations)

    if has_validate:
        for op in operations:
            if not op.get("validate"):
                continue
            result = None
            op_type = op.get("op")
            if op_type == "move" and "position" in op:
                result = validate_move(op["position"], op.get("node", ""), scene_data)
            elif op_type == "scale" and "scale" in op:
                result = validate_scale(op["scale"], op.get("node", ""), scene_data)
            elif op_type == "add_child" and "position" in op:
                result = validate_move(op["position"], op.get("node", op.get("name", "")), scene_data)
            if result is not None:
                validations.append(result)

        blocked_count = sum(1 for v in validations if v.get("severity") == "BLOCKED")
        if blocked_count > 0:
            return {
                "status": "BLOCKED",
                "validation": validations,
                "message": "One or more operations blocked by spatial validation. No changes made.",
                "operations_blocked": blocked_count,
            }

    bridge = await get_bridge()
    result = await bridge.request("node_ops", params={"operations": operations})

    if validations:
        result["validation"] = validations

    return result
