// Tests for mecha10_cli::services::discovery

use mecha10_cli::services::discovery::*;

#[test]
fn test_new_service() {
    let service = DiscoveryService::new();
    assert_eq!(service.node_count(), 0);
}

#[test]
fn test_default_config() {
    let config = DiscoveryConfig::default();
    assert_eq!(config.redis_url, "redis://localhost:6379");
    assert_eq!(config.discovery_topic, "mecha10/discovery");
    assert_eq!(config.heartbeat_interval, Duration::from_secs(5));
    assert_eq!(config.node_timeout, Duration::from_secs(30));
}

#[test]
fn test_node_count() {
    let mut service = DiscoveryService::new();
    assert_eq!(service.node_count(), 0);

    service.discovered_nodes.insert(
        "node1".to_string(),
        NodeInfo {
            node_id: "node1".to_string(),
            node_type: "sensor".to_string(),
            host: "192.168.1.100".to_string(),
            port: 8080,
            last_seen: SystemTime::now(),
            metadata: HashMap::new(),
        },
    );

    assert_eq!(service.node_count(), 1);
}

#[test]
fn test_get_nodes_by_type() {
    let mut service = DiscoveryService::new();

    service.discovered_nodes.insert(
        "sensor1".to_string(),
        NodeInfo {
            node_id: "sensor1".to_string(),
            node_type: "sensor".to_string(),
            host: "192.168.1.100".to_string(),
            port: 8080,
            last_seen: SystemTime::now(),
            metadata: HashMap::new(),
        },
    );

    service.discovered_nodes.insert(
        "motor1".to_string(),
        NodeInfo {
            node_id: "motor1".to_string(),
            node_type: "motor".to_string(),
            host: "192.168.1.101".to_string(),
            port: 8080,
            last_seen: SystemTime::now(),
            metadata: HashMap::new(),
        },
    );

    let sensors = service.get_nodes_by_type("sensor");
    assert_eq!(sensors.len(), 1);
    assert_eq!(sensors[0].node_id, "sensor1");

    let motors = service.get_nodes_by_type("motor");
    assert_eq!(motors.len(), 1);
    assert_eq!(motors[0].node_id, "motor1");
}

#[test]
fn test_clear() {
    let mut service = DiscoveryService::new();

    service.discovered_nodes.insert(
        "node1".to_string(),
        NodeInfo {
            node_id: "node1".to_string(),
            node_type: "sensor".to_string(),
            host: "192.168.1.100".to_string(),
            port: 8080,
            last_seen: SystemTime::now(),
            metadata: HashMap::new(),
        },
    );

    assert_eq!(service.node_count(), 1);

    service.clear();
    assert_eq!(service.node_count(), 0);
}

#[test]
fn test_cleanup_stale_nodes() {
    let mut service = DiscoveryService::new();

    // Add old node
    service.discovered_nodes.insert(
        "old_node".to_string(),
        NodeInfo {
            node_id: "old_node".to_string(),
            node_type: "sensor".to_string(),
            host: "192.168.1.100".to_string(),
            port: 8080,
            last_seen: SystemTime::now() - Duration::from_secs(60),
            metadata: HashMap::new(),
        },
    );

    // Add recent node
    service.discovered_nodes.insert(
        "new_node".to_string(),
        NodeInfo {
            node_id: "new_node".to_string(),
            node_type: "sensor".to_string(),
            host: "192.168.1.101".to_string(),
            port: 8080,
            last_seen: SystemTime::now(),
            metadata: HashMap::new(),
        },
    );

    assert_eq!(service.node_count(), 2);

    // Cleanup nodes older than 30 seconds
    let removed = service.cleanup_stale_nodes(Duration::from_secs(30));
    assert_eq!(removed, 1);
    assert_eq!(service.node_count(), 1);

    // Verify correct node was kept
    assert!(service.get_node("new_node").is_some());
    assert!(service.get_node("old_node").is_none());
}
