use serde::{Deserialize, Serialize};

/// An AI agent entry managed through the developer tools.
///
/// # Fields
///
/// * `id` - Unique agent identifier
/// * `name` - Human-readable agent name
/// * `description` - What this agent does
/// * `status` - Current running status label
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AgentEntry {
    pub id: String,
    pub name: String,
    pub description: String,
    pub status: String,
}

/// A workflow/flow entry from the flow builder.
///
/// # Fields
///
/// * `id` - Unique flow identifier
/// * `name` - Human-readable flow name
/// * `node_count` - Number of nodes in the flow graph
/// * `last_run` - ISO 8601 timestamp of the last execution
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FlowEntry {
    pub id: String,
    pub name: String,
    pub node_count: u32,
    pub last_run: Option<String>,
}

/// A single analytics metric for the developer dashboard.
///
/// # Fields
///
/// * `label` - Display name of the metric
/// * `value` - Current value as a formatted string
/// * `change_pct` - Percentage change from previous period (positive = increase)
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AnalyticsMetric {
    pub label: String,
    pub value: String,
    pub change_pct: f64,
}

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

    #[test]
    fn agent_entry_serde_round_trip() {
        let agent = AgentEntry {
            id: "a1".into(),
            name: "RAG Agent".into(),
            description: "Retrieval-augmented generation".into(),
            status: "running".into(),
        };
        let json = serde_json::to_string(&agent).expect("serialize AgentEntry");
        let back: AgentEntry = serde_json::from_str(&json).expect("deserialize AgentEntry");
        assert_eq!(agent, back);
    }

    #[test]
    fn flow_entry_serde_round_trip() {
        let flow = FlowEntry {
            id: "f1".into(),
            name: "Data Pipeline".into(),
            node_count: 5,
            last_run: Some("2025-06-01T12:00:00Z".into()),
        };
        let json = serde_json::to_string(&flow).expect("serialize FlowEntry");
        let back: FlowEntry = serde_json::from_str(&json).expect("deserialize FlowEntry");
        assert_eq!(flow, back);
    }

    #[test]
    fn flow_entry_with_none_last_run() {
        let flow = FlowEntry {
            id: "f2".into(),
            name: "New Flow".into(),
            node_count: 0,
            last_run: None,
        };
        let json = serde_json::to_string(&flow).expect("serialize");
        let back: FlowEntry = serde_json::from_str(&json).expect("deserialize");
        assert_eq!(flow, back);
        assert_eq!(back.last_run, None);
    }

    #[test]
    fn analytics_metric_negative_change_pct() {
        let metric = AnalyticsMetric {
            label: "Latency".into(),
            value: "120ms".into(),
            change_pct: -15.5,
        };
        let json = serde_json::to_string(&metric).expect("serialize AnalyticsMetric");
        let back: AnalyticsMetric =
            serde_json::from_str(&json).expect("deserialize AnalyticsMetric");
        assert_eq!(metric, back);
        assert!(back.change_pct < 0.0);
    }
}
