//! TEST-003 through TEST-007: Advanced ACP Tests
//!
//! This file contains advanced integration tests covering:
//! - TEST-003: Session lifecycle tests (create, prompt, cancel, load)
//! - TEST-004: Error condition tests (network failures, invalid JSON, timeouts)
//! - TEST-005: Reconnection tests (during init, active session, max retries)
//! - TEST-006: Edge case tests (empty messages, long messages, rapid-fire, leaks)
//! - TEST-007: Performance tests (latency, throughput, memory, concurrent sessions)

#![cfg(feature = "server")]

use dirigent_core::connectors::acp::{AcpConfig, AcpConnector};
use dirigent_core::connectors::{Connector, ConnectorCommand};
use dirigent_core::types::ConnectorState;
use dirigent_protocol::Event;
use std::path::PathBuf;
use std::time::{Duration, Instant};
use tokio::time::timeout;

// ============================================================================
// Test Helpers
// ============================================================================

fn test_fixture_path() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("tests")
        .join("fixtures")
        .join("acp_test.yaml")
}

fn mocker_binary() -> String {
    let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let project_root = manifest_dir.parent().unwrap().parent().unwrap();
    let debug_path = project_root
        .join("target")
        .join("debug")
        .join("dirigate.exe");

    if debug_path.exists() {
        debug_path.to_string_lossy().to_string()
    } else {
        "cargo".to_string()
    }
}

fn mocker_args() -> Vec<String> {
    let bin = mocker_binary();
    let fixture = test_fixture_path();

    if bin == "cargo" {
        vec![
            "run".to_string(),
            "--package".to_string(),
            "dirigate".to_string(),
            "--".to_string(),
            "serve".to_string(),
            "--stdio".to_string(),
            "--fixtures".to_string(),
            fixture.to_string_lossy().to_string(),
        ]
    } else {
        vec![
            "serve".to_string(),
            "--stdio".to_string(),
            "--fixtures".to_string(),
            fixture.to_string_lossy().to_string(),
        ]
    }
}

fn create_test_connector(id: &str) -> AcpConnector {
    let config = AcpConfig::stdio(mocker_binary(), mocker_args())
        .with_retry_max_attempts(3)
        .with_retry_initial_delay(Duration::from_millis(500));

    AcpConnector::new(
        id.to_string(),
        uuid::Uuid::nil(),
        "Test ACP Connector".to_string(),
        config,
        dirigent_core::sharing::bus::SharingBus::new(),
    )
    .expect("Failed to create connector")
}

async fn wait_for_event<F>(
    events_rx: &mut tokio::sync::broadcast::Receiver<Event>,
    predicate: F,
    timeout_duration: Duration,
) -> anyhow::Result<Event>
where
    F: Fn(&Event) -> bool,
{
    let result = timeout(timeout_duration, async {
        loop {
            match events_rx.recv().await {
                Ok(event) => {
                    if predicate(&event) {
                        return Ok(event);
                    }
                }
                Err(e) => return Err(anyhow::anyhow!("Recv error: {}", e)),
            }
        }
    })
    .await;

    match result {
        Ok(Ok(event)) => Ok(event),
        Ok(Err(e)) => Err(e),
        Err(_) => Err(anyhow::anyhow!("Timeout")),
    }
}

