use actix_web::{web, get, HttpResponse, Responder};
use sqlx::postgres::PgPool;
use serde::Serialize;

#[derive(Serialize)]
pub struct HealthResponse {
    pub status: String,
    pub database: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub hint: Option<String>,
}

#[get("/health")]
pub async fn health_check(pool: web::Data<PgPool>) -> impl Responder {
    match sqlx::query("SELECT 1").fetch_one(pool.get_ref()).await {
        Ok(_) => {
            HttpResponse::Ok().json(HealthResponse {
                status: "ok".to_string(),
                database: "connected".to_string(),
                error: None,
                hint: None,
            })
        }
        Err(e) => {
            let err_str = e.to_string();
            let (error_msg, hint_msg) = if err_str.contains("connection refused") {
                (
                    "无法连接到数据库".to_string(),
                    "请检查数据库服务是否运行".to_string(),
                )
            } else if err_str.contains("Connection timed out") {
                (
                    "数据库连接超时".to_string(),
                    "请检查网络连接".to_string(),
                )
            } else if err_str.contains("does not exist") {
                ("数据库不存在".to_string(), "请检查数据库配置".to_string())
            } else if err_str.contains("28P01") {
                (
                    "数据库认证失败".to_string(),
                    "用户名或密码错误".to_string(),
                )
            } else {
                (
                    "数据库连接失败".to_string(),
                    "请查看服务器日志获取详细信息".to_string(),
                )
            };

            tracing::error!("健康检查失败: {:?}", e);

            HttpResponse::ServiceUnavailable().json(HealthResponse {
                status: "error".to_string(),
                database: "disconnected".to_string(),
                error: Some(error_msg),
                hint: Some(hint_msg),
            })
        }
    }
}
