//! Helper functions for local Episteme operations.

use stemedb_core::types::Assertion;
use tracing::debug;

use super::corpus::current_timestamp;
use crate::types::PriorObservation;

/// Format a Unix timestamp as a human-readable relative time string.
pub fn format_timestamp(ts: u64) -> String {
    let now = current_timestamp();
    let diff = now.saturating_sub(ts);

    if diff < 60 {
        "just now".to_string()
    } else if diff < 3600 {
        let mins = diff / 60;
        format!("{} {} ago", mins, if mins == 1 { "min" } else { "mins" })
    } else if diff < 86400 {
        let hours = diff / 3600;
        format!("{} {} ago", hours, if hours == 1 { "hour" } else { "hours" })
    } else {
        let days = diff / 86400;
        format!("{} {} ago", days, if days == 1 { "day" } else { "days" })
    }
}

/// Extract file and line from source_metadata JSON (stored as bytes).
pub fn extract_source_location(metadata: &Option<Vec<u8>>) -> (String, usize) {
    if let Some(meta_bytes) = metadata {
        // Try to parse as UTF-8 string first, then as JSON
        match std::str::from_utf8(meta_bytes) {
            Ok(meta) => match serde_json::from_str::<serde_json::Value>(meta) {
                Ok(parsed) => {
                    let file = parsed
                        .get("file")
                        .and_then(|v| v.as_str())
                        .unwrap_or("unknown")
                        .to_string();
                    let line = parsed.get("line").and_then(|v| v.as_u64()).unwrap_or(0) as usize;
                    return (file, line);
                }
                Err(e) => {
                    debug!(error = %e, meta_preview = %meta.chars().take(50).collect::<String>(), "Failed to parse source_metadata as JSON");
                }
            },
            Err(e) => {
                debug!(error = %e, byte_len = meta_bytes.len(), "Failed to parse source_metadata as UTF-8");
            }
        }
    }
    ("unknown".to_string(), 0)
}

/// Convert a prior assertion to a PriorObservation struct.
pub fn assertion_to_prior_observation(assertion: &Assertion) -> PriorObservation {
    let (file, line) = extract_source_location(&assertion.source_metadata);
    PriorObservation { value: assertion.object.clone(), timestamp: assertion.timestamp, file, line }
}
