/// Integration test to verify the public API of dirigent_protocol
/// This ensures all types are accessible via `use dirigent_protocol::{...}`
use dirigent_protocol::{
    ContentBlock, Meta, ProviderMeta, SessionUpdate, ToolCall, ToolCallId, ToolCallStatus,
};

#[test]
fn test_content_block_import() {
    let text = ContentBlock::Text {
        text: "test".to_string(),
    };
    assert!(matches!(text, ContentBlock::Text { .. }));

    let resource = ContentBlock::ResourceLink {
        uri: "file:///test.txt".to_string(),
        name: None,
        mime_type: None,
    };
    assert!(matches!(resource, ContentBlock::ResourceLink { .. }));
}

#[test]
fn test_meta_import() {
    let meta = Meta::default();
    assert_eq!(meta.provider, None);
    assert!(meta.extra.is_empty());
}

#[test]
fn test_provider_meta_import() {
    let provider = ProviderMeta {
        name: "test".to_string(),
        original_ids: None,
        raw_excerpt: None,
    };
    assert_eq!(provider.name, "test");
}

#[test]
fn test_tool_call_types_import() {
    let tool_call_id: ToolCallId = "call_123".to_string();
    assert_eq!(tool_call_id, "call_123");

    let status = ToolCallStatus::Pending;
    assert_eq!(status, ToolCallStatus::Pending);

    let tool_call = ToolCall {
        id: tool_call_id,
        tool_name: "test".to_string(),
        status: ToolCallStatus::Running,
        content: vec![],
        raw_input: None,
        raw_output: None,
        title: None,
        error: None,
        metadata: None,
        origin: None,
    };
    assert_eq!(tool_call.tool_name, "test");
    assert_eq!(tool_call.status, ToolCallStatus::Running);
}

#[test]
fn test_session_update_import() {
    let update = SessionUpdate::UserMessageChunk {
        message_id: "msg_1".to_string(),
        content: ContentBlock::Text {
            text: "Hello".to_string(),
        },
        _meta: None,
    };
    assert!(matches!(update, SessionUpdate::UserMessageChunk { .. }));
}

#[test]
fn test_all_session_update_variants() {
    // Test all SessionUpdate variants can be constructed
    let user_chunk = SessionUpdate::UserMessageChunk {
        message_id: "m1".to_string(),
        content: ContentBlock::Text {
            text: "user".to_string(),
        },
        _meta: None,
    };

    let agent_chunk = SessionUpdate::AgentMessageChunk {
        message_id: "m2".to_string(),
        content: ContentBlock::Text {
            text: "agent".to_string(),
        },
        _meta: None,
    };

    let thought_chunk = SessionUpdate::AgentThoughtChunk {
        message_id: "m3".to_string(),
        content: ContentBlock::Text {
            text: "thinking".to_string(),
        },
        _meta: None,
    };

    let tool_call = SessionUpdate::ToolCall {
        message_id: "m4".to_string(),
        tool_call: ToolCall {
            id: "c1".to_string(),
            tool_name: "test".to_string(),
            status: ToolCallStatus::Pending,
            content: vec![],
            raw_input: None,
            raw_output: None,
            title: None,
            error: None,
            metadata: None,
            origin: None,
        },
        _meta: None,
    };

    let tool_call_update = SessionUpdate::ToolCallUpdate {
        message_id: "m5".to_string(),
        tool_call_id: "c2".to_string(),
        tool_call: ToolCall {
            id: "c2".to_string(),
            tool_name: "test".to_string(),
            status: ToolCallStatus::Completed,
            content: vec![],
            raw_input: None,
            raw_output: None,
            title: None,
            error: None,
            metadata: None,
            origin: None,
        },
        _meta: None,
    };

    // If we got here, all variants can be constructed
    assert!(matches!(user_chunk, SessionUpdate::UserMessageChunk { .. }));
    assert!(matches!(
        agent_chunk,
        SessionUpdate::AgentMessageChunk { .. }
    ));
    assert!(matches!(
        thought_chunk,
        SessionUpdate::AgentThoughtChunk { .. }
    ));
    assert!(matches!(tool_call, SessionUpdate::ToolCall { .. }));
    assert!(matches!(
        tool_call_update,
        SessionUpdate::ToolCallUpdate { .. }
    ));
}

#[test]
fn test_serialization_works_with_public_api() {
    // Verify that types imported from the public API can be serialized
    let update = SessionUpdate::UserMessageChunk {
        message_id: "msg_test".to_string(),
        content: ContentBlock::Text {
            text: "test message".to_string(),
        },
        _meta: Some(Meta {
            provider: Some(ProviderMeta {
                name: "test_provider".to_string(),
                original_ids: None,
                raw_excerpt: None,
            }),
            extra: Default::default(),
        }),
    };

    let json = serde_json::to_string(&update).unwrap();
    assert!(json.contains("msg_test"));
    assert!(json.contains("test message"));
    assert!(json.contains("test_provider"));

    // Verify round-trip
    let deserialized: SessionUpdate = serde_json::from_str(&json).unwrap();
    assert_eq!(update, deserialized);
}
