"""
BloomOS Kernel - Routing Handlers
=================================

Syscall handlers for tensor routing operations.

Syscalls:
- routing.route_tensor.v1: Route tensor to optimal backend (CPU/GPU/QPU)
"""

from __future__ import annotations

import hashlib
from typing import Any, Dict, TYPE_CHECKING

import numpy as np

if TYPE_CHECKING:
    from ..syscall_registry import SyscallRegistry


def routing_route_tensor_v1(inputs: Dict[str, Any]) -> Dict[str, Any]:
    """
    Route tensor to optimal backend based on Symbolic Entropy (Se).

    Wraps flowtorch/router.py SymbolicEntropyRouter

    Args (inputs dict):
        tensor_data: Tensor as list or numpy array
        state: Optional state dict for context
        queue_depth: Optional queue depth (default: 0)
        deadline_ms: Optional deadline pressure

    Returns:
        {
            "status": "OK" | "FAIL",
            "backend": "cpu" | "gpu" | "qpu",
            "Se": float,
            "C_struct": float,
            "routing_zone": int,
            "router_info": dict,
        }
    """
    tensor_data = inputs.get("tensor_data")
    state = inputs.get("state", {})
    queue_depth = inputs.get("queue_depth", 0)
    deadline_ms = inputs.get("deadline_ms")

    if tensor_data is None:
        return {
            "status": "FAIL",
            "error": "Missing required input: tensor_data",
        }

    # Import router
    try:
        from flowtorch.router import SymbolicEntropyRouter
        from flowtorch.braid import BraidedTensor
    except ImportError as e:
        return {
            "status": "FAIL",
            "error": f"Failed to import flowtorch: {e}",
        }

    # Convert to numpy if needed
    if isinstance(tensor_data, list):
        tensor = np.array(tensor_data, dtype=np.float32)
    else:
        tensor = np.asarray(tensor_data, dtype=np.float32)

    # Create braided tensor for router (framework="numpy" for numpy arrays)
    braided = BraidedTensor(tensor, original_framework="numpy")

    # Initialize router
    router = SymbolicEntropyRouter(use_qubo_router=False)

    # Route
    try:
        backend, se_norm = router.route_task(
            braided,
            state=state,
            queue_depth=queue_depth,
            deadline_ms=deadline_ms,
        )

        # Get diagnostics
        last_se = router.get_last_se_result() or {}

        return {
            "status": "OK",
            "backend": backend,
            "Se": se_norm,
            "C_struct": last_se.get("C_struct", 0.0),
            "routing_zone": last_se.get("routing_zone", 2),
            "router_info": router.info(),
        }

    except Exception as e:
        return {
            "status": "FAIL",
            "error": str(e),
        }


def routing_route_tensor_v1_cost_estimator(inputs: Dict[str, Any]) -> float:
    """
    Estimate IT cost for routing.route_tensor.v1.

    Cost model:
    - Base cost: 0.1 IT (routing is cheap)
    - Per MB: 0.01 IT (for Se calculation)

    Args:
        inputs: Syscall inputs

    Returns:
        Estimated IT tokens
    """
    base_cost = 0.1
    per_mb_cost = 0.01

    tensor_data = inputs.get("tensor_data")
    if tensor_data is None:
        return base_cost

    try:
        if isinstance(tensor_data, list):
            import sys
            size_estimate = sys.getsizeof(tensor_data)
        else:
            size_estimate = np.asarray(tensor_data).nbytes

        mb = size_estimate / (1024 * 1024)
        return base_cost + (mb * per_mb_cost)
    except Exception:
        return base_cost


# Schema definitions
ROUTING_ROUTE_TENSOR_V1_SCHEMA = {
    "required": ["tensor_data"],
    "types": {
        "tensor_data": "list",
        "state": "dict",
        "queue_depth": "int",
        "deadline_ms": "float",
    },
}


def register_routing_handlers(registry: "SyscallRegistry") -> None:
    """Register routing handlers with the registry."""
    registry.register(
        canonical_name="routing.route_tensor.v1",
        handler=routing_route_tensor_v1,
        schema=ROUTING_ROUTE_TENSOR_V1_SCHEMA,
        cost_estimator=routing_route_tensor_v1_cost_estimator,
        description="Route tensor to optimal backend (CPU/GPU/QPU) based on Se",
    )
