#![cfg(feature = "axum")]

mod compat;

use std::collections::BTreeSet;
use std::sync::Arc;

use athena_auth::adapters::{
    AccountOps, MemoryDatabaseAdapter, SessionOps, UserOps, VerificationOps,
};
use athena_auth::handlers::AxumIntegration;
use athena_auth::plugins::oauth::{OAuthConfig, OAuthProvider, OAuthUserInfo};
use athena_auth::plugins::{
    AccountManagementPlugin, AdminPlugin, ApiKeyPlugin, EmailPasswordPlugin,
    EmailVerificationPlugin, OAuthPlugin, OrganizationPlugin, PasskeyPlugin,
    PasswordManagementPlugin, SessionManagementPlugin, TwoFactorPlugin, UserManagementPlugin,
};
use athena_auth::types_mod::{ApiKeyOps, CreateOAuthClient, TwoFactorOps, UpdateApiKey};
use athena_auth::{
    AthenaAuth, AuthBuilder, AuthConfig, AuthSession, AuthTwoFactor, AuthUser, AuthVerification,
    ConsoleEmailProvider, CreateAccount, CreateSession, CreateUser, CreateVerification, HttpMethod,
    UpdateUser,
};
use axum::{
    Json, Router,
    body::{self, Body},
    http::{HeaderMap, Method, Request, Response},
    routing::get,
};
use chrono::{Duration as ChronoDuration, Utc};
use compat::helpers::{test_secret, unique_email, unique_slug};
use compat::schema::load_openapi_spec;
use serde::Serialize;
use serde_json::{Value, json};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use totp_rs::{Algorithm, Secret, TOTP};
use tower::ServiceExt;
use url::Url;

const TEST_ORIGIN: &str = "http://localhost:3000";
const AUTH_PREFIX: &str = "/api/auth";

fn map_test_user_info(value: Value) -> Result<OAuthUserInfo, String> {
    Ok(OAuthUserInfo {
        id: value["sub"]
            .as_str()
            .unwrap_or("mock-user-id-test")
            .to_string(),
        email: value["email"]
            .as_str()
            .unwrap_or("social-oauth@example.com")
            .to_string(),
        name: value["name"].as_str().map(String::from),
        image: None,
        email_verified: true,
    })
}

fn map_testlink_user_info(value: Value) -> Result<OAuthUserInfo, String> {
    Ok(OAuthUserInfo {
        id: value["sub"]
            .as_str()
            .unwrap_or("mock-user-id-testlink")
            .to_string(),
        email: value["email"]
            .as_str()
            .unwrap_or("linked-oauth@example.com")
            .to_string(),
        name: value["name"].as_str().map(String::from),
        image: None,
        email_verified: true,
    })
}

struct MockOAuthServer {
    base_url: String,
    join: tokio::task::JoinHandle<()>,
}

impl MockOAuthServer {
    async fn start() -> Self {
        let listener = tokio::net::TcpListener::bind("127.0.0.1:0")
            .await
            .expect("bind mock oauth listener");
        let addr = listener.local_addr().expect("mock oauth local_addr");
        let base_url = format!("http://{}", addr);

        let join = tokio::spawn(async move {
            loop {
                let Ok((mut stream, _peer)) = listener.accept().await else {
                    break;
                };
                tokio::spawn(async move {
                    let mut buf = vec![0_u8; 8192];
                    let n = stream.read(&mut buf).await.unwrap_or(0);
                    let request = String::from_utf8_lossy(&buf[..n]);

                    let (status, body) = if request.contains("POST /token/testlink ") {
                        (
                            "200 OK",
                            json!({
                                "access_token": "mock-access-token-testlink",
                                "refresh_token": "mock-refresh-token-testlink",
                                "token_type": "Bearer",
                                "expires_in": 3600,
                                "scope": "email profile"
                            })
                            .to_string(),
                        )
                    } else if request.contains("POST /token/test ") {
                        (
                            "200 OK",
                            json!({
                                "access_token": "mock-access-token-test",
                                "refresh_token": "mock-refresh-token-test",
                                "token_type": "Bearer",
                                "expires_in": 3600,
                                "scope": "email profile"
                            })
                            .to_string(),
                        )
                    } else if request.contains("GET /userinfo/testlink ") {
                        (
                            "200 OK",
                            json!({
                                "sub": "mock-user-id-testlink",
                                "email": "linked-oauth@example.com",
                                "name": "Linked OAuth User",
                                "email_verified": true
                            })
                            .to_string(),
                        )
                    } else if request.contains("GET /userinfo/test ") {
                        (
                            "200 OK",
                            json!({
                                "sub": "mock-user-id-test",
                                "email": "social-oauth@example.com",
                                "name": "Social OAuth User",
                                "email_verified": true
                            })
                            .to_string(),
                        )
                    } else {
                        ("404 Not Found", json!({ "error": "not found" }).to_string())
                    };

                    let response = format!(
                        "HTTP/1.1 {status}\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{body}",
                        body.len()
                    );
                    let _ = stream.write_all(response.as_bytes()).await;
                    let _ = stream.flush().await;
                });
            }
        });

        Self { base_url, join }
    }

    fn generic_provider(&self, provider_id: &str) -> OAuthProvider {
        let map_user_info = match provider_id {
            "test" => map_test_user_info,
            "testlink" => map_testlink_user_info,
            other => panic!("unsupported mock provider: {other}"),
        };
        OAuthProvider {
            client_id: format!("{provider_id}-client"),
            client_secret: format!("{provider_id}-secret"),
            auth_url: format!("{}/auth/{}", self.base_url, provider_id),
            token_url: format!("{}/token/{}", self.base_url, provider_id),
            user_info_url: format!("{}/userinfo/{}", self.base_url, provider_id),
            scopes: vec!["email".to_string(), "profile".to_string()],
            map_user_info,
            extra_auth_params: vec![],
        }
    }
}

impl Drop for MockOAuthServer {
    fn drop(&mut self) {
        self.join.abort();
    }
}

#[derive(Debug, Clone)]
struct FixtureUser {
    user_id: String,
    email: String,
    password: String,
    token: String,
}

#[derive(Debug)]
struct ResponseData {
    status: u16,
    body: Value,
    headers: HeaderMap,
}

#[derive(Debug, Clone)]
enum ExpectedStatus {
    OneOf(&'static [u16]),
    Range(u16, u16),
}

impl ExpectedStatus {
    fn matches(&self, status: u16) -> bool {
        match self {
            Self::OneOf(values) => values.contains(&status),
            Self::Range(start, end) => (status >= *start) && (status <= *end),
        }
    }

    fn description(&self) -> String {
        match self {
            Self::OneOf(values) => values
                .iter()
                .map(ToString::to_string)
                .collect::<Vec<_>>()
                .join("|"),
            Self::Range(start, end) => format!("{start}-{end}"),
        }
    }
}

#[derive(Debug, Clone)]
struct RouteReportEntry {
    method: String,
    route: String,
    actual_path: String,
    mode: &'static str,
    note: &'static str,
    expected: String,
    status: u16,
    passed: bool,
    body_preview: String,
}

#[derive(Default)]
struct RouteMatrixReport {
    entries: Vec<RouteReportEntry>,
    failures: Vec<String>,
}

impl RouteMatrixReport {
    fn record(
        &mut self,
        method: &str,
        route: &str,
        actual_path: impl Into<String>,
        mode: &'static str,
        note: &'static str,
        expected: ExpectedStatus,
        response: &ResponseData,
    ) {
        let passed = expected.matches(response.status);
        let body_preview = truncate_preview(&response.body);
        let entry = RouteReportEntry {
            method: method.to_string(),
            route: route.to_string(),
            actual_path: actual_path.into(),
            mode,
            note,
            expected: expected.description(),
            status: response.status,
            passed,
            body_preview: body_preview.clone(),
        };
        if !passed {
            self.failures.push(format!(
                "{method} {route} expected {} but received {}. Body: {}",
                entry.expected, response.status, body_preview
            ));
        }
        self.entries.push(entry);
    }

    fn exercised_route_keys(&self) -> BTreeSet<String> {
        self.entries
            .iter()
            .map(|entry| format!("{} {}", entry.method, entry.route))
            .collect()
    }
}

struct AxumRouteSuite {
    auth: Arc<AthenaAuth<MemoryDatabaseAdapter>>,
    router: Router,
    _mock_oauth: MockOAuthServer,
}

impl AxumRouteSuite {
    async fn new() -> Self {
        let mock_oauth = MockOAuthServer::start().await;

        let mut oauth_config = OAuthConfig::default();
        oauth_config
            .providers
            .insert("test".to_string(), mock_oauth.generic_provider("test"));
        oauth_config.providers.insert(
            "testlink".to_string(),
            mock_oauth.generic_provider("testlink"),
        );

        let config = AuthConfig::new(test_secret())
            .base_url(TEST_ORIGIN)
            .public_base_path(AUTH_PREFIX)
            .trusted_origin(TEST_ORIGIN.to_string())
            .password_min_length(8);

        let auth = Arc::new(
            AuthBuilder::new(config)
                .email_provider(ConsoleEmailProvider)
                .database(MemoryDatabaseAdapter::new())
                .plugin(EmailPasswordPlugin::new().enable_signup(true))
                .plugin(SessionManagementPlugin::new())
                .plugin(PasswordManagementPlugin::new().require_current_password(true))
                .plugin(AccountManagementPlugin::new())
                .plugin(EmailVerificationPlugin::new())
                .plugin(ApiKeyPlugin::builder().build())
                .plugin(OAuthPlugin::with_config(oauth_config))
                .plugin(TwoFactorPlugin::new())
                .plugin(OrganizationPlugin::new())
                .plugin(
                    PasskeyPlugin::new()
                        .rp_id("localhost")
                        .rp_name("Athena Auth Matrix")
                        .origin(TEST_ORIGIN)
                        .allow_insecure_unverified_assertion(true),
                )
                .plugin(AdminPlugin::new())
                .plugin(
                    UserManagementPlugin::new()
                        .change_email_enabled(true)
                        .delete_user_enabled(true),
                )
                .build()
                .await
                .expect("build matrix auth"),
        );

        auth.database()
            .create_oauth_client(CreateOAuthClient {
                client_name: "matrix-test-social".to_string(),
                provider: "test".to_string(),
                description: Some("matrix test social provider".to_string()),
                response_type: Some("code".to_string()),
                grant_type: Some("authorization_code".to_string()),
                token_authentication_method: Some("none".to_string()),
                redirect_uris: vec![format!("{TEST_ORIGIN}/session")],
                client_url: Some(TEST_ORIGIN.to_string()),
                scopes: Some(vec!["email".to_string(), "profile".to_string()]),
                is_active: Some(true),
                metadata: None,
            })
            .await
            .expect("seed oauth client for test provider");
        auth.database()
            .create_oauth_client(CreateOAuthClient {
                client_name: "matrix-test-link".to_string(),
                provider: "testlink".to_string(),
                description: Some("matrix test linked provider".to_string()),
                response_type: Some("code".to_string()),
                grant_type: Some("authorization_code".to_string()),
                token_authentication_method: Some("none".to_string()),
                redirect_uris: vec![format!("{TEST_ORIGIN}/session")],
                client_url: Some(TEST_ORIGIN.to_string()),
                scopes: Some(vec!["email".to_string(), "profile".to_string()]),
                is_active: Some(true),
                metadata: None,
            })
            .await
            .expect("seed oauth client for testlink provider");

        let auth_router = auth.clone().axum_router();
        let well_known_payload = Arc::new(json!({
            "origins": [TEST_ORIGIN]
        }));
        let router = Router::new()
            .route(
                "/.well-known/webauthn",
                get(move || {
                    let payload = well_known_payload.clone();
                    async move { Json((*payload).clone()) }
                }),
            )
            .nest(AUTH_PREFIX, auth_router)
            .with_state(auth.clone());

        Self {
            auth,
            router,
            _mock_oauth: mock_oauth,
        }
    }

