use std::cmp::Ordering;

/// Runtime representation of a `tracing` event field value.
#[derive(Debug, Clone, PartialEq)]
pub enum FieldValue {
    /// Signed integer field.
    I64(i64),
    /// Unsigned integer field.
    U64(u64),
    /// Boolean field.
    Bool(bool),
    /// String or debug-formatted field.
    String(String),
}

impl FieldValue {
    /// Returns a string view for string operations.
    pub fn as_str(&self) -> Option<&str> {
        match self {
            FieldValue::String(value) => Some(value),
            _ => None,
        }
    }

    /// Compares two field values, preferring numeric comparison when possible.
    pub fn compare(&self, other: &FieldValue) -> Option<Ordering> {
        match (self, other) {
            (FieldValue::I64(left), FieldValue::I64(right)) => Some(left.cmp(right)),
            (FieldValue::U64(left), FieldValue::U64(right)) => Some(left.cmp(right)),
            (FieldValue::I64(left), FieldValue::U64(right)) => {
                if *left < 0 {
                    Some(Ordering::Less)
                } else {
                    (*left as u64).partial_cmp(right)
                }
            }
            (FieldValue::U64(left), FieldValue::I64(right)) => {
                if *right < 0 {
                    Some(Ordering::Greater)
                } else {
                    left.partial_cmp(&(*right as u64))
                }
            }
            (FieldValue::Bool(left), FieldValue::Bool(right)) => Some(left.cmp(right)),
            (FieldValue::String(left), FieldValue::String(right)) => Some(left.cmp(right)),
            _ => None,
        }
    }
}
