#![recursion_limit = "512"]
mod cli;
mod config;
mod db;
mod domain;
mod error;
mod handlers;
mod infra;
mod repositories;
mod runtime_health;
mod services;
mod smtp;
mod utils;
mod workers;

use axum::{
    http::{HeaderValue, Method},
    middleware,
    routing::{delete, get, patch, post},
    Router,
};
use clap::Parser;
use cli::CliArgs;
use std::time::Duration;
use tower::limit::ConcurrencyLimitLayer;
use tower_http::{
    catch_panic::CatchPanicLayer, cors::CorsLayer, limit::RequestBodyLimitLayer,
    timeout::TimeoutLayer,
};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

#[derive(Clone)]
pub struct AppState {
    pub pool: db::DbPool,
    pub config: config::app::AppConfig,
    pub redis_client: Option<infra::redis::redis_client::RedisClient>,
    pub mail_hub: smtp::MailHub,
    pub runtime_health: runtime_health::RuntimeHealth,
}

fn cors_layer(config: &config::server::ServerConfig) -> anyhow::Result<CorsLayer> {
    let origins = config
        .cors_origins
        .iter()
        .map(|v| HeaderValue::from_str(v))
        .collect::<Result<Vec<_>, _>>()?;
    Ok(CorsLayer::new()
        .allow_origin(origins)
        .allow_methods([
            Method::GET,
            Method::POST,
            Method::PUT,
            Method::PATCH,
            Method::DELETE,
        ])
        .allow_headers(tower_http::cors::Any))
}

