# Copyright 2025 Softwell S.r.l.
# Licensed under the Apache License, Version 2.0

"""HandlerExecutor — ASGI app that executes a pre-resolved router node.

Used as innermost app in per-app middleware chains. The Dispatcher sets
scope["_handler_node"] before invoking the per-app chain.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from genro_routes import is_result_wrapper
from genro_toolbox.smartasync import smartasync

if TYPE_CHECKING:
    from .server import AsgiServer
    from ..types import Receive, Scope, Send

__all__ = ["HandlerExecutor"]


class HandlerExecutor:
    """ASGI app that executes a pre-resolved router node.

    Expects scope["_handler_node"] set by Dispatcher before invocation.
    Retrieves the current request from server.request_registry.
    """

    __slots__ = ("server",)

    def __init__(self, server: AsgiServer) -> None:
        """Args:
            server: Parent AsgiServer instance (provides request_registry).
        """
        self.server = server

    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
        """Execute pre-resolved handler node and send ASGI response.

        Args:
            scope: ASGI scope with "_handler_node" set by Dispatcher.
            receive: ASGI receive callable.
            send: ASGI send callable.
        """
        node = scope["_handler_node"]
        request = self.server.request_registry.current
        assert request is not None
        result = await smartasync(node)(**dict(request.query))
        if is_result_wrapper(result):
            metadata: dict[str, Any] = {**node.metadata, **result.metadata}
            request.response.set_result(result.value, metadata)
        else:
            request.response.set_result(result, node.metadata)
        await request.response(scope, receive, send)


if __name__ == "__main__":
    pass