// ============================================================================
// TEST-003: Session Lifecycle Tests
// ============================================================================

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t003_01_session_create_flow() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("lifecycle-create");
    let mut events = connector.subscribe();
    let handle = connector.start_task().await;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;

    // Create session
    connector
        .command_tx()
        .send(ConnectorCommand::CreateSession {
            cwd: None,
            project_id: None,
            ownership: dirigent_protocol::SessionOwnership::internal(),
        })
        .await?;

    // Verify session created
    let session = match wait_for_event(
        &mut events,
        |e| matches!(e, Event::SessionCreated { .. }),
        Duration::from_secs(5),
    )
    .await?
    {
        Event::SessionCreated { session, .. } => session,
        _ => anyhow::bail!("Expected SessionCreated"),
    };

    assert_eq!(session.title, "Lifecycle Test");
    tracing::info!("✓ Session created successfully");

    connector.stop();
    timeout(Duration::from_secs(5), handle).await??;
    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t003_02_session_prompt_flow() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("lifecycle-prompt");
    let mut events = connector.subscribe();
    let handle = connector.start_task().await;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;

    // Create session
    connector
        .command_tx()
        .send(ConnectorCommand::CreateSession {
            cwd: None,
            project_id: None,
            ownership: dirigent_protocol::SessionOwnership::internal(),
        })
        .await?;

    let session_id = match wait_for_event(
        &mut events,
        |e| matches!(e, Event::SessionCreated { .. }),
        Duration::from_secs(5),
    )
    .await?
    {
        Event::SessionCreated { session, .. } => session.id,
        _ => anyhow::bail!("Expected SessionCreated"),
    };

    // Send prompt
    connector
        .command_tx()
        .send(ConnectorCommand::SendMessage {
            session_id: session_id.clone(),
            text: "Test prompt".to_string(),
        })
        .await?;

    // Verify message flow: Started -> Content -> Completed
    wait_for_event(
        &mut events,
        |e| matches!(e, Event::MessageStarted { .. }),
        Duration::from_secs(5),
    )
    .await?;
    tracing::info!("✓ Message started");

    // Wait for content or completion
    let mut got_response = false;
    for _ in 0..10 {
        if let Ok(event) = timeout(Duration::from_secs(1), events.recv()).await {
            match event? {
                Event::SessionUpdate { .. } => {
                    got_response = true;
                    break;
                }
                Event::MessageCompleted { .. } => {
                    got_response = true;
                    break;
                }
                _ => {}
            }
        }
    }

    assert!(got_response, "Should receive response");
    tracing::info!("✓ Prompt flow completed");

    connector.stop();
    timeout(Duration::from_secs(5), handle).await??;
    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t003_03_session_cancel_flow() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("lifecycle-cancel");
    let mut events = connector.subscribe();
    let handle = connector.start_task().await;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;

    // Setup
    connector
        .command_tx()
        .send(ConnectorCommand::CreateSession {
            cwd: None,
            project_id: None,
            ownership: dirigent_protocol::SessionOwnership::internal(),
        })
        .await?;

    let session_id = match wait_for_event(
        &mut events,
        |e| matches!(e, Event::SessionCreated { .. }),
        Duration::from_secs(5),
    )
    .await?
    {
        Event::SessionCreated { session, .. } => session.id,
        _ => anyhow::bail!("Expected SessionCreated"),
    };

    // Start message
    connector
        .command_tx()
        .send(ConnectorCommand::SendMessage {
            session_id: session_id.clone(),
            text: "Long message".to_string(),
        })
        .await?;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::MessageStarted { .. }),
        Duration::from_secs(5),
    )
    .await?;

    // Cancel
    connector
        .command_tx()
        .send(ConnectorCommand::CancelGeneration { session_id })
        .await?;

    tracing::info!("✓ Cancel sent successfully");

    connector.stop();
    timeout(Duration::from_secs(5), handle).await??;
    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t003_04_session_load_flow() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("lifecycle-load");
    let mut events = connector.subscribe();
    let handle = connector.start_task().await;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;

    // Load existing session from fixture
    connector
        .command_tx()
        .send(ConnectorCommand::LoadSession {
            session_id: "test-session-1".to_string(),
            cwd: ".".to_string(),
            mcp_servers: None,
        })
        .await?;

    let session = match wait_for_event(
        &mut events,
        |e| matches!(e, Event::SessionCreated { .. }),
        Duration::from_secs(5),
    )
    .await?
    {
        Event::SessionCreated { session, .. } => session,
        _ => anyhow::bail!("Expected SessionCreated"),
    };

    assert_eq!(session.id, "test-session-1");
    tracing::info!("✓ Session loaded from fixture");

    connector.stop();
    timeout(Duration::from_secs(5), handle).await??;
    Ok(())
}