    async fn send(
        &self,
        method: Method,
        logical_path: &str,
        token: Option<&str>,
        body_json: Option<Value>,
    ) -> ResponseData {
        let request_path = if logical_path.starts_with('/') {
            format!("{AUTH_PREFIX}{logical_path}")
        } else {
            format!("{AUTH_PREFIX}/{logical_path}")
        };
        self.send_request_path(method, request_path, token, body_json)
            .await
    }

    async fn send_request_path(
        &self,
        method: Method,
        request_path: String,
        token: Option<&str>,
        body_json: Option<Value>,
    ) -> ResponseData {
        let mut builder = Request::builder()
            .method(method)
            .uri(&request_path)
            .header("origin", TEST_ORIGIN);
        if let Some(token) = token {
            builder = builder.header("authorization", format!("Bearer {token}"));
        }
        let body = if let Some(body_json) = body_json {
            builder = builder.header("content-type", "application/json");
            Body::from(body_json.to_string())
        } else {
            Body::empty()
        };
        let request = builder.body(body).expect("build request");
        let response: Response<Body> = self
            .router
            .clone()
            .oneshot(request)
            .await
            .expect("router oneshot");
        response_to_data(response).await
    }

    async fn send_raw(
        &self,
        method: Method,
        logical_path_with_query: &str,
        token: Option<&str>,
    ) -> ResponseData {
        self.send(method, logical_path_with_query, token, None)
            .await
    }

    async fn send_unprefixed_raw(
        &self,
        method: Method,
        path_with_query: &str,
        token: Option<&str>,
    ) -> ResponseData {
        self.send_request_path(method, path_with_query.to_string(), token, None)
            .await
    }

    async fn signup_user(&self, prefix: &str, name: &str) -> FixtureUser {
        let email = unique_email(prefix);
        let password = "password123".to_string();
        let response = self
            .send(
                Method::POST,
                "/sign-up/email",
                None,
                Some(json!({
                    "email": email,
                    "password": password,
                    "name": name
                })),
            )
            .await;
        assert_eq!(response.status, 200, "signup failed: {}", response.body);
        FixtureUser {
            user_id: response.body["user"]["id"]
                .as_str()
                .expect("signup response user.id")
                .to_string(),
            email: response.body["user"]["email"]
                .as_str()
                .expect("signup response user.email")
                .to_string(),
            password,
            token: response.body["token"]
                .as_str()
                .expect("signup response token")
                .to_string(),
        }
    }

    async fn create_bootstrap_admin(&self) -> FixtureUser {
        let admin = self.signup_user("matrix_admin", "Matrix Admin").await;
        self.auth
            .database()
            .update_user(
                &admin.user_id,
                UpdateUser {
                    role: Some("admin".to_string()),
                    ..Default::default()
                },
            )
            .await
            .expect("promote admin");
        admin
    }

    async fn mark_email_verified(&self, email: &str) {
        let user = self
            .auth
            .database()
            .get_user_by_email(email)
            .await
            .expect("lookup user by email")
            .expect("user should exist");
        self.auth
            .database()
            .update_user(
                user.id(),
                UpdateUser {
                    email_verified: Some(true),
                    ..Default::default()
                },
            )
            .await
            .expect("mark email verified");
    }

    async fn create_social_only_user_session(&self, prefix: &str) -> FixtureUser {
        let email = unique_email(prefix);
        let user = self
            .auth
            .database()
            .create_user(
                CreateUser::new()
                    .with_email(&email)
                    .with_name("Social Only User")
                    .with_email_verified(true),
            )
            .await
            .expect("create social only user");
        let session = self
            .auth
            .database()
            .create_session(CreateSession {
                user_id: user.id().to_string(),
                expires_at: Utc::now() + ChronoDuration::hours(24),
                ip_address: None,
                user_agent: None,
                impersonated_by: None,
                active_organization_id: None,
            })
            .await
            .expect("create session");
        FixtureUser {
            user_id: user.id().to_string(),
            email,
            password: String::new(),
            token: session.token().to_string(),
        }
    }

    async fn seed_delete_callback_token(&self, user_id: &str) -> String {
        let token = format!("delete_callback_{}", unique_slug("token"));
        self.auth
            .database()
            .create_verification(CreateVerification {
                identifier: user_id.to_string(),
                value: token.clone(),
                expires_at: Utc::now() + ChronoDuration::hours(24),
            })
            .await
            .expect("create deletion callback token");
        token
    }

    async fn current_verification_value(&self, identifier: &str) -> String {
        let mut candidates = vec![identifier.to_string()];
        if identifier.contains('@') {
            #[derive(Serialize)]
            struct ResetContextProbe<'a> {
                email: &'a str,
                #[serde(rename = "callbackURL")]
                callback_url: String,
            }

            let serialized = serde_json::to_string(&ResetContextProbe {
                email: identifier,
                callback_url: format!("{TEST_ORIGIN}/reset-password"),
            })
            .expect("serialize reset token context probe");
            candidates.push(format!("reset_ctx:{}", serialized));
        }

        for candidate in &candidates {
            if let Some(verification) = self
                .auth
                .database()
                .get_verification_by_identifier(candidate)
                .await
                .expect("lookup verification")
            {
                return verification.value().to_string();
            }
        }

        panic!(
            "verification should exist for one of: {}",
            candidates.join(", ")
        );
    }

    async fn compute_current_totp_code(&self, user_id: &str) -> String {
        let record = self
            .auth
            .database()
            .get_two_factor_by_user_id(user_id)
            .await
            .expect("lookup two factor")
            .expect("two factor should exist");
        let secret = Secret::Encoded(record.secret().to_string());
        let secret_bytes = secret.to_bytes().expect("decode two factor secret");
        let user = self
            .auth
            .database()
            .get_user_by_id(user_id)
            .await
            .expect("lookup user")
            .expect("user should exist");
        let email = user.email().unwrap_or("user@example.com");
        let totp = TOTP::new(
            Algorithm::SHA1,
            6,
            1,
            30,
            secret_bytes,
            Some("AthenaAuth".to_string()),
            email.to_string(),
        )
        .expect("create totp");
        totp.generate_current().expect("generate current totp")
    }

    async fn implemented_route_keys(&self) -> BTreeSet<String> {
        let mut routes = BTreeSet::new();
        for (method, path) in [
            ("GET", "/ok"),
            ("GET", "/error"),
            ("GET", "/health"),
            ("GET", "/reference/openapi.json"),
            ("GET", "/.well-known/webauthn"),
            ("POST", "/update-user"),
            ("POST", "/change-email"),
            ("POST", "/delete-user"),
            ("DELETE", "/delete-user"),
            ("GET", "/delete-user/callback"),
        ] {
            routes.insert(format!("{method} {path}"));
        }

        for plugin in self.auth.plugins() {
            for route in plugin.routes() {
                let method = match route.method {
                    HttpMethod::Get => "GET",
                    HttpMethod::Post => "POST",
                    HttpMethod::Put => "PUT",
                    HttpMethod::Delete => "DELETE",
                    HttpMethod::Patch => "PATCH",
                    HttpMethod::Options => "OPTIONS",
                    HttpMethod::Head => "HEAD",
                };
                routes.insert(format!("{method} {}", route.path));
            }
        }

        routes
    }
}

async fn response_to_data(response: Response<Body>) -> ResponseData {
    let status = response.status().as_u16();
    let headers = response.headers().clone();
    let body_bytes = body::to_bytes(response.into_body(), usize::MAX)
        .await
        .expect("read response body");
    let body = serde_json::from_slice(&body_bytes)
        .unwrap_or_else(|_| Value::String(String::from_utf8_lossy(&body_bytes).to_string()));
    ResponseData {
        status,
        body,
        headers,
    }
}

fn truncate_preview(value: &Value) -> String {
    let text = serde_json::to_string(value).unwrap_or_else(|_| "<non-json>".to_string());
    if text.len() <= 160 {
        text
    } else {
        format!("{}...", &text[..160])
    }
}

fn extract_query_param(url: &str, key: &str) -> String {
    Url::parse(url)
        .expect("parse url")
        .query_pairs()
        .find(|(name, _)| name == key)
        .map(|(_, value)| value.to_string())
        .unwrap_or_else(|| panic!("missing query param '{key}' in url '{url}'"))
}

fn documented_route_keys() -> BTreeSet<String> {
    let spec = load_openapi_spec();
    let mut routes = BTreeSet::new();
    let paths = spec.paths.as_ref().expect("openapi paths");
    for (path, item) in paths {
        if item.get.is_some() {
            routes.insert(format!("GET {path}"));
        }
        if item.post.is_some() {
            routes.insert(format!("POST {path}"));
        }
        if item.put.is_some() {
            routes.insert(format!("PUT {path}"));
        }
        if item.delete.is_some() {
            routes.insert(format!("DELETE {path}"));
        }
        if item.patch.is_some() {
            routes.insert(format!("PATCH {path}"));
        }
        if item.options.is_some() {
            routes.insert(format!("OPTIONS {path}"));
        }
        if item.head.is_some() {
            routes.insert(format!("HEAD {path}"));
        }
    }
    routes
}

