//! 设备服务节点管理 API
//!
//! 设备服务启动时注册到 API 服务，定期发送心跳。
//! API 服务通过节点健康状况判断设备服务是否在线。

use axum::extract::{Path, State};
use axum::Json;
use serde::Deserialize;
use serde_json::{json, Value};

use crate::commands::AppState;
use crate::error::AppError;

/// 节点注册请求体
#[derive(Debug, Deserialize)]
pub struct NodeRegisterRequest {
    pub node_id: String,
    pub ip: String,
    pub tcp_port: u16,
}

/// POST /api/nodes/register — 设备服务注册
pub async fn register_node(
    State(state): State<AppState>,
    Json(req): Json<NodeRegisterRequest>,
) -> Result<Json<Value>, AppError> {
    state.nodes.register(&req.node_id, &req.ip, req.tcp_port).await;
    tracing::info!("[节点注册] node_id={}", req.node_id);
    Ok(Json(json!({"suc": 1})))
}

/// POST /api/nodes/:node_id/heartbeat — 节点心跳
pub async fn node_heartbeat(
    State(state): State<AppState>,
    Path(node_id): Path<String>,
) -> Result<Json<Value>, AppError> {
    if state.nodes.heartbeat(&node_id).await {
        Ok(Json(json!({"suc": 1})))
    } else {
        Ok(Json(json!({"suc": 0, "err": "节点未注册"})))
    }
}

/// POST /api/nodes/:node_id/deregister — 节点注销
pub async fn deregister_node(
    State(state): State<AppState>,
    Path(node_id): Path<String>,
) -> Result<Json<Value>, AppError> {
    state.nodes.remove(&node_id).await;
    tracing::info!("[节点注销] node_id={}", node_id);
    Ok(Json(json!({"suc": 1})))
}

/// GET /api/nodes — 节点列表
pub async fn list_nodes(
    State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
    let nodes = state.nodes.list().await;
    let list: Vec<Value> = nodes
        .into_iter()
        .map(|n| {
            json!({
                "node_id": n.node_id,
                "ip": n.ip,
                "tcp_port": n.tcp_port,
            })
        })
        .collect();
    Ok(Json(json!({"nodes": list, "count": list.len()})))
}
