agent-device-rec 0.1.0

Health device recommendation engine for longevity monitoring
use assert_cmd::Command;
use predicates::prelude::*;

fn cmd() -> Command {
    Command::cargo_bin("agent-device-rec").unwrap()
}

#[test]
fn test_agent_info() {
    cmd()
        .arg("agent-info")
        .assert()
        .success()
        .stdout(predicate::str::contains("agent-device-rec"))
        .stdout(predicate::str::contains("capabilities"))
        .stdout(predicate::str::contains("device_recommendation"));
}

#[test]
fn test_list_all() {
    cmd()
        .arg("list")
        .arg("--json")
        .assert()
        .success()
        .stdout(predicate::str::contains("\"version\": \"1\""))
        .stdout(predicate::str::contains("\"status\": \"success\""))
        .stdout(predicate::str::contains("dexcom-g7"));
}

#[test]
fn test_list_by_category_cgm() {
    let output = cmd()
        .args(["list", "--category", "cgm", "--json"])
        .output()
        .unwrap();

    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.contains("dexcom-g7"));
    assert!(stdout.contains("abbott-libre-3"));
    // Should not contain non-CGM devices
    assert!(!stdout.contains("oura-ring-4"));
    assert!(!stdout.contains("withings-bpm-connect"));
}

#[test]
fn test_list_by_brand() {
    let output = cmd()
        .args(["list", "--brand", "withings", "--json"])
        .output()
        .unwrap();

    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.contains("withings-bpm-connect"));
    assert!(stdout.contains("withings-body-smart"));
    assert!(!stdout.contains("dexcom-g7"));
}

#[test]
fn test_list_by_price_range() {
    let output = cmd()
        .args(["list", "--price-range", "budget", "--json"])
        .output()
        .unwrap();

    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.contains("omron-evolv"));
    assert!(!stdout.contains("apple-watch-ultra-2"));
}

#[test]
fn test_show_device() {
    cmd()
        .args(["show", "dexcom-g7", "--json"])
        .assert()
        .success()
        .stdout(predicate::str::contains("Dexcom G7"))
        .stdout(predicate::str::contains("\"category\": \"cgm\""))
        .stdout(predicate::str::contains("fasting_glucose"));
}

#[test]
fn test_show_device_not_found() {
    cmd()
        .args(["show", "nonexistent-device", "--json"])
        .assert()
        .code(3)
        .stderr(predicate::str::contains("Device not found"));
}

#[test]
fn test_search_blood_pressure() {
    let output = cmd()
        .args(["search", "blood pressure", "--json"])
        .output()
        .unwrap();

    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.contains("withings-bpm-connect") || stdout.contains("omron-evolv"));
}

#[test]
fn test_search_glucose() {
    let output = cmd()
        .args(["search", "glucose", "--json"])
        .output()
        .unwrap();

    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.contains("dexcom-g7") || stdout.contains("abbott-libre-3"));
}

#[test]
fn test_brands() {
    cmd()
        .args(["brands", "--json"])
        .assert()
        .success()
        .stdout(predicate::str::contains("Dexcom"))
        .stdout(predicate::str::contains("Withings"))
        .stdout(predicate::str::contains("Oura"))
        .stdout(predicate::str::contains("Masimo"));
}

#[test]
fn test_compare_two_devices() {
    cmd()
        .args(["compare", "dexcom-g7", "abbott-libre-3", "--json"])
        .assert()
        .success()
        .stdout(predicate::str::contains("comparison_matrix"))
        .stdout(predicate::str::contains("Dexcom G7"))
        .stdout(predicate::str::contains("Abbott FreeStyle Libre 3"));
}

#[test]
fn test_compare_insufficient_devices() {
    cmd()
        .args(["compare", "dexcom-g7", "--json"])
        .assert()
        .code(3)
        .stderr(predicate::str::contains("at least 2"));
}

#[test]
fn test_compare_device_not_found() {
    cmd()
        .args(["compare", "dexcom-g7", "nonexistent", "--json"])
        .assert()
        .code(3)
        .stderr(predicate::str::contains("Device not found"));
}