async fn exercise_auth_and_public_routes(suite: &AxumRouteSuite, report: &mut RouteMatrixReport) {
    let health = suite.send_raw(Method::GET, "/health", None).await;
    report.record(
        "GET",
        "/health",
        "/health",
        "success",
        "health check",
        ExpectedStatus::OneOf(&[200]),
        &health,
    );

    let openapi = suite
        .send_raw(Method::GET, "/reference/openapi.json", None)
        .await;
    report.record(
        "GET",
        "/reference/openapi.json",
        "/reference/openapi.json",
        "success",
        "openapi document",
        ExpectedStatus::OneOf(&[200]),
        &openapi,
    );

    let ok = suite.send_raw(Method::GET, "/ok", None).await;
    report.record(
        "GET",
        "/ok",
        "/ok",
        "success",
        "core ok endpoint",
        ExpectedStatus::OneOf(&[200]),
        &ok,
    );

    let error = suite.send_raw(Method::GET, "/error", None).await;
    report.record(
        "GET",
        "/error",
        "/error",
        "success",
        "core error endpoint",
        ExpectedStatus::OneOf(&[200]),
        &error,
    );

    let signup_user = suite
        .signup_user("matrix_auth_signup", "Matrix Signup")
        .await;
    let signup_response = ResponseData {
        status: 200,
        body: json!({
            "user": {
                "id": signup_user.user_id,
                "email": signup_user.email
            }
        }),
        headers: HeaderMap::new(),
    };
    report.record(
        "POST",
        "/sign-up/email",
        "/sign-up/email",
        "success",
        "email/password signup",
        ExpectedStatus::OneOf(&[200]),
        &signup_response,
    );

    let signin = suite
        .send(
            Method::POST,
            "/sign-in/email",
            None,
            Some(json!({
                "email": signup_user.email,
                "password": signup_user.password
            })),
        )
        .await;
    let signin_token = signin.body["token"]
        .as_str()
        .expect("sign-in token")
        .to_string();
    report.record(
        "POST",
        "/sign-in/email",
        "/sign-in/email",
        "success",
        "email/password sign-in",
        ExpectedStatus::OneOf(&[200]),
        &signin,
    );

    let get_session = suite
        .send(Method::GET, "/get-session", Some(&signin_token), None)
        .await;
    report.record(
        "GET",
        "/get-session",
        "/get-session",
        "success",
        "session lookup",
        ExpectedStatus::OneOf(&[200]),
        &get_session,
    );

    let post_get_session = suite
        .send(
            Method::POST,
            "/get-session",
            Some(&signin_token),
            Some(json!({})),
        )
        .await;
    report.record(
        "POST",
        "/get-session",
        "/get-session",
        "success",
        "session lookup via POST",
        ExpectedStatus::OneOf(&[200]),
        &post_get_session,
    );

    let update_user = suite
        .send(
            Method::POST,
            "/update-user",
            Some(&signin_token),
            Some(json!({
                "name": "Matrix Username",
                "username": "matrix_user_login"
            })),
        )
        .await;
    report.record(
        "POST",
        "/update-user",
        "/update-user",
        "success",
        "update profile and set username",
        ExpectedStatus::OneOf(&[200]),
        &update_user,
    );

    let signin_username = suite
        .send(
            Method::POST,
            "/sign-in/username",
            None,
            Some(json!({
                "username": "matrix_user_login",
                "password": signup_user.password
            })),
        )
        .await;
    report.record(
        "POST",
        "/sign-in/username",
        "/sign-in/username",
        "success",
        "username sign-in",
        ExpectedStatus::OneOf(&[200]),
        &signin_username,
    );

    let list_sessions = suite
        .send(Method::GET, "/list-sessions", Some(&signin_token), None)
        .await;
    let _session_tokens = list_sessions.body.as_array().cloned().unwrap_or_default();
    report.record(
        "GET",
        "/list-sessions",
        "/list-sessions",
        "success",
        "list active sessions",
        ExpectedStatus::OneOf(&[200]),
        &list_sessions,
    );

    let second_session = suite
        .send(
            Method::POST,
            "/sign-in/email",
            None,
            Some(json!({
                "email": signup_user.email,
                "password": signup_user.password
            })),
        )
        .await;
    let second_token = second_session.body["token"]
        .as_str()
        .expect("second session token")
        .to_string();

    let revoke_session = suite
        .send(
            Method::POST,
            "/revoke-session",
            Some(&signin_token),
            Some(json!({ "token": second_token })),
        )
        .await;
    report.record(
        "POST",
        "/revoke-session",
        "/revoke-session",
        "success",
        "revoke a specific session",
        ExpectedStatus::OneOf(&[200]),
        &revoke_session,
    );

    let third_session = suite
        .send(
            Method::POST,
            "/sign-in/email",
            None,
            Some(json!({
                "email": signup_user.email,
                "password": signup_user.password
            })),
        )
        .await;
    let third_token = third_session.body["token"]
        .as_str()
        .expect("third session token")
        .to_string();
    let revoke_other = suite
        .send(
            Method::POST,
            "/revoke-other-sessions",
            Some(&third_token),
            Some(json!({})),
        )
        .await;
    report.record(
        "POST",
        "/revoke-other-sessions",
        "/revoke-other-sessions",
        "success",
        "revoke every session except the current one",
        ExpectedStatus::OneOf(&[200]),
        &revoke_other,
    );

    let revoke_all_user = suite
        .signup_user("matrix_revoke_all", "Matrix Revoke All")
        .await;
    let revoke_all = suite
        .send(
            Method::POST,
            "/revoke-sessions",
            Some(&revoke_all_user.token),
            Some(json!({})),
        )
        .await;
    report.record(
        "POST",
        "/revoke-sessions",
        "/revoke-sessions",
        "success",
        "revoke every session for current user",
        ExpectedStatus::OneOf(&[200]),
        &revoke_all,
    );

    let verification_user = suite
        .signup_user("matrix_verify_email", "Matrix Verify Email")
        .await;
    let send_verification = suite
        .send(
            Method::POST,
            "/send-verification-email",
            None,
            Some(json!({
                "email": verification_user.email
            })),
        )
        .await;
    report.record(
        "POST",
        "/send-verification-email",
        "/send-verification-email",
        "success",
        "issue verification token",
        ExpectedStatus::OneOf(&[200]),
        &send_verification,
    );
    let verify_token = suite
        .current_verification_value(&verification_user.email)
        .await;
    let verify_email = suite
        .send_raw(
            Method::GET,
            &format!("/verify-email?token={verify_token}"),
            None,
        )
        .await;
    report.record(
        "GET",
        "/verify-email",
        format!("/verify-email?token={verify_token}"),
        "success",
        "consume email verification token",
        ExpectedStatus::OneOf(&[200]),
        &verify_email,
    );

    let change_email_user = suite
        .signup_user("matrix_change_email", "Matrix Change Email")
        .await;
    let new_email = unique_email("matrix_changed");
    let change_email = suite
        .send(
            Method::POST,
            "/change-email",
            Some(&change_email_user.token),
            Some(json!({
                "newEmail": new_email
            })),
        )
        .await;
    report.record(
        "POST",
        "/change-email",
        "/change-email",
        "success",
        "request change-email verification",
        ExpectedStatus::OneOf(&[200]),
        &change_email,
    );
    let change_email_token = suite
        .current_verification_value(&format!(
            "change_email:{}:{}",
            change_email_user.user_id, new_email
        ))
        .await;
    let change_email_verify = suite
        .send_raw(
            Method::GET,
            &format!("/change-email/verify?token={change_email_token}"),
            None,
        )
        .await;
    report.record(
        "GET",
        "/change-email/verify",
        format!("/change-email/verify?token={change_email_token}"),
        "success",
        "confirm pending email change",
        ExpectedStatus::OneOf(&[200]),
        &change_email_verify,
    );

    let password_user = suite
        .signup_user("matrix_password_reset", "Matrix Password Reset")
        .await;
    let forget_password = suite
        .send(
            Method::POST,
            "/forget-password",
            None,
            Some(json!({
                "email": password_user.email
            })),
        )
        .await;
    report.record(
        "POST",
        "/forget-password",
        "/forget-password",
        "success",
        "issue password reset token",
        ExpectedStatus::OneOf(&[200]),
        &forget_password,
    );
    let reset_token = suite.current_verification_value(&password_user.email).await;
    let reset_password_token = suite
        .send_raw(Method::GET, &format!("/reset-password/{reset_token}"), None)
        .await;
    if reset_password_token.status == 302 {
        let location = reset_password_token
            .headers
            .get("location")
            .and_then(|value| value.to_str().ok())
            .expect("reset-password redirect should expose location");
        assert!(
            location.starts_with(&format!("{TEST_ORIGIN}/reset-password?token={reset_token}")),
            "unexpected reset-password redirect location: {location}"
        );
    }
    report.record(
        "GET",
        "/reset-password/{token}",
        format!("/reset-password/{reset_token}"),
        "success",
        "inspect password reset token",
        ExpectedStatus::OneOf(&[200, 302]),
        &reset_password_token,
    );
    let reset_password = suite
        .send(
            Method::POST,
            "/reset-password",
            None,
            Some(json!({
                "token": reset_token,
                "newPassword": "ResetPassword123!"
            })),
        )
        .await;
    report.record(
        "POST",
        "/reset-password",
        "/reset-password",
        "success",
        "consume password reset token",
        ExpectedStatus::OneOf(&[200]),
        &reset_password,
    );

    let social_only = suite
        .create_social_only_user_session("matrix_social_only")
        .await;
    let set_password = suite
        .send(
            Method::POST,
            "/set-password",
            Some(&social_only.token),
            Some(json!({
                "newPassword": "SetPassword123!"
            })),
        )
        .await;
    report.record(
        "POST",
        "/set-password",
        "/set-password",
        "success",
        "set password for a social-only account",
        ExpectedStatus::OneOf(&[200]),
        &set_password,
    );

    let change_password_user = suite
        .signup_user("matrix_change_password", "Matrix Change Password")
        .await;
    let change_password = suite
        .send(
            Method::POST,
            "/change-password",
            Some(&change_password_user.token),
            Some(json!({
                "currentPassword": change_password_user.password,
                "newPassword": "MatrixNewPassword123!",
                "revokeOtherSessions": false
            })),
        )
        .await;
    report.record(
        "POST",
        "/change-password",
        "/change-password",
        "success",
        "change the authenticated user's password",
        ExpectedStatus::OneOf(&[200]),
        &change_password,
    );

    let account_user = suite
        .signup_user("matrix_accounts", "Matrix Accounts")
        .await;
    suite
        .auth
        .database()
        .create_account(CreateAccount {
            user_id: account_user.user_id.clone(),
            account_id: unique_slug("manual-account"),
            provider_id: "manual-secondary".to_string(),
            access_token: Some("manual-access-token".to_string()),
            refresh_token: None,
            id_token: None,
            access_token_expires_at: None,
            refresh_token_expires_at: None,
            scope: Some("email profile".to_string()),
            password: None,
        })
        .await
        .expect("seed secondary account");
    let list_accounts = suite
        .send(
            Method::GET,
            "/list-accounts",
            Some(&account_user.token),
            None,
        )
        .await;
    report.record(
        "GET",
        "/list-accounts",
        "/list-accounts",
        "success",
        "list linked accounts",
        ExpectedStatus::OneOf(&[200]),
        &list_accounts,
    );
    let unlink_account = suite
        .send(
            Method::POST,
            "/unlink-account",
            Some(&account_user.token),
            Some(json!({
                "providerId": "manual-secondary"
            })),
        )
        .await;
    report.record(
        "POST",
        "/unlink-account",
        "/unlink-account",
        "success",
        "unlink a secondary account",
        ExpectedStatus::OneOf(&[200]),
        &unlink_account,
    );

    let email_list = suite
        .send(Method::GET, "/email/list", Some(&account_user.token), None)
        .await;
    report.record(
        "GET",
        "/email/list",
        "/email/list",
        "success",
        "list current user's emails",
        ExpectedStatus::OneOf(&[200]),
        &email_list,
    );

    let delete_verify_user = suite
        .signup_user("matrix_delete_verify", "Matrix Delete Verify")
        .await;
    let delete_verify_request = suite
        .send(
            Method::POST,
            "/delete-user",
            Some(&delete_verify_user.token),
            Some(json!({})),
        )
        .await;
    report.record(
        "POST",
        "/delete-user",
        "/delete-user",
        "success",
        "request plugin delete-user verification flow",
        ExpectedStatus::OneOf(&[200]),
        &delete_verify_request,
    );
    let delete_verify_token = suite
        .current_verification_value(&format!("delete_user:{}", delete_verify_user.user_id))
        .await;
    let delete_verify = suite
        .send_raw(
            Method::GET,
            &format!("/delete-user/verify?token={delete_verify_token}"),
            None,
        )
        .await;
    report.record(
        "GET",
        "/delete-user/verify",
        format!("/delete-user/verify?token={delete_verify_token}"),
        "success",
        "consume plugin delete-user verification token",
        ExpectedStatus::OneOf(&[200]),
        &delete_verify,
    );

    let delete_callback_user = suite
        .signup_user("matrix_delete_callback", "Matrix Delete Callback")
        .await;
    let delete_callback_token = suite
        .seed_delete_callback_token(&delete_callback_user.user_id)
        .await;
    let delete_callback = suite
        .send_raw(
            Method::GET,
            &format!("/delete-user/callback?token={delete_callback_token}"),
            None,
        )
        .await;
    report.record(
        "GET",
        "/delete-user/callback",
        format!("/delete-user/callback?token={delete_callback_token}"),
        "success",
        "consume core delete-user callback token",
        ExpectedStatus::OneOf(&[200]),
        &delete_callback,
    );

    let delete_post_user = suite
        .signup_user("matrix_delete_post", "Matrix Delete Post")
        .await;
    let delete_post = suite
        .send(
            Method::POST,
            "/delete-user",
            Some(&delete_post_user.token),
            Some(json!({})),
        )
        .await;
    report.record(
        "POST",
        "/delete-user",
        "/delete-user",
        "success",
        "delete account via POST",
        ExpectedStatus::OneOf(&[200]),
        &delete_post,
    );

    let delete_delete_user = suite
        .signup_user("matrix_delete_delete", "Matrix Delete Delete")
        .await;
    let delete_delete = suite
        .send(
            Method::DELETE,
            "/delete-user",
            Some(&delete_delete_user.token),
            None,
        )
        .await;
    report.record(
        "DELETE",
        "/delete-user",
        "/delete-user",
        "success",
        "delete account via DELETE",
        ExpectedStatus::OneOf(&[200]),
        &delete_delete,
    );

    let sign_out_user = suite
        .signup_user("matrix_sign_out", "Matrix Sign Out")
        .await;
    let sign_out = suite
        .send(
            Method::POST,
            "/sign-out",
            Some(&sign_out_user.token),
            Some(json!({})),
        )
        .await;
    report.record(
        "POST",
        "/sign-out",
        "/sign-out",
        "success",
        "sign out current session",
        ExpectedStatus::OneOf(&[200]),
        &sign_out,
    );
}