// ============================================================================
// TEST-004: Error Condition Tests
// ============================================================================

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t004_01_invalid_binary_path() {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let config = AcpConfig::stdio("nonexistent-binary".to_string(), vec![]);
    let result = AcpConnector::new(
        "error-test".to_string(),
        uuid::Uuid::nil(),
        "Error Test".to_string(),
        config,
        dirigent_core::sharing::bus::SharingBus::new(),
    );

    // Should fail validation or fail to start
    // Either is acceptable - the key is it doesn't panic
    if let Ok(connector) = result {
        let mut events = connector.subscribe();
        let _handle = connector.start_task().await;

        // Should either fail to connect or error out
        let result = timeout(Duration::from_secs(5), events.recv()).await;
        match result {
            Ok(Ok(Event::Error { .. })) => {
                tracing::info!("✓ Error handled gracefully");
            }
            Ok(Ok(Event::Connected)) => {
                panic!("Should not connect to nonexistent binary");
            }
            _ => {
                tracing::info!("✓ Connection failed as expected");
            }
        }
    } else {
        tracing::info!("✓ Config validation caught invalid binary");
    }
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t004_02_timeout_handling() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    // Create connector with very short timeout
    let config = AcpConfig::stdio(mocker_binary(), mocker_args())
        .with_request_timeout(Duration::from_millis(100));

    let connector = AcpConnector::new(
        "timeout-test".to_string(),
        uuid::Uuid::nil(),
        "Timeout Test".to_string(),
        config,
        dirigent_core::sharing::bus::SharingBus::new(),
    )?;
    let mut events = connector.subscribe();
    let _handle = connector.start_task().await;

    // Try to connect - might timeout during handshake
    match timeout(Duration::from_secs(10), events.recv()).await {
        Ok(Ok(Event::Connected)) => {
            tracing::info!("✓ Connected despite short timeout");
        }
        Ok(Ok(Event::Error { message })) => {
            tracing::info!("✓ Timeout error handled: {}", message);
        }
        Err(_) => {
            tracing::info!("✓ Timeout occurred as expected");
        }
        _ => {}
    }

    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t004_03_connection_state_on_error() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let config = AcpConfig::stdio("nonexistent".to_string(), vec![]);

    if let Ok(connector) = AcpConnector::new(
        "state-test".to_string(),
        uuid::Uuid::nil(),
        "State Test".to_string(),
        config,
        dirigent_core::sharing::bus::SharingBus::new(),
    ) {
        let state = connector.state_arc();
        let _handle = connector.start_task().await;

        // Wait a bit for state to update
        tokio::time::sleep(Duration::from_secs(2)).await;

        let current_state = state.read().await;
        match *current_state {
            ConnectorState::Error { .. } | ConnectorState::Stopped => {
                tracing::info!("✓ State correctly reflects error: {:?}", *current_state);
            }
            _ => {
                tracing::warn!("State is: {:?}", *current_state);
            }
        }
    }

    Ok(())
}

// ============================================================================
// TEST-005: Reconnection Tests
// ============================================================================

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t005_01_reconnect_after_disconnect() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("reconnect-test");
    let mut events = connector.subscribe();
    let handle = connector.start_task().await;

    // Wait for initial connection
    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;
    tracing::info!("✓ Initial connection established");

    // Stop and restart
    connector.stop();
    timeout(Duration::from_secs(5), handle).await??;

    // Create new connector with same config
    let connector2 = create_test_connector("reconnect-test-2");
    let mut events2 = connector2.subscribe();
    let handle2 = connector2.start_task().await;

    // Should reconnect
    wait_for_event(
        &mut events2,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;
    tracing::info!("✓ Reconnected successfully");

    connector2.stop();
    timeout(Duration::from_secs(5), handle2).await??;
    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t005_02_max_retries_respected() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let config = AcpConfig::stdio("nonexistent".to_string(), vec![])
        .with_retry_max_attempts(2)
        .with_retry_initial_delay(Duration::from_millis(100));

    if let Ok(connector) = AcpConnector::new(
        "retry-test".to_string(),
        uuid::Uuid::nil(),
        "Retry Test".to_string(),
        config,
        dirigent_core::sharing::bus::SharingBus::new(),
    ) {
        let _events = connector.subscribe();
        let _handle = connector.start_task().await;

        // Should eventually give up after max retries
        tokio::time::sleep(Duration::from_secs(3)).await;

        // Check state is error or stopped
        let state = connector.state_arc();
        let current = state.read().await;
        match *current {
            ConnectorState::Error { .. } | ConnectorState::Stopped => {
                tracing::info!("✓ Max retries respected, connector stopped");
            }
            _ => {
                tracing::warn!("State: {:?}", *current);
            }
        }
    }

    Ok(())
}

