"""Auto-discover all routes and verify they're covered in permission_config.

This test runs without a server — it inspects the FastAPI app directly.
When a new route is added, this test will FAIL until it's added to
permission_config.ROUTE_PERMISSIONS.
"""

from tests.permission_config import ROUTE_PERMISSIONS, DYNAMIC_ROUTES, EXCLUDED_ROUTES


def collect_app_routes():
    """Return set of (method, path) from the main app and all routers."""
    from app.main import app
    routes = set()
    for route in app.routes:
        if hasattr(route, "methods") and hasattr(route, "path"):
            for method in route.methods:
                method = method.upper()
                if method in ("GET", "POST", "PUT", "DELETE", "PATCH"):
                    routes.add((method, route.path))
    return routes


def test_all_routes_covered():
    """Every app route must have a permission entry."""
    app_routes = collect_app_routes() - EXCLUDED_ROUTES
    config_routes = set(ROUTE_PERMISSIONS.keys())
    missing = app_routes - config_routes
    assert not missing, (
        f"Routes missing from permission_config.ROUTE_PERMISSIONS:\n"
        + "\n".join(f"  {m} {p}" for m, p in sorted(missing))
        + "\n\nAdd them to py_service/tests/permission_config.py"
    )


def test_no_stale_permissions():
    """No stale entries in permission config."""
    app_routes = collect_app_routes() - EXCLUDED_ROUTES
    config_routes = set(ROUTE_PERMISSIONS.keys())
    stale = config_routes - app_routes
    assert not stale, (
        f"ROUTE_PERMISSIONS has stale entries (route no longer exists):\n"
        + "\n".join(f"  {m} {p}" for m, p in sorted(stale))
    )


def test_dynamic_routes_also_covered():
    """All DYNAMIC_ROUTES must also be in ROUTE_PERMISSIONS."""
    for entry in DYNAMIC_ROUTES:
        assert entry in ROUTE_PERMISSIONS, (
            f"{entry[0]} {entry[1]} is in DYNAMIC_ROUTES but missing from ROUTE_PERMISSIONS"
        )


def test_all_roles_valid():
    """Allowed roles must be one of: owner, engineer, technician, anonymous, authenticated."""
    valid_roles = {"owner", "engineer", "technician", "anonymous", "authenticated"}
    for (method, path), allowed_roles in ROUTE_PERMISSIONS.items():
        for role in allowed_roles:
            assert role in valid_roles, (
                f"{method} {path}: invalid role '{role}' (valid: {valid_roles})"
            )