async fn exercise_oauth_routes(suite: &AxumRouteSuite, report: &mut RouteMatrixReport) {
    let sign_in_social = suite
        .send(
            Method::POST,
            "/sign-in/social",
            None,
            Some(json!({
                "provider": "test",
                "callbackURL": format!("{TEST_ORIGIN}/session")
            })),
        )
        .await;
    let callback_url = sign_in_social.body["url"]
        .as_str()
        .expect("social sign-in url");
    let state = extract_query_param(callback_url, "state");
    report.record(
        "POST",
        "/sign-in/social",
        "/sign-in/social",
        "success",
        "start social sign-in redirect flow",
        ExpectedStatus::OneOf(&[200]),
        &sign_in_social,
    );

    let callback = suite
        .send_raw(
            Method::GET,
            &format!("/callback/test?code=mock-code&state={state}"),
            None,
        )
        .await;
    let oauth_session_token = callback.body["token"]
        .as_str()
        .expect("oauth callback token")
        .to_string();
    report.record(
        "GET",
        "/callback/{provider}",
        format!("/callback/test?code=mock-code&state={state}"),
        "success",
        "complete social sign-in callback",
        ExpectedStatus::OneOf(&[200]),
        &callback,
    );

    let get_access_token = suite
        .send(
            Method::POST,
            "/get-access-token",
            Some(&oauth_session_token),
            Some(json!({
                "providerId": "test"
            })),
        )
        .await;
    report.record(
        "POST",
        "/get-access-token",
        "/get-access-token",
        "success",
        "read decrypted oauth access token",
        ExpectedStatus::OneOf(&[200]),
        &get_access_token,
    );

    let refresh_token = suite
        .send(
            Method::POST,
            "/refresh-token",
            Some(&oauth_session_token),
            Some(json!({
                "providerId": "test"
            })),
        )
        .await;
    report.record(
        "POST",
        "/refresh-token",
        "/refresh-token",
        "success",
        "refresh oauth access token",
        ExpectedStatus::OneOf(&[200]),
        &refresh_token,
    );

    let link_social_user = suite
        .signup_user("matrix_link_social", "Matrix Link Social")
        .await;
    let link_social = suite
        .send(
            Method::POST,
            "/link-social",
            Some(&link_social_user.token),
            Some(json!({
                "provider": "testlink",
                "callbackURL": format!("{TEST_ORIGIN}/session")
            })),
        )
        .await;
    report.record(
        "POST",
        "/link-social",
        "/link-social",
        "success",
        "start account linking redirect flow",
        ExpectedStatus::OneOf(&[200]),
        &link_social,
    );
}

