partiri-cli 0.1.3

partiri CLI — Deploy and manage services on Partiri Cloud
use tabled::Table;

use crate::client::ApiClient;
use crate::config::PartiriConfig;
use crate::error::Result;
use crate::output::{colored_job_status, JobRow};

pub fn run_list(client: &ApiClient, config: &PartiriConfig) -> Result<()> {
    let id = config.id_or_err()?;
    let jobs = client.list_service_jobs(id)?;

    if jobs.is_empty() {
        println!("No jobs found for this service.");
        return Ok(());
    }

    let mut jobs = jobs;
    jobs.sort_by(|a, b| b.created_at.cmp(&a.created_at));

    let rows: Vec<JobRow> = jobs
        .into_iter()
        .take(5)
        .map(|j| JobRow {
            job_type: j.job_type,
            deploy_ref: j
                .deploy_ref
                .as_deref()
                .map(|r| r.get(..7).unwrap_or(r).to_string())
                .unwrap_or_else(|| "".to_string()),
            status: colored_job_status(&j.status),
            created_at: j
                .created_at
                .as_deref()
                .map(format_timestamp)
                .unwrap_or_else(|| "".to_string()),
        })
        .collect();

    println!("{}", Table::new(rows));
    Ok(())
}

fn format_timestamp(ts: &str) -> String {
    // Extract "YYYY-MM-DD HH:MM" from an RFC 3339 timestamp
    if ts.len() >= 16 && ts.as_bytes().get(10) == Some(&b'T') {
        format!("{} {}", &ts[..10], &ts[11..16])
    } else {
        ts.to_string()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn formats_utc_timestamp() {
        assert_eq!(format_timestamp("2024-02-25T10:30:00Z"), "2024-02-25 10:30");
    }

    #[test]
    fn formats_timestamp_with_positive_offset() {
        // format preserves the local time as-is (does not convert to UTC)
        assert_eq!(
            format_timestamp("2024-02-25T12:30:00+02:00"),
            "2024-02-25 12:30"
        );
    }

    #[test]
    fn formats_timestamp_with_negative_offset() {
        assert_eq!(
            format_timestamp("2024-02-25T08:00:00-05:00"),
            "2024-02-25 08:00"
        );
    }

    #[test]
    fn invalid_string_returns_original() {
        assert_eq!(format_timestamp("not-a-timestamp"), "not-a-timestamp");
    }

    #[test]
    fn empty_string_returns_empty() {
        assert_eq!(format_timestamp(""), "");
    }

    #[test]
    fn date_only_returns_original() {
        // "2024-02-25" is not valid RFC3339 — returns as-is
        assert_eq!(format_timestamp("2024-02-25"), "2024-02-25");
    }

    #[test]
    fn milliseconds_are_dropped_in_output() {
        assert_eq!(
            format_timestamp("2024-02-25T10:30:45.123Z"),
            "2024-02-25 10:30"
        );
    }
}