//! Output format abstraction for JSON and human-readable rendering.
//!
//! Every command result type implements [`HumanReadable`] so the CLI can
//! switch between `--json` (machine-readable) and the default tabular output
//! with a single [`render`] call.

use serde::Serialize;
use std::io::Write;

/// Output format selected by the global `--json` flag.
#[derive(Debug, Clone, Copy)]
pub enum OutputFormat {
    /// Default: pretty-printed tables/text for humans.
    Human,
    /// Structured JSON (for CI pipelines, LLM tool-use, jq).
    Json,
}

/// Render any serializable result in the chosen format.
///
/// # Errors
///
/// Returns an error if JSON serialization or stdout writing fails.
pub fn render<T: Serialize + HumanReadable>(result: &T, format: OutputFormat) -> anyhow::Result<()> {
    match format {
        OutputFormat::Json => {
            let json = serde_json::to_string_pretty(result)?;
            let mut stdout = std::io::stdout().lock();
            writeln!(stdout, "{json}")?;
        }
        OutputFormat::Human => {
            result.print_human();
        }
    }
    Ok(())
}

/// Trait for human-readable terminal rendering.
///
/// Implementors print directly to stdout using `println!`, `colored`, or
/// `tabled` — whatever looks best for the data type.
pub trait HumanReadable {
    /// Print a human-friendly representation to stdout.
    fn print_human(&self);
}