async fn exercise_two_factor_and_passkey_routes(
    suite: &AxumRouteSuite,
    report: &mut RouteMatrixReport,
) {
    let two_factor_user = suite.signup_user("matrix_2fa", "Matrix Two Factor").await;
    let enable = suite
        .send(
            Method::POST,
            "/two-factor/enable",
            Some(&two_factor_user.token),
            Some(json!({
                "password": two_factor_user.password
            })),
        )
        .await;
    let _backup_codes = enable.body["backupCodes"]
        .as_array()
        .cloned()
        .unwrap_or_default();
    report.record(
        "POST",
        "/two-factor/enable",
        "/two-factor/enable",
        "success",
        "enable two-factor and issue backup codes",
        ExpectedStatus::OneOf(&[200]),
        &enable,
    );

    let totp_uri = suite
        .send(
            Method::POST,
            "/two-factor/get-totp-uri",
            Some(&two_factor_user.token),
            Some(json!({
                "password": two_factor_user.password
            })),
        )
        .await;
    report.record(
        "POST",
        "/two-factor/get-totp-uri",
        "/two-factor/get-totp-uri",
        "success",
        "fetch current TOTP URI",
        ExpectedStatus::OneOf(&[200]),
        &totp_uri,
    );

    let generate_backup_codes = suite
        .send(
            Method::POST,
            "/two-factor/generate-backup-codes",
            Some(&two_factor_user.token),
            Some(json!({
                "password": two_factor_user.password
            })),
        )
        .await;
    report.record(
        "POST",
        "/two-factor/generate-backup-codes",
        "/two-factor/generate-backup-codes",
        "success",
        "rotate backup codes",
        ExpectedStatus::OneOf(&[200]),
        &generate_backup_codes,
    );
    let rotated_backup_codes = generate_backup_codes.body["backupCodes"]
        .as_array()
        .cloned()
        .unwrap_or_default();

    let pending_signin = suite
        .send(
            Method::POST,
            "/sign-in/email",
            None,
            Some(json!({
                "email": two_factor_user.email,
                "password": two_factor_user.password
            })),
        )
        .await;
    let pending_token = pending_signin.body["token"]
        .as_str()
        .expect("pending 2fa token")
        .to_string();

    let send_otp = suite
        .send(
            Method::POST,
            "/two-factor/send-otp",
            Some(&pending_token),
            Some(json!({})),
        )
        .await;
    report.record(
        "POST",
        "/two-factor/send-otp",
        "/two-factor/send-otp",
        "success",
        "issue an email OTP for pending sign-in",
        ExpectedStatus::OneOf(&[200]),
        &send_otp,
    );

    let otp_code = suite
        .current_verification_value(&format!("2fa_otp:{}", two_factor_user.user_id))
        .await;
    let verify_otp = suite
        .send(
            Method::POST,
            "/two-factor/verify-otp",
            Some(&pending_token),
            Some(json!({
                "code": otp_code
            })),
        )
        .await;
    report.record(
        "POST",
        "/two-factor/verify-otp",
        "/two-factor/verify-otp",
        "success",
        "complete pending sign-in with OTP",
        ExpectedStatus::OneOf(&[200]),
        &verify_otp,
    );

    let pending_signin_backup = suite
        .send(
            Method::POST,
            "/sign-in/email",
            None,
            Some(json!({
                "email": two_factor_user.email,
                "password": two_factor_user.password
            })),
        )
        .await;
    let pending_backup_token = pending_signin_backup.body["token"]
        .as_str()
        .expect("pending backup token")
        .to_string();
    let backup_code = rotated_backup_codes
        .first()
        .and_then(Value::as_str)
        .expect("first backup code")
        .to_string();
    let verify_backup = suite
        .send(
            Method::POST,
            "/two-factor/verify-backup-code",
            Some(&pending_backup_token),
            Some(json!({
                "code": backup_code
            })),
        )
        .await;
    report.record(
        "POST",
        "/two-factor/verify-backup-code",
        "/two-factor/verify-backup-code",
        "success",
        "complete pending sign-in with backup code",
        ExpectedStatus::OneOf(&[200]),
        &verify_backup,
    );

    let pending_signin_totp = suite
        .send(
            Method::POST,
            "/sign-in/email",
            None,
            Some(json!({
                "email": two_factor_user.email,
                "password": two_factor_user.password
            })),
        )
        .await;
    let pending_totp_token = pending_signin_totp.body["token"]
        .as_str()
        .expect("pending totp token")
        .to_string();
    let totp_code = suite
        .compute_current_totp_code(&two_factor_user.user_id)
        .await;
    let verify_totp = suite
        .send(
            Method::POST,
            "/two-factor/verify-totp",
            Some(&pending_totp_token),
            Some(json!({
                "code": totp_code
            })),
        )
        .await;
    report.record(
        "POST",
        "/two-factor/verify-totp",
        "/two-factor/verify-totp",
        "success",
        "complete pending sign-in with current TOTP code",
        ExpectedStatus::OneOf(&[200]),
        &verify_totp,
    );

    let disable = suite
        .send(
            Method::POST,
            "/two-factor/disable",
            Some(&two_factor_user.token),
            Some(json!({
                "password": two_factor_user.password
            })),
        )
        .await;
    report.record(
        "POST",
        "/two-factor/disable",
        "/two-factor/disable",
        "success",
        "disable two-factor",
        ExpectedStatus::OneOf(&[200]),
        &disable,
    );

    let passkey_user = suite.signup_user("matrix_passkey", "Matrix Passkey").await;
    let well_known = suite
        .send_unprefixed_raw(Method::GET, "/.well-known/webauthn", None)
        .await;
    report.record(
        "GET",
        "/.well-known/webauthn",
        "/.well-known/webauthn",
        "success",
        "fetch webauthn well-known metadata",
        ExpectedStatus::OneOf(&[200]),
        &well_known,
    );

    let register_options = suite
        .send(
            Method::GET,
            "/passkey/generate-register-options",
            Some(&passkey_user.token),
            None,
        )
        .await;
    report.record(
        "GET",
        "/passkey/generate-register-options",
        "/passkey/generate-register-options",
        "success",
        "generate passkey registration options",
        ExpectedStatus::OneOf(&[200]),
        &register_options,
    );

    let authenticate_options = suite
        .send(
            Method::POST,
            "/passkey/generate-authenticate-options",
            Some(&passkey_user.token),
            Some(json!({})),
        )
        .await;
    report.record(
        "POST",
        "/passkey/generate-authenticate-options",
        "/passkey/generate-authenticate-options",
        "success",
        "generate passkey authentication options",
        ExpectedStatus::OneOf(&[200]),
        &authenticate_options,
    );

    let verify_registration = suite
        .send(
            Method::POST,
            "/passkey/verify-registration",
            Some(&passkey_user.token),
            Some(json!({
                "id": "fake-credential-id",
                "rawId": "fake-raw-id",
                "response": {
                    "attestationObject": "fake",
                    "clientDataJSON": "fake"
                },
                "type": "public-key"
            })),
        )
        .await;
    report.record(
        "POST",
        "/passkey/verify-registration",
        "/passkey/verify-registration",
        "handled-error",
        "reject fake passkey registration payload",
        ExpectedStatus::Range(400, 499),
        &verify_registration,
    );

    let verify_authentication = suite
        .send(
            Method::POST,
            "/passkey/verify-authentication",
            Some(&passkey_user.token),
            Some(json!({
                "id": "fake-credential-id",
                "rawId": "fake-raw-id",
                "response": {
                    "authenticatorData": "fake",
                    "clientDataJSON": "fake",
                    "signature": "fake"
                },
                "type": "public-key"
            })),
        )
        .await;
    report.record(
        "POST",
        "/passkey/verify-authentication",
        "/passkey/verify-authentication",
        "handled-error",
        "reject fake passkey authentication payload",
        ExpectedStatus::Range(400, 499),
        &verify_authentication,
    );

    let list_passkeys = suite
        .send(
            Method::GET,
            "/passkey/list-user-passkeys",
            Some(&passkey_user.token),
            None,
        )
        .await;
    report.record(
        "GET",
        "/passkey/list-user-passkeys",
        "/passkey/list-user-passkeys",
        "success",
        "list current user's passkeys",
        ExpectedStatus::OneOf(&[200]),
        &list_passkeys,
    );

    let update_passkey = suite
        .send(
            Method::POST,
            "/passkey/update-passkey",
            Some(&passkey_user.token),
            Some(json!({
                "id": "missing-passkey",
                "name": "Updated Passkey"
            })),
        )
        .await;
    report.record(
        "POST",
        "/passkey/update-passkey",
        "/passkey/update-passkey",
        "handled-error",
        "attempt to update a non-existent passkey",
        ExpectedStatus::OneOf(&[200, 400, 404]),
        &update_passkey,
    );

    let delete_passkey = suite
        .send(
            Method::POST,
            "/passkey/delete-passkey",
            Some(&passkey_user.token),
            Some(json!({
                "id": "missing-passkey"
            })),
        )
        .await;
    report.record(
        "POST",
        "/passkey/delete-passkey",
        "/passkey/delete-passkey",
        "handled-error",
        "attempt to delete a non-existent passkey",
        ExpectedStatus::OneOf(&[200, 400, 404]),
        &delete_passkey,
    );
}

async fn exercise_api_key_routes(suite: &AxumRouteSuite, report: &mut RouteMatrixReport) {
    let api_user = suite.signup_user("matrix_api_key", "Matrix API Key").await;
    let create = suite
        .send(
            Method::POST,
            "/api-key/create",
            Some(&api_user.token),
            Some(json!({
                "name": "matrix-key",
                "prefix": "mk_"
            })),
        )
        .await;
    let api_key_id = create.body["id"].as_str().expect("api key id").to_string();
    let raw_key = create.body["key"]
        .as_str()
        .expect("raw api key")
        .to_string();
    report.record(
        "POST",
        "/api-key/create",
        "/api-key/create",
        "success",
        "create an API key",
        ExpectedStatus::OneOf(&[200]),
        &create,
    );

    let verify = suite
        .send(
            Method::POST,
            "/api-key/verify",
            None,
            Some(json!({
                "key": raw_key
            })),
        )
        .await;
    report.record(
        "POST",
        "/api-key/verify",
        "/api-key/verify",
        "success",
        "verify a valid API key",
        ExpectedStatus::OneOf(&[200]),
        &verify,
    );

    let list = suite
        .send(Method::GET, "/api-key/list", Some(&api_user.token), None)
        .await;
    report.record(
        "GET",
        "/api-key/list",
        "/api-key/list",
        "success",
        "list owned API keys",
        ExpectedStatus::OneOf(&[200]),
        &list,
    );

    let get = suite
        .send_raw(
            Method::GET,
            &format!("/api-key/get?id={api_key_id}"),
            Some(&api_user.token),
        )
        .await;
    report.record(
        "GET",
        "/api-key/get",
        format!("/api-key/get?id={api_key_id}"),
        "success",
        "fetch API key by id",
        ExpectedStatus::OneOf(&[200]),
        &get,
    );

    let update = suite
        .send(
            Method::POST,
            "/api-key/update",
            Some(&api_user.token),
            Some(json!({
                "id": api_key_id,
                "name": "matrix-key-updated",
                "enabled": true
            })),
        )
        .await;
    report.record(
        "POST",
        "/api-key/update",
        "/api-key/update",
        "success",
        "update API key metadata",
        ExpectedStatus::OneOf(&[200]),
        &update,
    );

    let expiring = suite
        .send(
            Method::POST,
            "/api-key/create",
            Some(&api_user.token),
            Some(json!({
                "name": "expiring-key"
            })),
        )
        .await;
    let expiring_id = expiring.body["id"]
        .as_str()
        .expect("expiring api key id")
        .to_string();
    suite
        .auth
        .database()
        .update_api_key(
            &expiring_id,
            UpdateApiKey {
                expires_at: Some(Some((Utc::now() - ChronoDuration::hours(1)).to_rfc3339())),
                ..Default::default()
            },
        )
        .await
        .expect("expire api key in db");
    let delete_expired = suite
        .send(
            Method::POST,
            "/api-key/delete-all-expired-api-keys",
            Some(&api_user.token),
            Some(json!({})),
        )
        .await;
    report.record(
        "POST",
        "/api-key/delete-all-expired-api-keys",
        "/api-key/delete-all-expired-api-keys",
        "success",
        "delete expired API keys",
        ExpectedStatus::OneOf(&[200]),
        &delete_expired,
    );

    let delete = suite
        .send(
            Method::POST,
            "/api-key/delete",
            Some(&api_user.token),
            Some(json!({
                "id": create.body["id"]
            })),
        )
        .await;
    report.record(
        "POST",
        "/api-key/delete",
        "/api-key/delete",
        "success",
        "delete API key by id",
        ExpectedStatus::OneOf(&[200]),
        &delete,
    );
}

