"""
Extended tests for route_registry - Central documentation of all application routes.

Tests cover:
- Route registry structure
- get_all_routes() function
- get_routes_by_blueprint() function
- find_route() function
- Route data validation
- Blueprint configuration
"""


class TestRouteRegistryStructure:
    """Tests for ROUTE_REGISTRY structure."""

    def test_registry_contains_research_blueprint(self):
        """Registry should contain research blueprint."""
        registry = {
            "research": {
                "blueprint": "research_bp",
                "url_prefix": None,
                "routes": [],
            }
        }
        assert "research" in registry

    def test_registry_contains_api_v1_blueprint(self):
        """Registry should contain api_v1 blueprint."""
        registry = {
            "api_v1": {
                "blueprint": "api_blueprint",
                "url_prefix": "/api/v1",
                "routes": [],
            }
        }
        assert "api_v1" in registry

    def test_registry_contains_history_blueprint(self):
        """Registry should contain history blueprint."""
        registry = {
            "history": {
                "blueprint": "history_bp",
                "url_prefix": "/history",
                "routes": [],
            }
        }
        assert "history" in registry

    def test_registry_contains_settings_blueprint(self):
        """Registry should contain settings blueprint."""
        registry = {
            "settings": {
                "blueprint": "settings_bp",
                "url_prefix": "/settings",
                "routes": [],
            }
        }
        assert "settings" in registry

    def test_registry_contains_metrics_blueprint(self):
        """Registry should contain metrics blueprint."""
        registry = {
            "metrics": {
                "blueprint": "metrics_bp",
                "url_prefix": "/metrics",
                "routes": [],
            }
        }
        assert "metrics" in registry

    def test_blueprint_info_has_required_keys(self):
        """Blueprint info should have required keys."""
        blueprint_info = {
            "blueprint": "test_bp",
            "url_prefix": "/test",
            "routes": [],
        }

        assert "blueprint" in blueprint_info
        assert "url_prefix" in blueprint_info
        assert "routes" in blueprint_info

    def test_route_tuple_structure(self):
        """Route tuple should have 4 elements."""
        route = ("GET", "/", "index", "Home page")

        assert len(route) == 4
        assert route[0] == "GET"
        assert route[1] == "/"
        assert route[2] == "index"
        assert route[3] == "Home page"


class TestGetAllRoutes:
    """Tests for get_all_routes function."""

    def test_returns_list(self):
        """get_all_routes should return a list."""
        all_routes = []
        assert isinstance(all_routes, list)

    def test_route_dict_has_method(self):
        """Route dict should have method key."""
        route = {
            "method": "GET",
            "path": "/",
            "endpoint": "research.index",
            "description": "Home page",
            "blueprint": "research",
        }
        assert "method" in route
        assert route["method"] == "GET"

    def test_route_dict_has_path(self):
        """Route dict should have path key."""
        route = {
            "method": "GET",
            "path": "/api/history",
            "endpoint": "research.get_history",
            "description": "Get history",
            "blueprint": "research",
        }
        assert "path" in route
        assert route["path"] == "/api/history"

    def test_route_dict_has_endpoint(self):
        """Route dict should have endpoint key."""
        route = {
            "method": "POST",
            "path": "/api/start_research",
            "endpoint": "research.start_research",
            "description": "Start research",
            "blueprint": "research",
        }
        assert "endpoint" in route
        assert "." in route["endpoint"]  # Blueprint.endpoint format

    def test_route_dict_has_description(self):
        """Route dict should have description key."""
        route = {
            "method": "GET",
            "path": "/settings",
            "endpoint": "settings.settings_page",
            "description": "Settings page",
            "blueprint": "settings",
        }
        assert "description" in route
        assert len(route["description"]) > 0

    def test_route_dict_has_blueprint(self):
        """Route dict should have blueprint key."""
        route = {
            "method": "GET",
            "path": "/metrics",
            "endpoint": "metrics.metrics_dashboard",
            "description": "Metrics dashboard",
            "blueprint": "metrics",
        }
        assert "blueprint" in route

    def test_prefix_concatenation_with_prefix(self):
        """Should concatenate prefix with path."""
        prefix = "/api/v1"
        path = "/health"
        full_path = f"{prefix}{path}"

        assert full_path == "/api/v1/health"

    def test_prefix_concatenation_without_prefix(self):
        """Should use path directly when no prefix."""
        prefix = None
        path = "/"
        full_path = f"{prefix}{path}" if prefix else path

        assert full_path == "/"

    def test_endpoint_format(self):
        """Endpoint should be blueprint.endpoint format."""
        blueprint_name = "research"
        endpoint = "index"
        full_endpoint = f"{blueprint_name}.{endpoint}"

        assert full_endpoint == "research.index"


