mecha10-cli 0.1.47

Mecha10 CLI tool
Documentation
#![allow(dead_code)]
//! Status and monitoring commands

use crate::dev::DevState;
use anyhow::Result;
use console::Term;
use std::fs;
use std::io::BufRead;
use std::io::BufReader;
use std::path::Path;

/// Show running nodes status
pub async fn show_nodes(state: &mut DevState) -> Result<()> {
    println!("\n╭─────────────────────────────────────────╮");
    println!("│  Running Nodes                          │");
    println!("╰─────────────────────────────────────────╯\n");

    let status_map = state.process_tracker.get_status_map();

    if status_map.is_empty() {
        println!("  No nodes currently running");
        println!("  (Note: Nodes may have exited or failed to start)\n");
        return Ok(());
    }

    println!("  Node              Status");
    println!("  ───────────────── ──────────────────────");

    for (node_name, status) in status_map {
        println!("  {:<17} {}", node_name, status);
    }

    println!();
    Ok(())
}

/// Show development status
pub async fn show_status(state: &DevState) -> Result<()> {
    println!("\n╭─────────────────────────────────────────╮");
    println!("│  Development Status                      │");
    println!("╰─────────────────────────────────────────╯\n");
    println!("  Robot ID: {}", state.robot_id);
    println!("  Environment: {}", state.env_name);
    println!(
        "  Simulator: {}",
        if state.simulator_running { "Running" } else { "Stopped" }
    );
    println!("  Current Env: {}", state.current_env);
    println!("  Current Task: {}", state.current_task);

    if let Some(dashboard_url) = state.dashboard_url() {
        println!("\n  Services:");
        println!("    Dashboard: {}", dashboard_url);
    }

    println!();
    Ok(())
}

/// View logs with live streaming
pub async fn view_logs() -> Result<()> {
    println!("\n╭─────────────────────────────────────────╮");
    println!("│  View Logs                               │");
    println!("╰─────────────────────────────────────────╯\n");

    let logs_dir = Path::new("logs");
    if !logs_dir.exists() {
        println!("  No logs directory found. Logs will be created when nodes run.");
        println!("  Press any key to continue...");
        let term = Term::stdout();
        let _ = term.read_key();
        return Ok(());
    }

    let mut log_files = Vec::new();
    if let Ok(entries) = fs::read_dir(logs_dir) {
        for entry in entries.flatten() {
            if let Some(name) = entry.file_name().to_str() {
                if name.ends_with(".log") {
                    log_files.push(name.to_string());
                }
            }
        }
    }

    if log_files.is_empty() {
        println!("  No log files found in logs/ directory.");
        println!("  Logs will be created when nodes start running.");
        println!("\n  Press any key to continue...");
        let term = Term::stdout();
        let _ = term.read_key();
        return Ok(());
    }

    println!("  Available logs:");
    for (i, log_file) in log_files.iter().enumerate() {
        println!("    {}. {}", i + 1, log_file);
    }

    let log_path = logs_dir.join(&log_files[0]);
    println!("\n  Showing: {} (last 20 lines)", log_files[0]);
    println!("  Press 'q' to return to main menu\n");
    println!("─────────────────────────────────────────\n");

    if log_path.exists() {
        if let Ok(file) = fs::File::open(&log_path) {
            let reader = BufReader::new(file);
            let lines: Vec<String> = reader.lines().map_while(Result::ok).collect();
            let start = if lines.len() > 20 { lines.len() - 20 } else { 0 };
            for line in &lines[start..] {
                println!("{}", line);
            }
        }
    } else {
        println!("  Log file is empty or not readable.");
    }

    println!("\n─────────────────────────────────────────");
    println!("  Press any key to continue...");

    let term = Term::stdout();
    let _ = term.read_key();

    Ok(())
}