//! Tests for TopologyService

use mecha10_cli::services::topology::{TopicRef, TopologyService};
use std::collections::HashMap;
use std::path::PathBuf;

#[test]
fn test_parse_redis_url() {
    let service = TopologyService::new(PathBuf::from("."));

    let info = service.parse_redis_url("redis://localhost:6379").unwrap();
    assert_eq!(info.host, "localhost");
    assert_eq!(info.port, 6379);

    let info = service.parse_redis_url("redis://192.168.1.100:6380").unwrap();
    assert_eq!(info.host, "192.168.1.100");
    assert_eq!(info.port, 6380);
}

#[test]
fn test_extract_topic_definitions() {
    let service = TopologyService::new(PathBuf::from("."));

    let source = r#"
        pub const GREETINGS_TOPIC: Topic<Greeting> = Topic::new("/example/greetings");
        pub const STATUS_TOPIC: Topic<Status> = Topic::new("/robot/status");
    "#;

    let topics = service.extract_topic_definitions(source);
    assert_eq!(topics.len(), 2);
    assert_eq!(topics["GREETINGS_TOPIC"].path, "/example/greetings");
    assert_eq!(topics["GREETINGS_TOPIC"].message_type, Some("Greeting".to_string()));
}

#[test]
fn test_extract_publish_calls() {
    let service = TopologyService::new(PathBuf::from("."));

    let mut topics = HashMap::new();
    topics.insert(
        "TEST_TOPIC".to_string(),
        TopicRef {
            path: "/test".to_string(),
            message_type: Some("TestMsg".to_string()),
        },
    );

    let source = r#"
        ctx.publish_to(TEST_TOPIC, &msg).await?;
    "#;

    let publishes = service.extract_publish_calls(source, &topics);
    assert_eq!(publishes.len(), 1);
    assert_eq!(publishes[0].path, "/test");
}

#[test]
fn test_extract_subscribe_calls() {
    let service = TopologyService::new(PathBuf::from("."));

    let mut topics = HashMap::new();
    topics.insert(
        "TEST_TOPIC".to_string(),
        TopicRef {
            path: "/test".to_string(),
            message_type: Some("TestMsg".to_string()),
        },
    );

    let source = r#"
        let mut receiver = ctx.subscribe::<TestMsg>(TEST_TOPIC).await?;
    "#;

    let subscribes = service.extract_subscribe_calls(source, &topics);
    assert_eq!(subscribes.len(), 1);
    assert_eq!(subscribes[0].path, "/test");
}

#[test]
fn test_extract_publish_calls_with_module_prefix() {
    let service = TopologyService::new(PathBuf::from("."));

    let mut topics = HashMap::new();
    topics.insert(
        "CMD_VEL".to_string(),
        TopicRef {
            path: "/cmd_vel".to_string(),
            message_type: Some("Twist".to_string()),
        },
    );
    topics.insert(
        "MOTOR_CMD_VEL".to_string(),
        TopicRef {
            path: "/motor/cmd_vel".to_string(),
            message_type: Some("Twist".to_string()),
        },
    );

    let source = r#"
        ctx.publish_to(topics::CMD_VEL, &twist).await?;
        ctx.publish_to(topics::MOTOR_CMD_VEL, &self.current_twist).await?;
    "#;

    let publishes = service.extract_publish_calls(source, &topics);
    assert_eq!(publishes.len(), 2);
    assert!(publishes.iter().any(|p| p.path == "/cmd_vel"));
    assert!(publishes.iter().any(|p| p.path == "/motor/cmd_vel"));
}

#[test]
fn test_extract_subscribe_calls_with_module_prefix() {
    let service = TopologyService::new(PathBuf::from("."));

    let mut topics = HashMap::new();
    topics.insert(
        "CMD_VEL".to_string(),
        TopicRef {
            path: "/cmd_vel".to_string(),
            message_type: Some("Twist".to_string()),
        },
    );

    let source = r#"
        let mut cmd_vel_rx = ctx.subscribe(topics::CMD_VEL).await?;
    "#;

    let subscribes = service.extract_subscribe_calls(source, &topics);
    assert_eq!(subscribes.len(), 1);
    assert_eq!(subscribes[0].path, "/cmd_vel");
}
