use dirigent_testing::{load_fixture, Direction};

#[test]
fn test_zed_claude_fixture_loads() {
    let replay = load_fixture("zed_claude_session.json").unwrap();
    assert!(!replay.messages.is_empty());
    assert!(!replay.client_messages().is_empty());
    assert!(!replay.agent_messages().is_empty());
}

#[test]
fn test_zed_claude_starts_with_initialize() {
    let replay = load_fixture("zed_claude_session.json").unwrap();
    let first = &replay.messages[0];
    assert_eq!(first.direction, Direction::ClientToAgent);
    let method = first.payload.get("method").and_then(|m| m.as_str());
    assert_eq!(method, Some("initialize"));
}

#[test]
fn test_zed_claude_message_counts() {
    let replay = load_fixture("zed_claude_session.json").unwrap();
    // 3 client messages: initialize, session/load, session/list
    assert_eq!(replay.client_messages().len(), 3);
    // 6 agent messages: initialize response, 2x session/update notifications,
    // session/load response, available_commands_update, session/list response
    assert_eq!(replay.agent_messages().len(), 6);
    // Total: 9 messages
    assert_eq!(replay.messages.len(), 9);
}

#[test]
fn test_zed_claude_initialize_has_client_info() {
    let replay = load_fixture("zed_claude_session.json").unwrap();
    let init = &replay.messages[0].payload;
    let client_info = init
        .pointer("/params/clientInfo/name")
        .and_then(|v| v.as_str());
    assert_eq!(client_info, Some("zed"));
}

#[test]
fn test_zed_claude_initialize_response_has_agent_info() {
    let replay = load_fixture("zed_claude_session.json").unwrap();
    let init_resp = &replay.messages[1].payload;
    assert_eq!(init_resp.get("id").and_then(|v| v.as_u64()), Some(0));
    let agent_name = init_resp
        .pointer("/params/agentInfo/name")
        .and_then(|v| v.as_str());
    assert_eq!(agent_name, Some("@zed-industries/claude-agent-acp"));
}

#[test]
fn test_zed_claude_session_load_flow() {
    let replay = load_fixture("zed_claude_session.json").unwrap();
    // Message at index 2 is the session/load request
    let session_load = &replay.messages[2];
    assert_eq!(session_load.direction, Direction::ClientToAgent);
    let method = session_load
        .payload
        .get("method")
        .and_then(|m| m.as_str());
    assert_eq!(method, Some("session/load"));

    let session_id = session_load
        .payload
        .pointer("/params/sessionId")
        .and_then(|v| v.as_str());
    assert_eq!(
        session_id,
        Some("cb878ad6-d72b-43c9-93e0-8228f309a786")
    );
}

#[test]
fn test_zed_claude_contains_session_list() {
    let replay = load_fixture("zed_claude_session.json").unwrap();
    let list_request = replay
        .messages
        .iter()
        .find(|m| {
            m.direction == Direction::ClientToAgent
                && m.payload.get("method").and_then(|v| v.as_str()) == Some("session/list")
        })
        .expect("should contain a session/list request");

    assert_eq!(list_request.payload.get("id").and_then(|v| v.as_u64()), Some(2));

    // Find the matching response
    let list_response = replay
        .messages
        .iter()
        .find(|m| {
            m.direction == Direction::AgentToClient
                && m.payload.get("method").and_then(|v| v.as_str()) == Some("session/list")
                && m.payload.get("id").and_then(|v| v.as_u64()) == Some(2)
        })
        .expect("should contain a session/list response");

    let sessions = list_response
        .payload
        .pointer("/params/sessions")
        .and_then(|v| v.as_array())
        .expect("should have sessions array");
    assert_eq!(sessions.len(), 2);
}

#[test]
fn test_zed_claude_has_delay_timings() {
    let replay = load_fixture("zed_claude_session.json").unwrap();
    // First message (initialize request from client) has no delay
    assert!(replay.messages[0].delay_ms.is_none());
    // Most subsequent messages should have delay_ms set
    let messages_with_delay = replay
        .messages
        .iter()
        .filter(|m| m.delay_ms.is_some())
        .count();
    assert!(
        messages_with_delay > 0,
        "at least some messages should have delay timing"
    );
}

#[test]
fn test_zed_claude_serde_roundtrip() {
    let replay = load_fixture("zed_claude_session.json").unwrap();
    let json = serde_json::to_string_pretty(&replay).unwrap();
    let parsed: dirigent_testing::AcpReplay = serde_json::from_str(&json).unwrap();
    assert_eq!(parsed.name, replay.name);
    assert_eq!(parsed.messages.len(), replay.messages.len());

    for (original, roundtripped) in replay.messages.iter().zip(parsed.messages.iter()) {
        assert_eq!(original.direction, roundtripped.direction);
        assert_eq!(original.payload, roundtripped.payload);
        assert_eq!(original.delay_ms, roundtripped.delay_ms);
    }
}