// ============================================================================
// TEST-006: Edge Case Tests
// ============================================================================

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t006_01_empty_message() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("empty-msg-test");
    let mut events = connector.subscribe();
    let handle = connector.start_task().await;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;

    connector
        .command_tx()
        .send(ConnectorCommand::CreateSession {
            cwd: None,
            project_id: None,
            ownership: dirigent_protocol::SessionOwnership::internal(),
        })
        .await?;

    let session_id = match wait_for_event(
        &mut events,
        |e| matches!(e, Event::SessionCreated { .. }),
        Duration::from_secs(5),
    )
    .await?
    {
        Event::SessionCreated { session, .. } => session.id,
        _ => anyhow::bail!("Expected SessionCreated"),
    };

    // Send empty message
    connector
        .command_tx()
        .send(ConnectorCommand::SendMessage {
            session_id,
            text: "".to_string(),
        })
        .await?;

    // Should handle gracefully (either respond or error)
    let result = timeout(Duration::from_secs(3), events.recv()).await;
    tracing::info!("✓ Empty message handled: {:?}", result.is_ok());

    connector.stop();
    timeout(Duration::from_secs(5), handle).await??;
    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t006_02_very_long_message() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("long-msg-test");
    let mut events = connector.subscribe();
    let handle = connector.start_task().await;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;

    connector
        .command_tx()
        .send(ConnectorCommand::CreateSession {
            cwd: None,
            project_id: None,
            ownership: dirigent_protocol::SessionOwnership::internal(),
        })
        .await?;

    let session_id = match wait_for_event(
        &mut events,
        |e| matches!(e, Event::SessionCreated { .. }),
        Duration::from_secs(5),
    )
    .await?
    {
        Event::SessionCreated { session, .. } => session.id,
        _ => anyhow::bail!("Expected SessionCreated"),
    };

    // Send very long message (10KB)
    let long_content = "x".repeat(10_000);
    connector
        .command_tx()
        .send(ConnectorCommand::SendMessage {
            session_id,
            text: long_content,
        })
        .await?;

    // Should handle without issue
    wait_for_event(
        &mut events,
        |e| matches!(e, Event::MessageStarted { .. }),
        Duration::from_secs(5),
    )
    .await?;
    tracing::info!("✓ Long message handled");

    connector.stop();
    timeout(Duration::from_secs(5), handle).await??;
    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t006_03_rapid_fire_requests() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("rapid-test");
    let mut events = connector.subscribe();
    let handle = connector.start_task().await;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;

    connector
        .command_tx()
        .send(ConnectorCommand::CreateSession {
            cwd: None,
            project_id: None,
            ownership: dirigent_protocol::SessionOwnership::internal(),
        })
        .await?;

    let session_id = match wait_for_event(
        &mut events,
        |e| matches!(e, Event::SessionCreated { .. }),
        Duration::from_secs(5),
    )
    .await?
    {
        Event::SessionCreated { session, .. } => session.id,
        _ => anyhow::bail!("Expected SessionCreated"),
    };

    // Send 10 messages rapidly
    for i in 0..10 {
        connector
            .command_tx()
            .send(ConnectorCommand::SendMessage {
                session_id: session_id.clone(),
                text: format!("Message {}", i),
            })
            .await?;
    }

    tracing::info!("✓ Rapid-fire messages sent without blocking");

    // Just verify we don't crash
    tokio::time::sleep(Duration::from_secs(2)).await;

    connector.stop();
    timeout(Duration::from_secs(5), handle).await??;
    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t006_04_resource_cleanup() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    // Create and destroy multiple connectors
    for i in 0..5 {
        let connector = create_test_connector(&format!("cleanup-test-{}", i));
        let handle = connector.start_task().await;

        tokio::time::sleep(Duration::from_millis(500)).await;

        connector.stop();
        let _ = timeout(Duration::from_secs(2), handle).await;

        tracing::info!("✓ Connector {} cleaned up", i);
    }

    tracing::info!("✓ All resources cleaned up successfully");
    Ok(())
}