async fn exercise_admin_routes(suite: &AxumRouteSuite, report: &mut RouteMatrixReport) {
    let admin = suite.create_bootstrap_admin().await;
    let target_user = suite
        .signup_user("matrix_admin_target", "Matrix Admin Target")
        .await;

    let list_users = suite
        .send(Method::GET, "/admin/list-users", Some(&admin.token), None)
        .await;
    report.record(
        "GET",
        "/admin/list-users",
        "/admin/list-users",
        "success",
        "list users as global admin",
        ExpectedStatus::OneOf(&[200]),
        &list_users,
    );

    let list_user_sessions = suite
        .send(
            Method::POST,
            "/admin/list-user-sessions",
            Some(&admin.token),
            Some(json!({
                "userId": target_user.user_id
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/list-user-sessions",
        "/admin/list-user-sessions",
        "success",
        "list sessions for a target user",
        ExpectedStatus::OneOf(&[200]),
        &list_user_sessions,
    );

    let set_role = suite
        .send(
            Method::POST,
            "/admin/set-role",
            Some(&admin.token),
            Some(json!({
                "userId": target_user.user_id,
                "role": "moderator"
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/set-role",
        "/admin/set-role",
        "success",
        "change a user's global role",
        ExpectedStatus::OneOf(&[200]),
        &set_role,
    );

    let has_permission = suite
        .send(
            Method::POST,
            "/admin/has-permission",
            Some(&admin.token),
            Some(json!({
                "permissions": {
                    "user": ["create"]
                }
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/has-permission",
        "/admin/has-permission",
        "success",
        "evaluate admin permission access",
        ExpectedStatus::OneOf(&[200]),
        &has_permission,
    );

    let create_user = suite
        .send(
            Method::POST,
            "/admin/create-user",
            Some(&admin.token),
            Some(json!({
                "email": unique_email("matrix_admin_created"),
                "password": "password123",
                "name": "Matrix Admin Created",
                "role": "member"
            })),
        )
        .await;
    let created_user_id = create_user.body["user"]["id"]
        .as_str()
        .expect("created user id")
        .to_string();
    report.record(
        "POST",
        "/admin/create-user",
        "/admin/create-user",
        "success",
        "create a user as admin",
        ExpectedStatus::OneOf(&[200]),
        &create_user,
    );

    let set_user_password = suite
        .send(
            Method::POST,
            "/admin/set-user-password",
            Some(&admin.token),
            Some(json!({
                "userId": target_user.user_id,
                "newPassword": "AdminChangedPassword123!"
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/set-user-password",
        "/admin/set-user-password",
        "success",
        "set a target user's password",
        ExpectedStatus::OneOf(&[200]),
        &set_user_password,
    );

    let target_reauth = suite
        .send(
            Method::POST,
            "/sign-in/email",
            None,
            Some(json!({
                "email": target_user.email,
                "password": "AdminChangedPassword123!"
            })),
        )
        .await;
    let target_fresh_token = target_reauth.body["token"]
        .as_str()
        .expect("target fresh token")
        .to_string();
    let extra_target_session = suite
        .send(
            Method::POST,
            "/sign-in/email",
            None,
            Some(json!({
                "email": target_user.email,
                "password": "AdminChangedPassword123!"
            })),
        )
        .await;
    let extra_target_token = extra_target_session.body["token"]
        .as_str()
        .expect("extra target token")
        .to_string();

    let ban_user = suite
        .send(
            Method::POST,
            "/admin/ban-user",
            Some(&admin.token),
            Some(json!({
                "userId": target_user.user_id,
                "banReason": "matrix-test"
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/ban-user",
        "/admin/ban-user",
        "success",
        "ban a user and revoke sessions",
        ExpectedStatus::OneOf(&[200]),
        &ban_user,
    );

    let unban_user = suite
        .send(
            Method::POST,
            "/admin/unban-user",
            Some(&admin.token),
            Some(json!({
                "userId": target_user.user_id
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/unban-user",
        "/admin/unban-user",
        "success",
        "remove a user's ban",
        ExpectedStatus::OneOf(&[200]),
        &unban_user,
    );

    let session_reauth = suite
        .send(
            Method::POST,
            "/sign-in/email",
            None,
            Some(json!({
                "email": target_user.email,
                "password": "AdminChangedPassword123!"
            })),
        )
        .await;
    let session_token_for_admin_revoke = session_reauth.body["token"]
        .as_str()
        .expect("target token for admin revoke")
        .to_string();

    let revoke_user_session = suite
        .send(
            Method::POST,
            "/admin/revoke-user-session",
            Some(&admin.token),
            Some(json!({
                "sessionToken": session_token_for_admin_revoke
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/revoke-user-session",
        "/admin/revoke-user-session",
        "success",
        "revoke one specific target session",
        ExpectedStatus::OneOf(&[200]),
        &revoke_user_session,
    );

    let target_again = suite
        .send(
            Method::POST,
            "/sign-in/email",
            None,
            Some(json!({
                "email": target_user.email,
                "password": "AdminChangedPassword123!"
            })),
        )
        .await;
    let revoke_all_user_token = target_again.body["token"]
        .as_str()
        .expect("token for revoke-user-sessions")
        .to_string();
    let revoke_user_sessions = suite
        .send(
            Method::POST,
            "/admin/revoke-user-sessions",
            Some(&admin.token),
            Some(json!({
                "userId": target_user.user_id
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/revoke-user-sessions",
        "/admin/revoke-user-sessions",
        "success",
        "revoke every session for a target user",
        ExpectedStatus::OneOf(&[200]),
        &revoke_user_sessions,
    );

    let impersonation_target = suite
        .signup_user("matrix_impersonation", "Matrix Impersonation")
        .await;
    let impersonate = suite
        .send(
            Method::POST,
            "/admin/impersonate-user",
            Some(&admin.token),
            Some(json!({
                "userId": impersonation_target.user_id
            })),
        )
        .await;
    let impersonation_token = impersonate.body["session"]["token"]
        .as_str()
        .expect("impersonation token")
        .to_string();
    report.record(
        "POST",
        "/admin/impersonate-user",
        "/admin/impersonate-user",
        "success",
        "create an impersonation session",
        ExpectedStatus::OneOf(&[200]),
        &impersonate,
    );

    let stop_impersonating = suite
        .send(
            Method::POST,
            "/admin/stop-impersonating",
            Some(&impersonation_token),
            Some(json!({})),
        )
        .await;
    report.record(
        "POST",
        "/admin/stop-impersonating",
        "/admin/stop-impersonating",
        "success",
        "restore a normal admin session",
        ExpectedStatus::OneOf(&[200]),
        &stop_impersonating,
    );

    let admin_api_key = suite
        .send(
            Method::POST,
            "/admin/api-key/create",
            Some(&admin.token),
            Some(json!({
                "name": "matrix-admin-key"
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/api-key/create",
        "/admin/api-key/create",
        "success",
        "create admin-scoped API key",
        ExpectedStatus::OneOf(&[200]),
        &admin_api_key,
    );

    let athena_client_create = suite
        .send(
            Method::POST,
            "/admin/athena-client/create",
            Some(&admin.token),
            Some(json!({
                "clientName": "matrix-athena-client"
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/athena-client/create",
        "/admin/athena-client/create",
        "success",
        "create athena client metadata",
        ExpectedStatus::OneOf(&[200]),
        &athena_client_create,
    );

    let athena_client_list = suite
        .send(
            Method::GET,
            "/admin/athena-client/list",
            Some(&admin.token),
            None,
        )
        .await;
    report.record(
        "GET",
        "/admin/athena-client/list",
        "/admin/athena-client/list",
        "success",
        "list athena clients",
        ExpectedStatus::OneOf(&[200]),
        &athena_client_list,
    );

    let oauth_client_create = suite
        .send(
            Method::POST,
            "/admin/oauth-client/create",
            Some(&admin.token),
            Some(json!({
                "clientName": "matrix-admin-oauth-client",
                "provider": "test",
                "redirectUris": [format!("{TEST_ORIGIN}/session")]
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/oauth-client/create",
        "/admin/oauth-client/create",
        "success",
        "create oauth client registration",
        ExpectedStatus::OneOf(&[200]),
        &oauth_client_create,
    );

    let oauth_client_list = suite
        .send(
            Method::GET,
            "/admin/oauth-client/list",
            Some(&admin.token),
            None,
        )
        .await;
    report.record(
        "GET",
        "/admin/oauth-client/list",
        "/admin/oauth-client/list",
        "success",
        "list oauth clients",
        ExpectedStatus::OneOf(&[200]),
        &oauth_client_list,
    );

    let audit_log_list = suite
        .send(
            Method::GET,
            "/admin/audit-log/list",
            Some(&admin.token),
            None,
        )
        .await;
    report.record(
        "GET",
        "/admin/audit-log/list",
        "/admin/audit-log/list",
        "success",
        "list admin audit records",
        ExpectedStatus::OneOf(&[200]),
        &audit_log_list,
    );

    let email_create = suite
        .send(
            Method::POST,
            "/admin/email/create",
            Some(&admin.token),
            Some(json!({
                "recipientEmail": unique_email("matrix_email_recipient"),
                "subject": "Matrix Email",
                "fromAddress": "noreply@example.com",
                "fromName": "Matrix",
                "textBody": "hello",
                "provider": "test-provider"
            })),
        )
        .await;
    let email_id = email_create.body["email"]["id"]
        .as_str()
        .expect("sent email id")
        .to_string();
    report.record(
        "POST",
        "/admin/email/create",
        "/admin/email/create",
        "success",
        "create an email admin record",
        ExpectedStatus::OneOf(&[200]),
        &email_create,
    );

    let email_list = suite
        .send(Method::GET, "/admin/email/list", Some(&admin.token), None)
        .await;
    report.record(
        "GET",
        "/admin/email/list",
        "/admin/email/list",
        "success",
        "list email admin records",
        ExpectedStatus::OneOf(&[200]),
        &email_list,
    );

    let email_get = suite
        .send_raw(
            Method::GET,
            &format!("/admin/email/get?id={email_id}"),
            Some(&admin.token),
        )
        .await;
    report.record(
        "GET",
        "/admin/email/get",
        format!("/admin/email/get?id={email_id}"),
        "success",
        "get email admin record",
        ExpectedStatus::OneOf(&[200]),
        &email_get,
    );

    let email_update = suite
        .send(
            Method::POST,
            "/admin/email/update",
            Some(&admin.token),
            Some(json!({
                "id": email_id,
                "subject": "Matrix Email Updated"
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/email/update",
        "/admin/email/update",
        "success",
        "update email admin record",
        ExpectedStatus::OneOf(&[200]),
        &email_update,
    );

    let email_delete = suite
        .send(
            Method::POST,
            "/admin/email/delete",
            Some(&admin.token),
            Some(json!({
                "id": email_create.body["email"]["id"]
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/email/delete",
        "/admin/email/delete",
        "success",
        "delete email admin record",
        ExpectedStatus::OneOf(&[200]),
        &email_delete,
    );

    let failure_create = suite
        .send(
            Method::POST,
            "/admin/email-failure/create",
            Some(&admin.token),
            Some(json!({
                "recipientEmail": unique_email("matrix_failure"),
                "flow": "matrix_flow",
                "provider": "smtp",
                "errorMessage": "simulated failure"
            })),
        )
        .await;
    let failure_id = failure_create.body["emailSendFailure"]["id"]
        .as_str()
        .expect("email failure id")
        .to_string();
    report.record(
        "POST",
        "/admin/email-failure/create",
        "/admin/email-failure/create",
        "success",
        "create email failure record",
        ExpectedStatus::OneOf(&[200]),
        &failure_create,
    );

    let failure_list = suite
        .send(
            Method::GET,
            "/admin/email-failure/list",
            Some(&admin.token),
            None,
        )
        .await;
    report.record(
        "GET",
        "/admin/email-failure/list",
        "/admin/email-failure/list",
        "success",
        "list email failures",
        ExpectedStatus::OneOf(&[200]),
        &failure_list,
    );

    let failure_get = suite
        .send_raw(
            Method::GET,
            &format!("/admin/email-failure/get?id={failure_id}"),
            Some(&admin.token),
        )
        .await;
    report.record(
        "GET",
        "/admin/email-failure/get",
        format!("/admin/email-failure/get?id={failure_id}"),
        "success",
        "get email failure record",
        ExpectedStatus::OneOf(&[200]),
        &failure_get,
    );

    let failure_update = suite
        .send(
            Method::POST,
            "/admin/email-failure/update",
            Some(&admin.token),
            Some(json!({
                "id": failure_id,
                "resolved": true,
                "resolutionNote": "handled in matrix test"
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/email-failure/update",
        "/admin/email-failure/update",
        "success",
        "update email failure resolution",
        ExpectedStatus::OneOf(&[200]),
        &failure_update,
    );

    let failure_delete = suite
        .send(
            Method::POST,
            "/admin/email-failure/delete",
            Some(&admin.token),
            Some(json!({
                "id": failure_create.body["emailSendFailure"]["id"]
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/email-failure/delete",
        "/admin/email-failure/delete",
        "success",
        "delete email failure record",
        ExpectedStatus::OneOf(&[200]),
        &failure_delete,
    );

    let template_create = suite
        .send(
            Method::POST,
            "/admin/email-template/create",
            Some(&admin.token),
            Some(json!({
                "templateKey": unique_slug("matrix-template"),
                "subjectTemplate": "Matrix subject",
                "textTemplate": "Matrix body"
            })),
        )
        .await;
    let template_id = template_create.body["id"]
        .as_str()
        .expect("template id")
        .to_string();
    let template_key = template_create.body["templateKey"]
        .as_str()
        .expect("template key")
        .to_string();
    report.record(
        "POST",
        "/admin/email-template/create",
        "/admin/email-template/create",
        "success",
        "create email template",
        ExpectedStatus::OneOf(&[200]),
        &template_create,
    );

    let template_list = suite
        .send_raw(
            Method::GET,
            &format!("/admin/email-template/list?templateKey={template_key}"),
            Some(&admin.token),
        )
        .await;
    report.record(
        "GET",
        "/admin/email-template/list",
        format!("/admin/email-template/list?templateKey={template_key}"),
        "success",
        "list email templates",
        ExpectedStatus::OneOf(&[200]),
        &template_list,
    );

    let template_get = suite
        .send_raw(
            Method::GET,
            &format!("/admin/email-template/get?id={template_id}"),
            Some(&admin.token),
        )
        .await;
    report.record(
        "GET",
        "/admin/email-template/get",
        format!("/admin/email-template/get?id={template_id}"),
        "success",
        "get email template by id",
        ExpectedStatus::OneOf(&[200]),
        &template_get,
    );

    let template_update = suite
        .send(
            Method::POST,
            "/admin/email-template/update",
            Some(&admin.token),
            Some(json!({
                "id": template_id,
                "subjectTemplate": "Matrix subject updated"
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/email-template/update",
        "/admin/email-template/update",
        "success",
        "update email template",
        ExpectedStatus::OneOf(&[200]),
        &template_update,
    );

    let template_delete = suite
        .send(
            Method::POST,
            "/admin/email-template/delete",
            Some(&admin.token),
            Some(json!({
                "id": template_create.body["id"]
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/email-template/delete",
        "/admin/email-template/delete",
        "success",
        "delete email template",
        ExpectedStatus::OneOf(&[200]),
        &template_delete,
    );

    let event_type_list = suite
        .send(
            Method::GET,
            "/admin/email-event-type/list",
            Some(&admin.token),
            None,
        )
        .await;
    report.record(
        "GET",
        "/admin/email-event-type/list",
        "/admin/email-event-type/list",
        "success",
        "list email event type catalog",
        ExpectedStatus::OneOf(&[200]),
        &event_type_list,
    );

    let remove_user = suite
        .send(
            Method::POST,
            "/admin/remove-user",
            Some(&admin.token),
            Some(json!({
                "userId": created_user_id
            })),
        )
        .await;
    report.record(
        "POST",
        "/admin/remove-user",
        "/admin/remove-user",
        "success",
        "delete a user via admin endpoint",
        ExpectedStatus::OneOf(&[200]),
        &remove_user,
    );

    let _ = extra_target_token;
    let _ = revoke_all_user_token;
    let _ = target_fresh_token;
}

async fn exercise_organization_routes(suite: &AxumRouteSuite, report: &mut RouteMatrixReport) {
    let owner = suite
        .signup_user("matrix_org_owner", "Matrix Org Owner")
        .await;
    let invitee = suite
        .signup_user("matrix_org_invitee", "Matrix Org Invitee")
        .await;
    suite.mark_email_verified(&invitee.email).await;

    let create_org = suite
        .send(
            Method::POST,
            "/organization/create",
            Some(&owner.token),
            Some(json!({
                "name": "Matrix Organization",
                "slug": "matrix-organization"
            })),
        )
        .await;
    let org_id = create_org.body["id"]
        .as_str()
        .expect("organization id")
        .to_string();
    report.record(
        "POST",
        "/organization/create",
        "/organization/create",
        "success",
        "create organization",
        ExpectedStatus::OneOf(&[200]),
        &create_org,
    );

    let check_slug = suite
        .send(
            Method::POST,
            "/organization/check-slug",
            Some(&owner.token),
            Some(json!({
                "slug": "matrix-organization"
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/check-slug",
        "/organization/check-slug",
        "success",
        "check organization slug availability",
        ExpectedStatus::OneOf(&[200]),
        &check_slug,
    );

    let list_orgs = suite
        .send(Method::GET, "/organization/list", Some(&owner.token), None)
        .await;
    report.record(
        "GET",
        "/organization/list",
        "/organization/list",
        "success",
        "list organizations for current user",
        ExpectedStatus::OneOf(&[200]),
        &list_orgs,
    );

    let update_org = suite
        .send(
            Method::POST,
            "/organization/update",
            Some(&owner.token),
            Some(json!({
                "organizationId": org_id,
                "name": "Matrix Organization Updated"
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/update",
        "/organization/update",
        "success",
        "update organization metadata",
        ExpectedStatus::OneOf(&[200]),
        &update_org,
    );

    let set_active_owner = suite
        .send(
            Method::POST,
            "/organization/set-active",
            Some(&owner.token),
            Some(json!({
                "organizationSlug": "matrix-organization"
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/set-active",
        "/organization/set-active",
        "success",
        "activate organization context for owner",
        ExpectedStatus::OneOf(&[200]),
        &set_active_owner,
    );

    let get_full = suite
        .send_raw(
            Method::GET,
            "/organization/get-full-organization?organizationSlug=matrix-organization",
            Some(&owner.token),
        )
        .await;
    report.record(
        "GET",
        "/organization/get-full-organization",
        "/organization/get-full-organization?organizationSlug=matrix-organization",
        "success",
        "load full organization view",
        ExpectedStatus::OneOf(&[200]),
        &get_full,
    );

    let get_active_member = suite
        .send(
            Method::GET,
            "/organization/get-active-member",
            Some(&owner.token),
            None,
        )
        .await;
    report.record(
        "GET",
        "/organization/get-active-member",
        "/organization/get-active-member",
        "success",
        "get active member for current user",
        ExpectedStatus::OneOf(&[200]),
        &get_active_member,
    );

    let has_permission = suite
        .send(
            Method::POST,
            "/organization/has-permission",
            Some(&owner.token),
            Some(json!({
                "permissions": {
                    "member": ["create"]
                }
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/has-permission",
        "/organization/has-permission",
        "success",
        "check owner organization permissions",
        ExpectedStatus::OneOf(&[200]),
        &has_permission,
    );

    let invite_member = suite
        .send(
            Method::POST,
            "/organization/invite-member",
            Some(&owner.token),
            Some(json!({
                "email": invitee.email,
                "role": "member"
            })),
        )
        .await;
    let invitation_id = invite_member.body["id"]
        .as_str()
        .expect("invitation id")
        .to_string();
    report.record(
        "POST",
        "/organization/invite-member",
        "/organization/invite-member",
        "success",
        "invite member into organization",
        ExpectedStatus::OneOf(&[200]),
        &invite_member,
    );

    let get_invitation = suite
        .send_raw(
            Method::GET,
            &format!("/organization/get-invitation?id={invitation_id}"),
            Some(&owner.token),
        )
        .await;
    report.record(
        "GET",
        "/organization/get-invitation",
        format!("/organization/get-invitation?id={invitation_id}"),
        "success",
        "get invitation details",
        ExpectedStatus::OneOf(&[200]),
        &get_invitation,
    );

    let list_invitations = suite
        .send(
            Method::GET,
            "/organization/list-invitations",
            Some(&owner.token),
            None,
        )
        .await;
    report.record(
        "GET",
        "/organization/list-invitations",
        "/organization/list-invitations",
        "success",
        "list active organization invitations",
        ExpectedStatus::OneOf(&[200]),
        &list_invitations,
    );

    let list_user_invitations = suite
        .send(
            Method::GET,
            "/organization/list-user-invitations",
            Some(&invitee.token),
            None,
        )
        .await;
    report.record(
        "GET",
        "/organization/list-user-invitations",
        "/organization/list-user-invitations",
        "success",
        "list invitations visible to invitee",
        ExpectedStatus::OneOf(&[200]),
        &list_user_invitations,
    );

    let accept_invitation = suite
        .send(
            Method::POST,
            "/organization/accept-invitation",
            Some(&invitee.token),
            Some(json!({
                "invitationId": invitation_id
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/accept-invitation",
        "/organization/accept-invitation",
        "success",
        "accept organization invitation",
        ExpectedStatus::OneOf(&[200]),
        &accept_invitation,
    );

    let list_members = suite
        .send_raw(
            Method::GET,
            "/organization/list-members?organizationSlug=matrix-organization",
            Some(&owner.token),
        )
        .await;
    report.record(
        "GET",
        "/organization/list-members",
        "/organization/list-members?organizationSlug=matrix-organization",
        "success",
        "list organization members",
        ExpectedStatus::OneOf(&[200]),
        &list_members,
    );

    let full_after_accept = suite
        .send_raw(
            Method::GET,
            "/organization/get-full-organization?organizationSlug=matrix-organization",
            Some(&owner.token),
        )
        .await;
    let members = full_after_accept.body["members"]
        .as_array()
        .expect("members array");
    let invitee_member_id = members
        .iter()
        .find(|member| member["user"]["email"].as_str() == Some(&invitee.email))
        .and_then(|member| member["id"].as_str())
        .expect("invitee member id")
        .to_string();

    let update_member_role = suite
        .send(
            Method::POST,
            "/organization/update-member-role",
            Some(&owner.token),
            Some(json!({
                "memberId": invitee_member_id,
                "role": "admin"
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/update-member-role",
        "/organization/update-member-role",
        "success",
        "promote accepted member",
        ExpectedStatus::OneOf(&[200]),
        &update_member_role,
    );

    let second_member = suite
        .signup_user("matrix_org_member2", "Matrix Org Member Two")
        .await;
    suite.mark_email_verified(&second_member.email).await;
    let second_invite = suite
        .send(
            Method::POST,
            "/organization/invite-member",
            Some(&owner.token),
            Some(json!({
                "email": second_member.email,
                "role": "member"
            })),
        )
        .await;
    let second_invitation_id = second_invite.body["id"]
        .as_str()
        .expect("second invitation id")
        .to_string();
    let _ = suite
        .send(
            Method::POST,
            "/organization/accept-invitation",
            Some(&second_member.token),
            Some(json!({
                "invitationId": second_invitation_id
            })),
        )
        .await;
    let full_with_second_member = suite
        .send_raw(
            Method::GET,
            "/organization/get-full-organization?organizationSlug=matrix-organization",
            Some(&owner.token),
        )
        .await;
    let second_member_id = full_with_second_member.body["members"]
        .as_array()
        .expect("members array")
        .iter()
        .find(|member| member["user"]["email"].as_str() == Some(&second_member.email))
        .and_then(|member| member["id"].as_str())
        .expect("second member id")
        .to_string();

    let remove_member = suite
        .send(
            Method::POST,
            "/organization/remove-member",
            Some(&owner.token),
            Some(json!({
                "memberId": second_member_id
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/remove-member",
        "/organization/remove-member",
        "success",
        "remove another member from organization",
        ExpectedStatus::OneOf(&[200]),
        &remove_member,
    );

    let reject_user = suite
        .signup_user("matrix_org_reject", "Matrix Org Reject")
        .await;
    suite.mark_email_verified(&reject_user.email).await;
    let reject_invite = suite
        .send(
            Method::POST,
            "/organization/invite-member",
            Some(&owner.token),
            Some(json!({
                "email": reject_user.email,
                "role": "member"
            })),
        )
        .await;
    let reject_invitation_id = reject_invite.body["id"]
        .as_str()
        .expect("reject invitation id")
        .to_string();
    let reject_invitation = suite
        .send(
            Method::POST,
            "/organization/reject-invitation",
            Some(&reject_user.token),
            Some(json!({
                "invitationId": reject_invitation_id
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/reject-invitation",
        "/organization/reject-invitation",
        "success",
        "reject organization invitation",
        ExpectedStatus::OneOf(&[200]),
        &reject_invitation,
    );

    let cancel_user = suite
        .signup_user("matrix_org_cancel", "Matrix Org Cancel")
        .await;
    suite.mark_email_verified(&cancel_user.email).await;
    let cancel_invite = suite
        .send(
            Method::POST,
            "/organization/invite-member",
            Some(&owner.token),
            Some(json!({
                "email": cancel_user.email,
                "role": "member"
            })),
        )
        .await;
    let cancel_invitation_id = cancel_invite.body["id"]
        .as_str()
        .expect("cancel invitation id")
        .to_string();
    let cancel_invitation = suite
        .send(
            Method::POST,
            "/organization/cancel-invitation",
            Some(&owner.token),
            Some(json!({
                "invitationId": cancel_invitation_id
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/cancel-invitation",
        "/organization/cancel-invitation",
        "success",
        "cancel a pending organization invitation",
        ExpectedStatus::OneOf(&[200]),
        &cancel_invitation,
    );

    let set_active_member = suite
        .send(
            Method::POST,
            "/organization/set-active",
            Some(&invitee.token),
            Some(json!({
                "organizationSlug": "matrix-organization"
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/set-active",
        "/organization/set-active",
        "success",
        "activate organization context for accepted member",
        ExpectedStatus::OneOf(&[200]),
        &set_active_member,
    );

    let leave_org = suite
        .send(
            Method::POST,
            "/organization/leave",
            Some(&invitee.token),
            Some(json!({
                "organizationId": org_id
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/leave",
        "/organization/leave",
        "success",
        "leave active organization",
        ExpectedStatus::OneOf(&[200]),
        &leave_org,
    );

    let delete_org = suite
        .send(
            Method::POST,
            "/organization/delete",
            Some(&owner.token),
            Some(json!({
                "organizationId": org_id
            })),
        )
        .await;
    report.record(
        "POST",
        "/organization/delete",
        "/organization/delete",
        "success",
        "delete organization",
        ExpectedStatus::OneOf(&[200]),
        &delete_org,
    );
}

fn render_markdown_report(
    report: &RouteMatrixReport,
    implemented_routes: &BTreeSet<String>,
    documented_routes: &BTreeSet<String>,
) -> String {
    let exercised_routes = report.exercised_route_keys();
    let missing_implemented = implemented_routes
        .difference(&exercised_routes)
        .cloned()
        .collect::<Vec<_>>();
    let undocumented_implemented = implemented_routes
        .difference(documented_routes)
        .cloned()
        .collect::<Vec<_>>();
    let undocumented_exercised = exercised_routes
        .difference(documented_routes)
        .cloned()
        .collect::<Vec<_>>();

    let passed = report.entries.iter().filter(|entry| entry.passed).count();
    let failed = report.entries.len().saturating_sub(passed);

    let mut output = String::new();
    output.push_str("# Axum Route Matrix Report\n\n");
    output.push_str(&format!(
        "- Implemented routes: {}\n- Documented routes: {}\n- Exercised routes: {}\n- Passed scenarios: {}\n- Failed scenarios: {}\n\n",
        implemented_routes.len(),
        documented_routes.len(),
        exercised_routes.len(),
        passed,
        failed
    ));

    if !missing_implemented.is_empty() {
        output.push_str("## Missing Implemented Routes\n\n");
        for route in &missing_implemented {
            output.push_str(&format!("- {route}\n"));
        }
        output.push('\n');
    }

    if !undocumented_implemented.is_empty() {
        output.push_str("## Implemented But Undocumented Routes\n\n");
        for route in &undocumented_implemented {
            output.push_str(&format!("- {route}\n"));
        }
        output.push('\n');
    }

    if !undocumented_exercised.is_empty() {
        output.push_str("## Exercised Undocumented Routes\n\n");
        for route in &undocumented_exercised {
            output.push_str(&format!("- {route}\n"));
        }
        output.push('\n');
    }

    output.push_str("## Scenario Results\n\n");
    output.push_str("| Status | Method | Route | Mode | Expected | Actual | Note |\n");
    output.push_str("| --- | --- | --- | --- | --- | --- | --- |\n");
    for entry in &report.entries {
        let marker = if entry.passed { "PASS" } else { "FAIL" };
        output.push_str(&format!(
            "| {marker} | {} | `{}` | {} | `{}` | `{}` | {} |\n",
            entry.method, entry.route, entry.mode, entry.expected, entry.status, entry.note
        ));
    }

    output.push_str("\n## Response Previews\n\n");
    for entry in &report.entries {
        output.push_str(&format!(
            "- `{}` `{}` -> `{}` [{}] {}\n",
            entry.method, entry.route, entry.actual_path, entry.status, entry.body_preview
        ));
    }

    output
}

#[tokio::test]
async fn test_axum_route_matrix_exercises_every_implemented_route() {
    let suite = AxumRouteSuite::new().await;
    let mut report = RouteMatrixReport::default();

    exercise_auth_and_public_routes(&suite, &mut report).await;
    exercise_oauth_routes(&suite, &mut report).await;
    exercise_two_factor_and_passkey_routes(&suite, &mut report).await;
    exercise_api_key_routes(&suite, &mut report).await;
    exercise_admin_routes(&suite, &mut report).await;
    exercise_organization_routes(&suite, &mut report).await;

    let implemented_routes = suite.implemented_route_keys().await;
    let documented_routes = documented_route_keys();
    let exercised_routes = report.exercised_route_keys();
    let missing_implemented = implemented_routes
        .difference(&exercised_routes)
        .cloned()
        .collect::<Vec<_>>();
    if !missing_implemented.is_empty() {
        report.failures.push(format!(
            "Missing implemented route scenarios: {}",
            missing_implemented.join(", ")
        ));
    }

    let markdown = render_markdown_report(&report, &implemented_routes, &documented_routes);
    let report_path =
        std::path::Path::new("compat-tests/reports/axum-route-matrix-report.md").to_path_buf();
    if let Some(parent) = report_path.parent() {
        std::fs::create_dir_all(parent).expect("create report directory");
    }
    std::fs::write(&report_path, markdown).expect("write route matrix report");

    assert!(
        report.failures.is_empty(),
        "Axum route matrix failures:\n{}\n\nReport: {}",
        report.failures.join("\n"),
        report_path.display()
    );
}