fn build_router(state: AppState) -> anyhow::Result<Router> {
    let mut public = Router::new()
        .route("/health", get(handlers::health::health_check))
        .route("/info", get(handlers::health::server_info))
        .route("/auth/register", post(handlers::auth::register))
        .route("/auth/login", post(handlers::auth::login))
        .route("/auth/refresh", post(handlers::auth::refresh));
    if state.config.email.enabled {
        public = public
            .route(
                "/auth/request-verification-code",
                post(handlers::email::send_verification_code),
            )
            .route(
                "/auth/reset-password",
                post(handlers::email::reset_password),
            );
    }
    let mut protected = Router::new()
        .route("/auth/logout", post(handlers::auth::delete_refresh_token))
        .route(
            "/auth/delete-refresh-token",
            post(handlers::auth::delete_refresh_token),
        )
        .route("/auth/delete", post(handlers::auth::delete_account))
        .route(
            "/api/user/profile",
            get(handlers::user_profile::get_profile)
                .put(handlers::user_profile::update_profile)
                .delete(handlers::user_profile::delete_profile),
        )
        .route(
            "/api/mailboxes",
            post(handlers::mailbox::create_mailbox).get(handlers::mailbox::list_mailboxes),
        )
        .route(
            "/api/mailboxes/:id",
            delete(handlers::mailbox::delete_mailbox),
        )
        .route(
            "/api/mailboxes/:id/rotate-token",
            post(handlers::mailbox::rotate_token),
        )
        .route("/api/credits", get(handlers::credit::get_balance))
        .route("/api/credits/check-in", post(handlers::credit::check_in))
        .route(
            "/api/credits/transactions",
            get(handlers::credit::list_transactions),
        );
    if state.config.email.enabled {
        protected = protected
            .route("/api/email/latest-log", get(handlers::email::latest_log))
            .route(
                "/api/email/queue-status",
                get(handlers::email::queue_status),
            );
    }
    protected = protected.route_layer(middleware::from_fn_with_state(
        state.clone(),
        infra::middleware::auth::auth_middleware,
    ));

    // 邮箱级 access_token 保护路由（查邮件 / WebSocket）
    let mailbox_protected = Router::new()
        .route(
            "/api/mailboxes/:id/emails",
            get(handlers::mailbox::list_emails),
        )
        .route(
            "/api/mailboxes/:id/emails/:eid",
            get(handlers::mailbox::get_email).delete(handlers::mailbox::delete_email),
        )
        .route(
            "/api/mailboxes/:id/emails/:eid/attachments/:aid",
            get(handlers::mailbox::get_attachment),
        )
        .route(
            "/api/mailboxes/:id/ws",
            get(handlers::mailbox::ws_subscribe),
        )
        .route_layer(middleware::from_fn_with_state(
            state.clone(),
            infra::middleware::mailbox_auth::mailbox_auth_middleware,
        ));

    // 管理后台路由（用户 JWT + admin 角色）
    let admin_routes = Router::new()
        .route("/admin/overview", get(handlers::admin_governance::overview))
        .route("/admin/users", get(handlers::admin_governance::list_users))
        .route(
            "/admin/users/bulk-actions",
            post(handlers::admin_governance::bulk_users),
        )
        .route("/admin/users/:id", patch(handlers::admin::update_user))
        .route(
            "/admin/mailboxes",
            get(handlers::admin_governance::list_mailboxes),
        )
        .route(
            "/admin/mailboxes/bulk-actions",
            post(handlers::admin_governance::bulk_mailboxes),
        )
        .route(
            "/admin/emails",
            get(handlers::admin_governance::list_emails),
        )
        .route(
            "/admin/emails/bulk-actions",
            post(handlers::admin_governance::bulk_emails),
        )
        .route(
            "/admin/emails/:id",
            get(handlers::admin_governance::get_email_detail),
        )
        .route(
            "/admin/emails/:id/attachments/:attachment_id",
            get(handlers::admin_governance::get_email_attachment),
        )
        .route(
            "/admin/blacklists/senders",
            get(handlers::admin_governance::list_sender_blacklists)
                .post(handlers::admin_governance::add_sender_blacklist),
        )
        .route(
            "/admin/blacklists/senders/bulk-actions",
            post(handlers::admin_governance::bulk_sender_blacklists),
        )
        .route(
            "/admin/blacklists/ips",
            get(handlers::admin_governance::list_ip_blacklists)
                .post(handlers::admin_governance::add_ip_blacklist),
        )
        .route(
            "/admin/blacklists/ips/bulk-actions",
            post(handlers::admin_governance::bulk_ip_blacklists),
        )
        .route(
            "/admin/audit-logs",
            get(handlers::admin_governance::list_audit_logs),
        )
        .route(
            "/admin/credit-transactions",
            get(handlers::admin_governance::list_credit_transactions),
        )
        .route(
            "/admin/email-logs",
            get(handlers::admin_governance::list_email_logs),
        )
        .route(
            "/admin/credits/settings/history",
            get(handlers::admin_governance::list_credit_rule_changes),
        )
        .route(
            "/admin/blocked-senders",
            get(handlers::admin::list_blocked_senders).post(handlers::admin::add_blocked_sender),
        )
        .route(
            "/admin/blocked-senders/:id",
            delete(handlers::admin::delete_blocked_sender),
        )
        .route(
            "/admin/blocked-ips",
            get(handlers::admin::list_blocked_ips).post(handlers::admin::add_blocked_ip),
        )
        .route(
            "/admin/blocked-ips/:id",
            delete(handlers::admin::delete_blocked_ip),
        )
        .route("/admin/stats", get(handlers::admin::stats))
        .route(
            "/admin/credits/adjust",
            post(handlers::admin::adjust_credits),
        )
        .route(
            "/admin/credits/settings",
            get(handlers::admin::get_credit_settings).put(handlers::admin::update_credit_settings),
        )
        .route(
            "/admin/credits/settings/reset",
            post(handlers::admin::reset_credit_settings),
        )
        .route(
            "/admin/emails/quarantined",
            get(handlers::admin::list_quarantined_emails),
        )
        .route(
            "/admin/emails/:id/release",
            post(handlers::admin::release_email),
        )
        .route_layer(middleware::from_fn_with_state(
            state.clone(),
            infra::middleware::admin::require_admin,
        ))
        .route_layer(middleware::from_fn_with_state(
            state.clone(),
            infra::middleware::auth::auth_middleware,
        ));

    let limiter =
        infra::middleware::rate_limit::RateLimiter::new(state.config.server.rate_limit_per_minute);
    let server = state.config.server.clone();
    Ok(public
        .merge(protected)
        .merge(mailbox_protected)
        .merge(admin_routes)
        .fallback(infra::middleware::security::fallback_404)
        .method_not_allowed_fallback(infra::middleware::security::fallback_405)
        .layer(middleware::from_fn(
            infra::middleware::security::security_headers,
        ))
        .layer(middleware::from_fn(
            infra::middleware::language::language_middleware,
        ))
        .layer(cors_layer(&server)?)
        .layer(middleware::from_fn(
            infra::middleware::logging::request_logging_middleware,
        ))
        .layer(middleware::from_fn_with_state(
            limiter,
            infra::middleware::rate_limit::rate_limit_middleware,
        ))
        .layer(TimeoutLayer::new(Duration::from_secs(
            server.request_timeout_seconds,
        )))
        .layer(CatchPanicLayer::new())
        .layer(ConcurrencyLimitLayer::new(server.concurrency_limit))
        .layer(RequestBodyLimitLayer::new(server.max_body_bytes))
        .layer(middleware::from_fn_with_state(
            server.max_body_bytes,
            infra::middleware::body_limit::enforce_body_limit,
        ))
        .with_state(state))
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let args = CliArgs::parse();
    tracing_subscriber::registry()
        .with(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| args.get_log_filter().into()),
        )
        .with(tracing_subscriber::fmt::layer())
        .init();
    args.print_startup_info();
    if let Some(ref dir) = args.work_dir {
        std::env::set_current_dir(dir)?;
    }
    let config = config::app::AppConfig::load_with_overrides(
        args.resolve_config_path(),
        args.get_overrides(),
        args.env.as_str(),
    )?;
    let pool = db::init_database(&config.database).await?;
    let credit_rules =
        services::credit_rule_service::CreditRuleService::ensure_defaults(&pool).await?;
    let backfilled = services::credit_service::CreditService::backfill_missing_accounts(
        &pool,
        credit_rules.register_bonus,
    )
    .await?;
    if backfilled > 0 {
        tracing::info!(backfilled, "已为存量用户补建积分账户");
    }
    let redis_client = if config.redis.enabled {
        match infra::redis::redis_client::RedisClient::new(&config.redis.build_url()).await {
            Ok(client) => {
                tracing::info!("Redis connected");
                Some(client)
            }
            Err(error) => {
                tracing::warn!(%error, "Redis unavailable; dependent capabilities are disabled");
                None
            }
        }
    } else {
        None
    };
    let address = format!("{}:{}", config.server.host, config.server.port);
    let mail_hub = smtp::MailHub::new();
    let state = AppState {
        runtime_health: runtime_health::RuntimeHealth::new(
            config.smtp.enabled,
            config.email.enabled,
        ),
        pool,
        config,
        redis_client,
        mail_hub,
    };
    // 启动 SMTP 收信（监听 25）
    if state.config.smtp.enabled {
        let smtp_state = state.clone();
        let smtp_health = state.runtime_health.clone();
        tokio::spawn(async move {
            if let Err(e) = smtp::server::run(smtp_state).await {
                smtp_health.smtp_failed(e.to_string()).await;
                tracing::error!(%e, "SMTP 服务器退出");
            }
        });
    }
    // 启动定时任务（清理过期邮件/邮箱）
    workers::start(state.clone());
    if state.config.email.enabled && state.config.email.queue_enabled {
        if let Some(redis) = state.redis_client.clone() {
            infra::mail::worker::start(redis, state.config.email.clone(), state.pool.clone());
            state.runtime_health.outbound_status("healthy").await;
        } else {
            tracing::warn!("mail queue requested but Redis is unavailable");
            state.runtime_health.outbound_status("fault").await;
        }
    } else if state.config.email.enabled {
        state.runtime_health.outbound_status("healthy").await;
    }
    let listener = tokio::net::TcpListener::bind(&address).await?;
    tracing::info!(%address, "server listening");
    axum::serve(
        listener,
        build_router(state)?.into_make_service_with_connect_info::<std::net::SocketAddr>(),
    )
    .await?;
    Ok(())
}

