//! Observability initialisation.
//!
//! Per `_docs/02_document/deployment/observability.md`, the autopilot emits
//! JSON-formatted log records to stdout containing at least: `ts`, `ts_mono_ns`,
//! `level`, `target`, `event`. Initialisation reads the `RUST_LOG` env var (or
//! the `default_log_filter` config fallback) and the `log_format` setting.

use tracing_subscriber::{fmt, prelude::*, EnvFilter};

/// Output format for the tracing layer.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogFormat {
    /// Structured JSON to stdout — production default.
    Json,
    /// Human-readable colour output — dev shells only.
    Pretty,
}

impl LogFormat {
    pub fn parse(s: &str) -> Self {
        match s {
            "json" => LogFormat::Json,
            "pretty" => LogFormat::Pretty,
            _ => LogFormat::Json,
        }
    }
}

/// Initialise `tracing-subscriber` with the configured format and filter.
///
/// `default_filter` is used when the `RUST_LOG` env var is unset.
/// Safe to call exactly once at startup.
pub fn init(
    format: LogFormat,
    default_filter: &str,
) -> Result<(), tracing_subscriber::util::TryInitError> {
    let env_filter =
        EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(default_filter));

    let registry = tracing_subscriber::registry().with(env_filter);

    match format {
        LogFormat::Json => registry
            .with(
                fmt::layer()
                    .json()
                    .with_target(true)
                    .with_current_span(false)
                    .with_span_list(false),
            )
            .try_init(),
        LogFormat::Pretty => registry.with(fmt::layer().with_target(true)).try_init(),
    }
}

/// Canonical log field constants (mirrors observability.md §2).
pub mod fields {
    pub const TS: &str = "ts";
    pub const TS_MONO_NS: &str = "ts_mono_ns";
    pub const LEVEL: &str = "level";
    pub const TARGET: &str = "target";
    pub const EVENT: &str = "event";
    pub const FRAME_SEQ: &str = "frame_seq";
    pub const POI_ID: &str = "poi_id";
    pub const COMMAND_ID: &str = "command_id";
}

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

    #[test]
    fn log_format_parses_known_values() {
        assert_eq!(LogFormat::parse("json"), LogFormat::Json);
        assert_eq!(LogFormat::parse("pretty"), LogFormat::Pretty);
        // Unknown values fall back to JSON (the production-safe default).
        assert_eq!(LogFormat::parse("xml"), LogFormat::Json);
    }
}
