//! E2E trace tests: thread/scheduler operations (#572).
//!
//! Covers multi-turn state persistence, undo/redo, and concurrent dispatch.
//! Tests for thread_interruption and max_parallel_exceeded are deferred.

#[cfg(feature = "libsql")]
mod support;

#[cfg(feature = "libsql")]
mod tests {
    use std::time::Duration;

    use crate::support::test_rig::TestRigBuilder;
    use crate::support::trace_llm::LlmTrace;

    // -----------------------------------------------------------------------
    // Test 1: multi_turn_state
    // -----------------------------------------------------------------------

    #[tokio::test]
    async fn multi_turn_state() {
        let trace = LlmTrace::from_file(concat!(
            env!("CARGO_MANIFEST_DIR"),
            "/tests/fixtures/llm_traces/threading/multi_turn_state.json"
        ))
        .expect("failed to load multi_turn_state.json");

        let rig = TestRigBuilder::new()
            .with_trace(trace.clone())
            .build()
            .await;

        let all_responses = rig
            .run_and_verify_trace(&trace, Duration::from_secs(30))
            .await;

        // Should have 3 turns of responses.
        assert_eq!(
            all_responses.len(),
            3,
            "Expected 3 turns, got {}",
            all_responses.len()
        );

        // Verify memory tools were used across turns.
        let started = rig.tool_calls_started();
        let mw_count = started
            .iter()
            .filter(|n| n.as_str() == "memory_write")
            .count();
        let ms_count = started
            .iter()
            .filter(|n| n.as_str() == "memory_search")
            .count();
        assert!(
            mw_count >= 2,
            "Expected >= 2 memory_write calls: {started:?}"
        );
        assert!(
            ms_count >= 1,
            "Expected >= 1 memory_search calls: {started:?}"
        );

        // Verify DB is accessible (conversation persistence is tested by
        // the agent's internal session management).
        let _db = rig.database();

        rig.shutdown();
    }

    // -----------------------------------------------------------------------
    // Test 2: thread_interruption -- DEFERRED
    // -----------------------------------------------------------------------
    // Needs interrupt signaling infrastructure in TestChannel.

    // -----------------------------------------------------------------------
    // Test 3: undo_redo_cycle
    // -----------------------------------------------------------------------

    #[tokio::test]
    async fn undo_redo_cycle() {
        let trace = LlmTrace::from_file(concat!(
            env!("CARGO_MANIFEST_DIR"),
            "/tests/fixtures/llm_traces/threading/undo_redo.json"
        ))
        .expect("failed to load undo_redo.json");

        let rig = TestRigBuilder::new()
            .with_trace(trace.clone())
            .build()
            .await;

        let all_responses = rig
            .run_and_verify_trace(&trace, Duration::from_secs(30))
            .await;

        // Should get responses for all 3 turns (echo, /undo, /redo).
        assert_eq!(
            all_responses.len(),
            3,
            "Expected 3 turn responses, got {}",
            all_responses.len()
        );

        rig.shutdown();
    }

    // -----------------------------------------------------------------------
    // Test 4: concurrent_dispatch
    // -----------------------------------------------------------------------

    #[tokio::test]
    async fn concurrent_dispatch() {
        let trace = LlmTrace::from_file(concat!(
            env!("CARGO_MANIFEST_DIR"),
            "/tests/fixtures/llm_traces/threading/concurrent_dispatch.json"
        ))
        .expect("failed to load concurrent_dispatch.json");

        let rig = TestRigBuilder::new()
            .with_trace(trace.clone())
            .build()
            .await;

        let all_responses = rig
            .run_and_verify_trace(&trace, Duration::from_secs(30))
            .await;

        // Should have 2 turns.
        assert_eq!(
            all_responses.len(),
            2,
            "Expected 2 turns, got {}",
            all_responses.len()
        );

        // Both echo calls should have succeeded.
        let completed = rig.tool_calls_completed();
        let echo_successes = completed
            .iter()
            .filter(|(name, ok)| name == "echo" && *ok)
            .count();
        assert!(
            echo_successes >= 2,
            "Expected >= 2 successful echo calls: {completed:?}"
        );

        rig.shutdown();
    }

    // -----------------------------------------------------------------------
    // Test 5: max_parallel_exceeded -- DEFERRED
    // -----------------------------------------------------------------------
    // Needs max_parallel config exposed through TestRigBuilder.
}