#[cfg(test)]
mod route_tests {
    use super::*;
    use axum::{
        body::{to_bytes, Body},
        http::{Request, StatusCode},
    };
    use tower::ServiceExt;

    async fn test_app(max_body_bytes: usize) -> Router {
        let mut config = config::app::AppConfig::load_from_path("config/development.toml").unwrap();
        let db_path =
            std::env::temp_dir().join(format!("email-unlimit-{}.sqlite", uuid::Uuid::new_v4()));
        config.database.path = Some(db_path);
        config.redis.enabled = false;
        config.email.enabled = false;
        config.server.max_body_bytes = max_body_bytes;
        let pool = db::init_database(&config.database).await.unwrap();
        build_router(AppState {
            runtime_health: runtime_health::RuntimeHealth::new(false, false),
            pool,
            config,
            redis_client: None,
            mail_hub: smtp::MailHub::new(),
        })
        .unwrap()
    }

    #[tokio::test]
    async fn health_works_without_redis() {
        let response = test_app(1024)
            .await
            .oneshot(
                Request::builder()
                    .uri("/health")
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::OK);
        let body = to_bytes(response.into_body(), 4096).await.unwrap();
        assert!(String::from_utf8_lossy(&body).contains("\"redis\":false"));
    }

    #[tokio::test]
    async fn fallback_is_structured_json() {
        let response = test_app(1024)
            .await
            .oneshot(
                Request::builder()
                    .uri("/missing")
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::NOT_FOUND);
        let body = to_bytes(response.into_body(), 4096).await.unwrap();
        assert!(String::from_utf8_lossy(&body).contains("\"code\":404"));
    }

