"""Tests for route_registry functions and data structure."""

from local_deep_research.web.routes.route_registry import (
    ROUTE_REGISTRY,
    find_route,
    get_all_routes,
    get_routes_by_blueprint,
)


class TestGetAllRoutes:
    """Tests for get_all_routes()."""

    def test_returns_list(self):
        result = get_all_routes()
        assert isinstance(result, list)

    def test_each_item_has_required_keys(self):
        required_keys = {
            "method",
            "path",
            "endpoint",
            "description",
            "blueprint",
        }
        for route in get_all_routes():
            assert required_keys <= route.keys(), (
                f"Route missing keys: {required_keys - route.keys()}"
            )

    def test_prefixed_routes_have_prefix_prepended(self):
        """Routes from blueprints with a url_prefix get that prefix in the path."""
        routes = get_all_routes()
        settings_routes = [r for r in routes if r["blueprint"] == "settings"]
        assert settings_routes, "Expected settings routes"
        for route in settings_routes:
            assert route["path"].startswith("/settings"), route["path"]

    def test_no_prefix_routes_have_no_prefix(self):
        """Routes with url_prefix=None keep their original path."""
        routes = get_all_routes()
        research_routes = [r for r in routes if r["blueprint"] == "research"]
        assert research_routes, "Expected research routes"
        # The research blueprint has url_prefix=None, so paths should not
        # be double-prefixed — they start with "/" directly.
        for route in research_routes:
            assert not route["path"].startswith("None"), route["path"]

    def test_contains_routes_from_all_blueprints(self):
        routes = get_all_routes()
        blueprints_in_routes = {r["blueprint"] for r in routes}
        assert blueprints_in_routes == set(ROUTE_REGISTRY.keys())


class TestGetRoutesByBlueprint:
    """Tests for get_routes_by_blueprint()."""

    def test_known_blueprint_returns_routes(self):
        result = get_routes_by_blueprint("settings")
        assert len(result) > 0

    def test_unknown_blueprint_returns_empty_list(self):
        result = get_routes_by_blueprint("nonexistent_blueprint_xyz")
        assert result == []

    def test_routes_have_required_keys(self):
        required_keys = {"method", "path", "endpoint", "description"}
        for route in get_routes_by_blueprint("settings"):
            assert required_keys <= route.keys()

    def test_settings_routes_have_settings_prefix(self):
        routes = get_routes_by_blueprint("settings")
        for route in routes:
            assert route["path"].startswith("/settings"), route["path"]

    def test_research_routes_have_no_prefix(self):
        """research blueprint has url_prefix=None so paths are root-level."""
        routes = get_routes_by_blueprint("research")
        assert routes, "Expected research routes"
        # First route is "/" — just confirm no double prefix
        assert routes[0]["path"] == "/"


class TestFindRoute:
    """Tests for find_route()."""

    def test_case_insensitive_match(self):
        lower = find_route("api")
        upper = find_route("API")
        assert len(lower) == len(upper)
        assert len(lower) > 0

    def test_api_finds_multiple_routes(self):
        results = find_route("api")
        assert len(results) > 1

    def test_nonexistent_pattern_returns_empty(self):
        results = find_route("nonexistent_xyz")
        assert results == []

    def test_settings_pattern_finds_settings_routes(self):
        results = find_route("settings")
        assert len(results) > 0
        for route in results:
            assert "settings" in route["path"].lower()

    def test_empty_string_matches_all(self):
        all_routes = get_all_routes()
        results = find_route("")
        assert len(results) == len(all_routes)


class TestRouteRegistryDataStructure:
    """Tests for the ROUTE_REGISTRY dict itself."""

    def test_is_dict(self):
        assert isinstance(ROUTE_REGISTRY, dict)

    def test_contains_expected_blueprints(self):
        for key in ("research", "settings", "history", "metrics"):
            assert key in ROUTE_REGISTRY, f"Missing blueprint: {key}"

    def test_each_value_has_required_keys(self):
        required = {"blueprint", "url_prefix", "routes"}
        for name, info in ROUTE_REGISTRY.items():
            assert required <= info.keys(), (
                f"Blueprint '{name}' missing: {required - info.keys()}"
            )

    def test_each_route_tuple_has_four_elements(self):
        for name, info in ROUTE_REGISTRY.items():
            for route in info["routes"]:
                assert len(route) == 4, (
                    f"Blueprint '{name}' route {route} has {len(route)} elements"
                )