class TestGetRoutesByBlueprint:
    """Tests for get_routes_by_blueprint function."""

    def test_returns_list(self):
        """get_routes_by_blueprint should return a list."""
        routes = []
        assert isinstance(routes, list)

    def test_unknown_blueprint_returns_empty(self):
        """Unknown blueprint should return empty list."""
        registry = {
            "research": {
                "blueprint": "research_bp",
                "url_prefix": None,
                "routes": [],
            }
        }
        blueprint_name = "unknown"

        if blueprint_name not in registry:
            result = []
        else:
            result = registry[blueprint_name]["routes"]

        assert result == []

    def test_valid_blueprint_returns_routes(self):
        """Valid blueprint should return its routes."""
        registry = {
            "research": {
                "blueprint": "research_bp",
                "url_prefix": None,
                "routes": [("GET", "/", "index", "Home page")],
            }
        }

        result = registry["research"]["routes"]
        assert len(result) == 1

    def test_route_dict_structure(self):
        """Route dict should have expected structure."""
        route = {
            "method": "GET",
            "path": "/settings/api",
            "endpoint": "api_get_all_settings",
            "description": "Get all settings",
        }

        assert "method" in route
        assert "path" in route
        assert "endpoint" in route
        assert "description" in route

    def test_prefix_applied_to_routes(self):
        """Prefix should be applied to all routes."""
        prefix = "/settings"
        path = "/api"
        full_path = f"{prefix}{path}"

        assert full_path == "/settings/api"


class TestFindRoute:
    """Tests for find_route function."""

    def test_returns_list(self):
        """find_route should return a list."""
        matching_routes = []
        assert isinstance(matching_routes, list)

    def test_case_insensitive_matching(self):
        """Should match routes case-insensitively."""
        pattern = "/API"
        route_path = "/api/history"

        matches = pattern.lower() in route_path.lower()
        assert matches is True

    def test_partial_matching(self):
        """Should match partial path patterns."""
        pattern = "research"
        route_path = "/api/research/123/status"

        matches = pattern.lower() in route_path.lower()
        assert matches is True

    def test_no_match_returns_empty(self):
        """No matching routes should return empty list."""
        pattern = "nonexistent"
        routes = [
            {"path": "/api/history"},
            {"path": "/settings"},
        ]

        matching = [r for r in routes if pattern.lower() in r["path"].lower()]
        assert matching == []

    def test_multiple_matches(self):
        """Should return all matching routes."""
        pattern = "api"
        routes = [
            {"path": "/api/history"},
            {"path": "/api/start_research"},
            {"path": "/settings"},
        ]

        matching = [r for r in routes if pattern.lower() in r["path"].lower()]
        assert len(matching) == 2

    def test_matching_preserves_route_info(self):
        """Matching should preserve full route info."""
        route = {
            "method": "GET",
            "path": "/api/history",
            "endpoint": "research.get_history",
            "description": "Get history",
        }

        pattern = "history"
        if pattern.lower() in route["path"].lower():
            matched = route

        assert matched["method"] == "GET"
        assert matched["endpoint"] == "research.get_history"


class TestResearchBlueprintRoutes:
    """Tests for research blueprint routes."""

    def test_index_route_exists(self):
        """Index route should exist."""
        route = ("GET", "/", "index", "Home/Research page")
        assert route[0] == "GET"
        assert route[1] == "/"

    def test_start_research_route_exists(self):
        """Start research route should exist."""
        route = (
            "POST",
            "/api/start_research",
            "start_research",
            "Start new research",
        )
        assert route[0] == "POST"

    def test_get_research_details_route_exists(self):
        """Get research details route should exist."""
        route = (
            "GET",
            "/api/research/<string:research_id>",
            "get_research_details",
            "Get research details",
        )
        assert "<string:research_id>" in route[1]

    def test_terminate_research_route_exists(self):
        """Terminate research route should exist."""
        route = (
            "POST",
            "/api/terminate/<string:research_id>",
            "terminate_research",
            "Stop research",
        )
        assert route[0] == "POST"

    def test_delete_research_route_exists(self):
        """Delete research route should exist."""
        route = (
            "DELETE",
            "/api/delete/<string:research_id>",
            "delete_research",
            "Delete research",
        )
        assert route[0] == "DELETE"