    #[tokio::test]
    async fn rejects_oversized_body() {
        let response = test_app(8)
            .await
            .oneshot(
                Request::builder()
                    .method("POST")
                    .uri("/auth/login")
                    .header("content-type", "application/json")
                    .body(Body::from("0123456789"))
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::PAYLOAD_TOO_LARGE);
    }

    #[tokio::test]
    async fn protected_route_requires_token_and_uses_language() {
        let response = test_app(1024)
            .await
            .oneshot(
                Request::builder()
                    .uri("/api/user/profile")
                    .header("accept-language", "en")
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
        let body = to_bytes(response.into_body(), 4096).await.unwrap();
        assert!(String::from_utf8_lossy(&body).contains("Missing authorization header"));
    }

    #[tokio::test]
    async fn method_not_allowed_is_structured() {
        let response = test_app(1024)
            .await
            .oneshot(
                Request::builder()
                    .method("PATCH")
                    .uri("/health")
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::METHOD_NOT_ALLOWED);
        let body = to_bytes(response.into_body(), 4096).await.unwrap();
        assert!(String::from_utf8_lossy(&body).contains("\"code\":405"));
    }

    #[tokio::test]
    async fn bootstrap_admin_can_access_admin_routes() {
        let mut config = config::app::AppConfig::load_from_path("config/development.toml").unwrap();
        let db_path = std::env::temp_dir().join(format!(
            "email-unlimit-admin-{}.sqlite",
            uuid::Uuid::new_v4()
        ));
        config.database.path = Some(db_path);
        config.redis.enabled = false;
        config.email.enabled = false;
        config.auth.bootstrap_admin_email = "admin@example.com".into();
        let pool = db::init_database(&config.database).await.unwrap();
        let app = build_router(AppState {
            runtime_health: runtime_health::RuntimeHealth::new(false, false),
            pool,
            config,
            redis_client: None,
            mail_hub: smtp::MailHub::new(),
        })
        .unwrap();

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .method("POST")
                    .uri("/auth/register")
                    .header("content-type", "application/json")
                    .body(Body::from(
                        r#"{"email":"admin@example.com","password":"password123"}"#,
                    ))
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::OK);
        let body = to_bytes(response.into_body(), 16 * 1024).await.unwrap();
        let value: serde_json::Value = serde_json::from_slice(&body).unwrap();
        let token = value["data"]["access_token"].as_str().unwrap();

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .uri("/api/credits")
                    .header("authorization", format!("Bearer {token}"))
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::OK);
        let body = to_bytes(response.into_body(), 16 * 1024).await.unwrap();
        let credits: serde_json::Value = serde_json::from_slice(&body).unwrap();
        assert_eq!(credits["data"]["balance"], 30);
        assert_eq!(credits["data"]["pricing"]["create_mailbox"], 2);
        assert_eq!(credits["data"]["daily_limits"]["mailboxes"], 3);
        assert_eq!(credits["data"]["usage_today"]["mailboxes_created"], 0);
        assert_eq!(credits["data"]["check_in"]["reward"], 3);

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .uri("/admin/stats")
                    .header("authorization", format!("Bearer {token}"))
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::OK);

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .uri("/admin/credits/settings")
                    .header("authorization", format!("Bearer {token}"))
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::OK);

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .method("PUT")
                    .uri("/admin/credits/settings")
                    .header("authorization", format!("Bearer {token}"))
                    .header("content-type", "application/json")
                    .body(Body::from(
                        r#"{
                            "register_bonus":30,
                            "daily_check_in_reward":3,
                            "reward_balance_cap":90,
                            "create_mailbox_cost":4,
                            "receive_email_cost":1,
                            "daily_mailboxes_limit":3,
                            "daily_emails_limit":20,
                            "expected_version":0,
                            "reason":"route test"
                        }"#,
                    ))
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::OK);

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .method("PUT")
                    .uri("/admin/credits/settings")
                    .header("authorization", format!("Bearer {token}"))
                    .header("content-type", "application/json")
                    .body(Body::from(
                        r#"{
                            "register_bonus":30,
                            "daily_check_in_reward":3,
                            "reward_balance_cap":90,
                            "create_mailbox_cost":2,
                            "receive_email_cost":1,
                            "daily_mailboxes_limit":3,
                            "daily_emails_limit":20,
                            "expected_version":0,
                            "reason":"stale update"
                        }"#,
                    ))
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::CONFLICT);

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .method("POST")
                    .uri("/api/credits/check-in")
                    .header("authorization", format!("Bearer {token}"))
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::OK);
        let body = to_bytes(response.into_body(), 16 * 1024).await.unwrap();
        let check_in: serde_json::Value = serde_json::from_slice(&body).unwrap();
        assert_eq!(check_in["data"]["claimed"], true);
        assert_eq!(check_in["data"]["reward_granted"], 3);

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .uri("/admin/users")
                    .header("authorization", format!("Bearer {token}"))
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        let body = to_bytes(response.into_body(), 16 * 1024).await.unwrap();
        let users: serde_json::Value = serde_json::from_slice(&body).unwrap();
        assert_eq!(users["data"]["page"], 1);
        assert_eq!(users["data"]["total"], 1);
        let user_id = users["data"]["items"][0]["id"].as_str().unwrap();
        assert_eq!(users["data"]["items"][0]["is_current"], true);

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .method("PATCH")
                    .uri(format!("/admin/users/{user_id}"))
                    .header("authorization", format!("Bearer {token}"))
                    .header("content-type", "application/json")
                    .body(Body::from(r#"{"status":"suspended"}"#))
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::BAD_REQUEST);

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .uri("/api/credits")
                    .header("authorization", format!("Bearer {token}"))
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::OK);

        let response = app
            .oneshot(
                Request::builder()
                    .method("POST")
                    .uri("/admin/credits/adjust")
                    .header("authorization", format!("Bearer {token}"))
                    .header("content-type", "application/json")
                    .body(Body::from(format!(
                        r#"{{"user_id":"{user_id}","delta":1,"reason":"self adjustment"}}"#
                    )))
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::OK);
    }

    #[tokio::test]
    async fn deleting_account_revokes_mailbox_tokens() {
        let app = test_app(16 * 1024).await;
        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .method("POST")
                    .uri("/auth/register")
                    .header("content-type", "application/json")
                    .body(Body::from(
                        r#"{"email":"delete@example.com","password":"password123"}"#,
                    ))
                    .unwrap(),
            )
            .await
            .unwrap();
        let body = to_bytes(response.into_body(), 16 * 1024).await.unwrap();
        let registered: serde_json::Value = serde_json::from_slice(&body).unwrap();
        let user_token = registered["data"]["access_token"].as_str().unwrap();

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .method("POST")
                    .uri("/api/mailboxes")
                    .header("authorization", format!("Bearer {user_token}"))
                    .header("content-type", "application/json")
                    .body(Body::from(r#"{"local_part":"delete-account"}"#))
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::OK);
        let body = to_bytes(response.into_body(), 16 * 1024).await.unwrap();
        let mailbox: serde_json::Value = serde_json::from_slice(&body).unwrap();
        let mailbox_id = mailbox["data"]["id"].as_i64().unwrap();
        let mailbox_token = mailbox["data"]["access_token"].as_str().unwrap();

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .uri("/api/credits")
                    .header("authorization", format!("Bearer {user_token}"))
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        let body = to_bytes(response.into_body(), 16 * 1024).await.unwrap();
        let credits: serde_json::Value = serde_json::from_slice(&body).unwrap();
        assert_eq!(credits["data"]["balance"], 28);
        assert_eq!(credits["data"]["usage_today"]["mailboxes_created"], 1);

        let response = app
            .clone()
            .oneshot(
                Request::builder()
                    .method("POST")
                    .uri("/auth/delete")
                    .header("authorization", format!("Bearer {user_token}"))
                    .header("content-type", "application/json")
                    .body(Body::from(
                        r#"{"user_id":"ignored","password":"password123"}"#,
                    ))
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::OK);

        let response = app
            .oneshot(
                Request::builder()
                    .uri(format!("/api/mailboxes/{mailbox_id}/emails"))
                    .header("authorization", format!("Bearer {mailbox_token}"))
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();
        assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
    }
}
