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

"""Tests for auto-wrapping plain RoutingClass in OpenApiApplication."""

from genro_routes import RoutingClass, Router, route  # type: ignore[import-untyped]

from genro_asgi.applications import AsgiApplication, OpenApiApplication
from genro_asgi.server.server import AsgiServer


class SampleRoutingClass(RoutingClass):
    """Plain RoutingClass for testing — NOT an AsgiApplication."""

    def __init__(self, custom_param: str = "default") -> None:
        self.custom_param = custom_param
        self.api = Router(self, name="api")

    @route()
    def hello(self) -> str:
        return "hello"


class SampleApp(AsgiApplication):
    """AsgiApplication subclass for testing — should NOT be wrapped."""

    def on_init(self, **kwargs: object) -> None:
        pass


class TestMaybeWrap:
    """Test AsgiServer._maybe_wrap detection and wrapping logic."""

    def _call(self, cls: type, kwargs: dict) -> tuple[type, dict]:
        """Call _maybe_wrap as unbound, bypassing server init."""
        return AsgiServer._maybe_wrap(None, cls, kwargs)  # type: ignore[arg-type]

    def test_asgi_application_passthrough(self) -> None:
        """AsgiApplication subclass is returned unchanged."""
        kwargs = {"docs": "swagger", "db_name": "default"}
        result_cls, result_kwargs = self._call(SampleApp, kwargs)
        assert result_cls is SampleApp
        assert result_kwargs is kwargs

    def test_plain_routing_class_wrapped(self) -> None:
        """Plain RoutingClass is wrapped in OpenApiApplication."""
        kwargs = {"docs": "swagger", "custom_param": "test_value"}
        result_cls, result_kwargs = self._call(SampleRoutingClass, kwargs)
        assert result_cls is OpenApiApplication
        assert result_kwargs["docs"] == "swagger"
        assert isinstance(result_kwargs["routing_class"], SampleRoutingClass)
        assert result_kwargs["routing_class"].custom_param == "test_value"

    def test_plain_routing_class_default_docs(self) -> None:
        """Plain RoutingClass without docs gets docs='off'."""
        kwargs = {"custom_param": "value"}
        result_cls, result_kwargs = self._call(SampleRoutingClass, kwargs)
        assert result_cls is OpenApiApplication
        assert result_kwargs["docs"] == "off"

    def test_kwargs_split_base_dir(self) -> None:
        """base_dir goes to wrapper, not to inner RoutingClass."""
        kwargs = {"base_dir": "/some/path", "custom_param": "val"}
        result_cls, result_kwargs = self._call(SampleRoutingClass, kwargs)
        assert result_kwargs["base_dir"] == "/some/path"
        assert result_kwargs["routing_class"].custom_param == "val"

    def test_kwargs_split_db_name(self) -> None:
        """db_name goes to wrapper, not to inner RoutingClass."""
        kwargs = {"db_name": "mydb", "custom_param": "val"}
        result_cls, result_kwargs = self._call(SampleRoutingClass, kwargs)
        assert result_kwargs["db_name"] == "mydb"
        assert result_kwargs["routing_class"].custom_param == "val"

    def test_non_routing_class_passthrough(self) -> None:
        """A class that is neither AsgiApplication nor RoutingClass passes through."""

        class PlainClass:
            pass

        kwargs = {"docs": "swagger"}
        result_cls, result_kwargs = self._call(PlainClass, kwargs)
        assert result_cls is PlainClass
        assert result_kwargs is kwargs

    def test_wrapper_kwargs_absent_when_none(self) -> None:
        """base_dir and db_name are omitted from wrapper kwargs when not in input."""
        kwargs = {"docs": "swagger"}
        _, result_kwargs = self._call(SampleRoutingClass, kwargs)
        assert "base_dir" not in result_kwargs
        assert "db_name" not in result_kwargs