class TestApiV1BlueprintRoutes:
    """Tests for API v1 blueprint routes."""

    def test_url_prefix(self):
        """API v1 should have /api/v1 prefix."""
        prefix = "/api/v1"
        assert prefix == "/api/v1"

    def test_health_check_route_exists(self):
        """Health check route should exist."""
        route = ("GET", "/health", "health_check", "Health check")
        assert route[2] == "health_check"

    def test_quick_summary_route_exists(self):
        """Quick summary route should exist."""
        route = (
            "POST",
            "/quick_summary",
            "api_quick_summary",
            "Quick LLM summary",
        )
        assert route[0] == "POST"

    def test_generate_report_route_exists(self):
        """Generate report route should exist."""
        route = (
            "POST",
            "/generate_report",
            "api_generate_report",
            "Generate research report",
        )
        assert route[0] == "POST"


class TestSettingsBlueprintRoutes:
    """Tests for settings blueprint routes."""

    def test_url_prefix(self):
        """Settings should have /settings prefix."""
        prefix = "/settings"
        assert prefix == "/settings"

    def test_save_all_settings_route_exists(self):
        """Save all settings route should exist."""
        route = (
            "POST",
            "/save_all_settings",
            "save_all_settings",
            "Save all settings",
        )
        assert route[0] == "POST"

    def test_reset_to_defaults_route_exists(self):
        """Reset to defaults route should exist."""
        route = (
            "POST",
            "/reset_to_defaults",
            "reset_to_defaults",
            "Reset to defaults",
        )
        assert route[0] == "POST"

    def test_api_crud_routes_exist(self):
        """API CRUD routes should exist."""
        routes = [
            ("GET", "/api", "api_get_all_settings", "Get all settings"),
            (
                "GET",
                "/api/<path:key>",
                "api_get_setting",
                "Get specific setting",
            ),
            ("POST", "/api/<path:key>", "api_update_setting", "Update setting"),
            (
                "DELETE",
                "/api/<path:key>",
                "api_delete_setting",
                "Delete setting",
            ),
        ]

        methods = [r[0] for r in routes]
        assert "GET" in methods
        assert "POST" in methods
        assert "DELETE" in methods


class TestMetricsBlueprintRoutes:
    """Tests for metrics blueprint routes."""

    def test_url_prefix(self):
        """Metrics should have /metrics prefix."""
        prefix = "/metrics"
        assert prefix == "/metrics"

    def test_metrics_dashboard_route_exists(self):
        """Metrics dashboard route should exist."""
        route = ("GET", "/", "metrics_dashboard", "Metrics dashboard")
        assert route[2] == "metrics_dashboard"

    def test_costs_page_route_exists(self):
        """Costs page route should exist."""
        route = ("GET", "/costs", "costs_page", "Costs page")
        assert route[2] == "costs_page"

    def test_ratings_routes_exist(self):
        """Rating routes should exist."""
        routes = [
            (
                "GET",
                "/api/ratings/<string:research_id>",
                "api_get_research_rating",
                "Get research rating",
            ),
            (
                "POST",
                "/api/ratings/<string:research_id>",
                "api_save_research_rating",
                "Save research rating",
            ),
        ]

        assert routes[0][0] == "GET"
        assert routes[1][0] == "POST"


class TestRoutePathPatterns:
    """Tests for route path patterns."""

    def test_string_parameter_pattern(self):
        """Should support string parameter pattern."""
        path = "/api/research/<string:research_id>"
        assert "<string:research_id>" in path

    def test_path_parameter_pattern(self):
        """Should support path parameter pattern."""
        path = "/api/<path:key>"
        assert "<path:key>" in path

    def test_root_path(self):
        """Should support root path."""
        path = "/"
        assert path == "/"

    def test_nested_path(self):
        """Should support nested paths."""
        path = "/api/metrics/research/<string:research_id>/timeline"
        assert path.count("/") == 5


class TestHTTPMethods:
    """Tests for HTTP method support."""

    def test_get_method_supported(self):
        """GET method should be supported."""
        method = "GET"
        supported_methods = ["GET", "POST", "PUT", "DELETE", "PATCH"]
        assert method in supported_methods

    def test_post_method_supported(self):
        """POST method should be supported."""
        method = "POST"
        supported_methods = ["GET", "POST", "PUT", "DELETE", "PATCH"]
        assert method in supported_methods

    def test_delete_method_supported(self):
        """DELETE method should be supported."""
        method = "DELETE"
        supported_methods = ["GET", "POST", "PUT", "DELETE", "PATCH"]
        assert method in supported_methods

    def test_method_case_sensitivity(self):
        """Methods should be uppercase."""
        methods = ["GET", "POST", "DELETE"]
        for method in methods:
            assert method == method.upper()
