use crate::commons::utils::CONFIG as config;
use crate::protocols;
use salvo::catcher::Catcher;
use salvo::prelude::*;
use serde_json::json;
use socketioxide::SocketIo;
use tower::ServiceBuilder;
use tower_http::cors::CorsLayer;

pub fn config_router() -> Router {
    let (layer, io) = SocketIo::new_layer();
    let layer = ServiceBuilder::new()
        .layer(CorsLayer::permissive())
        .layer(layer);

    io.ns(
        config.client_ns.as_str(),
        crate::protocols::socket_io::on_connect,
    );
    let layer = layer.compat();
    Router::new()
        .push(
            Router::with_path(config.socket_path.as_str())
                .hoop(layer)
                .goal(hello),
        )
        .push(Router::with_path("/manager/login").post(crate::protocols::socket_io::login))
        .push(Router::with_path("/manager/getConn").post(crate::protocols::socket_io::getConn))
        .push(
            Router::with_path("/manager/getTop10Rank")
                .post(crate::protocols::socket_io::getTop10Rank),
        )
}

pub fn config_catcher() -> Catcher {
    Catcher::default().hoop(rewrite_405_to_404)
}

#[handler]
async fn hello() -> &'static str {
    ""
}

// 将 405 Method Not Allowed 转换为 404 Not Found，并渲染统一的 404 页面。
#[handler]
async fn rewrite_405_to_404(
    req: &mut Request,
    depot: &mut Depot,
    res: &mut Response,
    ctrl: &mut FlowCtrl,
) {
    if res.status_code == Some(StatusCode::METHOD_NOT_ALLOWED) {
        res.status_code(StatusCode::NOT_FOUND);
    }

    if res.status_code == Some(StatusCode::NOT_FOUND) {
        render_not_found(req, res);
        ctrl.skip_rest();
        return;
    }

    ctrl.call_next(req, depot, res).await;
}

// 根据请求的 Accept 头和 URL 路径，返回 JSON 格式的 404 错误信息，或者渲染一个简单的 HTML 404 页面。
fn render_not_found(req: &Request, res: &mut Response) {
    let accept = req
        .headers()
        .get("accept")
        .and_then(|value| value.to_str().ok())
        .unwrap_or("");
    let path = req.uri().path();

    if path.starts_with("/api/") || accept.contains("application/json") {
        res.render(Json(json!({
            "code": 404,
            "message": "resource not found",
            "path": path,
        })));
        return;
    }

    res.render(Text::Html(
        r#"<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>404 Not Found</title>
    <style>
        body{margin:0;min-height:100vh;display:grid;place-items:center;background:#f6f7fb;color:#1f2937;font-family:sans-serif;}main{padding:32px;text-align:center;}h1{margin:0 0 12px;font-size:64px;}p{margin:0;font-size:16px;}
    </style>
</head>
<body>
    <main>
        <h1>404</h1>
        <p>页面不存在</p>
    </main>
</body>
</html>"#,
    ));
}
