//! Strategy resolver for the heartbeat path. The actual SQL lives in
//! `Database::strategy_resolve_for` — this module exists to give the
//! heartbeat handler a stable import surface and to centralize how a
//! resolved strategy is converted into the wire-shape JSON the client
//! expects (`strategy.config_options` + `strategy.extra` per
//! CONSOLE_API.md §6.1).

use crate::api::state::AppState;
use crate::database::ResolvedStrategy;
use serde_json::{json, Value};

/// Resolve and serialize a strategy for `peer_id`. Returns
/// `(modified_at, strategy_value)` where `strategy_value` is the JSON object
/// the heartbeat reply embeds under `strategy`. When no strategy applies, we
/// return an empty `{config_options: {}, extra: {}}` and `modified_at = 0`.
pub async fn resolve_for(state: &AppState, peer_id: &str) -> (i64, Value) {
    let resolved = state
        .db
        .strategy_resolve_for(peer_id)
        .await
        .unwrap_or_default();
    serialize(&resolved)
}

fn serialize(r: &ResolvedStrategy) -> (i64, Value) {
    let cfg: Value = serde_json::from_str(&r.config_options_json).unwrap_or_else(|_| json!({}));
    let extra: Value = serde_json::from_str(&r.extra_json).unwrap_or_else(|_| json!({}));
    (
        r.modified_at,
        json!({
            "config_options": cfg,
            "extra": extra,
        }),
    )
}