#[test]
fn test_recommend_stdin_insulin_resistance() {
    let labassess_json = r#"{
        "version": "1",
        "status": "success",
        "data": {
            "mode": "longevity",
            "patient": { "sex": "male", "age": 45 },
            "scored_biomarkers": [
                {
                    "name": "HbA1c",
                    "standardized_name": "hba1c",
                    "value": 5.8,
                    "unit": "%",
                    "status": "concern",
                    "severity": "high"
                },
                {
                    "name": "Fasting Glucose",
                    "standardized_name": "fasting_glucose",
                    "value": 105,
                    "unit": "mg/dL",
                    "status": "attention",
                    "severity": "moderate"
                }
            ],
            "derived_values": [],
            "patterns_detected": [
                {
                    "name": "insulin_resistance_cascade",
                    "confidence": "high",
                    "criteria_met": ["HOMA-IR >= 2.5"],
                    "action": "CGM monitoring recommended"
                }
            ],
            "red_flags": [],
            "summary": {
                "total_markers": 2,
                "scored": 2,
                "unknown": 0,
                "optimal": 0,
                "good": 0,
                "attention": 1,
                "marginal": 0,
                "concern": 1
            }
        }
    }"#;

    let output = cmd()
        .args(["recommend", "--stdin", "--json"])
        .write_stdin(labassess_json)
        .output()
        .unwrap();

    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(output.status.success(), "stderr: {}", String::from_utf8_lossy(&output.stderr));
    assert!(stdout.contains("\"status\": \"success\""));
    // Should recommend CGM devices for insulin resistance
    assert!(
        stdout.contains("dexcom-g7") || stdout.contains("abbott-libre-3"),
        "Expected CGM recommendation, got: {stdout}"
    );
}

#[test]
fn test_recommend_stdin_cv_risk() {
    let labassess_json = r#"{
        "version": "1",
        "status": "success",
        "data": {
            "mode": "longevity",
            "patient": { "sex": "female", "age": 55 },
            "scored_biomarkers": [],
            "derived_values": [],
            "patterns_detected": [
                {
                    "name": "cv_risk_enhancement",
                    "confidence": "moderate",
                    "criteria_met": ["ApoB elevated"],
                    "action": "Cardiovascular monitoring"
                }
            ],
            "red_flags": [],
            "summary": {
                "total_markers": 0,
                "scored": 0,
                "unknown": 0,
                "optimal": 0,
                "good": 0,
                "attention": 0,
                "marginal": 0,
                "concern": 0
            }
        }
    }"#;

    let output = cmd()
        .args(["recommend", "--stdin", "--json"])
        .write_stdin(labassess_json)
        .output()
        .unwrap();

    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(output.status.success());
    // CV risk should recommend BP and pulse oximeter
    assert!(
        stdout.contains("blood_pressure") || stdout.contains("pulse_oximeter"),
        "Expected BP/pulse oximeter recommendation, got: {stdout}"
    );
}

#[test]
fn test_recommend_stdin_red_flag() {
    let labassess_json = r#"{
        "version": "1",
        "status": "success",
        "data": {
            "mode": "longevity",
            "patient": { "sex": "male", "age": 60 },
            "scored_biomarkers": [],
            "derived_values": [],
            "patterns_detected": [],
            "red_flags": [
                {
                    "marker": "systolic_bp",
                    "value": 180.0,
                    "unit": "mmHg",
                    "urgency": "same_day",
                    "action": "Urgent BP evaluation",
                    "referral": "Cardiology"
                }
            ],
            "summary": {
                "total_markers": 0,
                "scored": 0,
                "unknown": 0,
                "optimal": 0,
                "good": 0,
                "attention": 0,
                "marginal": 0,
                "concern": 0
            }
        }
    }"#;

    let output = cmd()
        .args(["recommend", "--stdin", "--json"])
        .write_stdin(labassess_json)
        .output()
        .unwrap();

    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(output.status.success());
    assert!(
        stdout.contains("red_flag_monitor"),
        "Expected red_flag_monitor priority, got: {stdout}"
    );
    assert!(
        stdout.contains("blood_pressure"),
        "Expected blood pressure device, got: {stdout}"
    );
}

#[test]
fn test_no_input_error() {
    // recommend with no slug and no stdin should fail
    cmd()
        .args(["recommend", "--json"])
        .assert()
        .code(3)
        .stderr(predicate::str::contains("No input provided"));
}