//! Docker compose container name helpers.

use super::InfraContext;
use std::process::Command;

/// Resolve the running container name for the postgres service.
/// Falls back to "compose-postgres-1" when docker is unavailable.
pub fn postgres_container_name(ctx: &InfraContext) -> String {
    resolve_container_name(ctx, "postgres")
        .unwrap_or_else(|| "compose-postgres-1".to_string())
}

/// Resolve the running container name for the RGS service.
/// Falls back to "compose-rgs-1" when docker is unavailable.
pub fn rgs_container_name(ctx: &InfraContext) -> String {
    resolve_container_name(ctx, "rgs")
        .unwrap_or_else(|| "compose-rgs-1".to_string())
}

/// Query `docker compose ps --format json` to find the actual container name
/// for a compose service. Returns `None` when docker is unavailable or the
/// service is not found.
fn resolve_container_name(ctx: &InfraContext, service: &str) -> Option<String> {
    let out = Command::new("docker")
        .args(["compose", "ps", "--format", "json"])
        .current_dir(ctx.compose_dir())
        .output()
        .ok()?;
    if !out.status.success() {
        return None;
    }
    let text = String::from_utf8_lossy(&out.stdout);

    // docker compose ps --format json outputs one JSON object per line (NDJSON).
    for line in text.lines() {
        let Ok(v) = serde_json::from_str::<serde_json::Value>(line) else {
            continue;
        };
        let svc = v.get("Service").and_then(|s| s.as_str()).unwrap_or("");
        if svc.eq_ignore_ascii_case(service) {
            if let Some(name) = v.get("Name").and_then(|s| s.as_str()) {
                return Some(name.to_string());
            }
        }
    }
    None
}

#[allow(dead_code)]
pub fn compose_is_running(ctx: &InfraContext) -> bool {
    Command::new("docker")
        .args(["compose", "ps", "-q"])
        .current_dir(ctx.compose_dir())
        .output()
        .map(|o| o.status.success() && !o.stdout.is_empty())
        .unwrap_or(false)
}