// ============================================================================
// TEST-007: Performance Tests
// ============================================================================

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t007_01_connection_latency() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("latency-test");
    let mut events = connector.subscribe();

    let start = Instant::now();
    let _handle = connector.start_task().await;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;

    let latency = start.elapsed();
    tracing::info!("✓ Connection latency: {:?}", latency);

    // Should connect within 5 seconds
    assert!(latency < Duration::from_secs(5), "Connection took too long");

    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t007_02_request_roundtrip() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("roundtrip-test");
    let mut events = connector.subscribe();
    let handle = connector.start_task().await;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;

    // Measure session creation time
    let start = Instant::now();
    connector
        .command_tx()
        .send(ConnectorCommand::CreateSession {
            cwd: None,
            project_id: None,
            ownership: dirigent_protocol::SessionOwnership::internal(),
        })
        .await?;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::SessionCreated { .. }),
        Duration::from_secs(5),
    )
    .await?;
    let roundtrip = start.elapsed();

    tracing::info!("✓ Session creation roundtrip: {:?}", roundtrip);
    assert!(roundtrip < Duration::from_secs(2), "Roundtrip too slow");

    connector.stop();
    timeout(Duration::from_secs(5), handle).await??;
    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t007_03_event_delivery_latency() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("event-latency-test");
    let mut events = connector.subscribe();
    let handle = connector.start_task().await;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;

    connector
        .command_tx()
        .send(ConnectorCommand::CreateSession {
            cwd: None,
            project_id: None,
            ownership: dirigent_protocol::SessionOwnership::internal(),
        })
        .await?;

    let session_id = match wait_for_event(
        &mut events,
        |e| matches!(e, Event::SessionCreated { .. }),
        Duration::from_secs(5),
    )
    .await?
    {
        Event::SessionCreated { session, .. } => session.id,
        _ => anyhow::bail!("Expected SessionCreated"),
    };

    // Measure event delivery
    let start = Instant::now();
    connector
        .command_tx()
        .send(ConnectorCommand::SendMessage {
            session_id,
            text: "Test".to_string(),
        })
        .await?;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::MessageStarted { .. }),
        Duration::from_secs(5),
    )
    .await?;
    let delivery_time = start.elapsed();

    tracing::info!("✓ Event delivery latency: {:?}", delivery_time);
    assert!(
        delivery_time < Duration::from_secs(1),
        "Event delivery too slow"
    );

    connector.stop();
    timeout(Duration::from_secs(5), handle).await??;
    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t007_04_concurrent_session_capacity() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    let connector = create_test_connector("capacity-test");
    let mut events = connector.subscribe();
    let handle = connector.start_task().await;

    wait_for_event(
        &mut events,
        |e| matches!(e, Event::Connected),
        Duration::from_secs(10),
    )
    .await?;

    // Create 10 sessions
    let start = Instant::now();
    let mut session_ids = Vec::new();

    for _i in 0..10 {
        connector
            .command_tx()
            .send(ConnectorCommand::CreateSession {
                cwd: None,
                project_id: None,
                ownership: dirigent_protocol::SessionOwnership::internal(),
            })
            .await?;

        if let Event::SessionCreated { session, .. } = wait_for_event(
            &mut events,
            |e| matches!(e, Event::SessionCreated { .. }),
            Duration::from_secs(5),
        )
        .await?
        {
            session_ids.push(session.id);
        }
    }

    let total_time = start.elapsed();
    tracing::info!(
        "✓ Created {} sessions in {:?}",
        session_ids.len(),
        total_time
    );
    assert_eq!(session_ids.len(), 10);

    connector.stop();
    timeout(Duration::from_secs(5), handle).await??;
    Ok(())
}

#[tokio::test]
#[ignore = "Requires mocker binary"]
async fn test_t007_05_memory_stability() -> anyhow::Result<()> {
    tracing_subscriber::fmt().with_test_writer().try_init().ok();

    // Run 20 create/destroy cycles to check for memory leaks
    for i in 0..20 {
        let connector = create_test_connector(&format!("mem-test-{}", i));
        let mut events = connector.subscribe();
        let handle = connector.start_task().await;

        if let Ok(_) = timeout(
            Duration::from_secs(5),
            wait_for_event(
                &mut events,
                |e| matches!(e, Event::Connected),
                Duration::from_secs(10),
            ),
        )
        .await
        {
            tracing::info!("Cycle {} connected", i);
        }

        connector.stop();
        let _ = timeout(Duration::from_secs(2), handle).await;
    }

    tracing::info!("✓ 20 cycles completed without crash (manual memory check needed)");
    Ok(())
}
