# Chat Provider Architecture

This module provides an abstraction layer for chat provider integrations, enabling support for multiple platforms (Slack, Microsoft Teams, etc.) through a unified interface.

## Architecture Overview

```
┌────────────────────┐
│   Routes Layer     │  chat/generic.py, chat/questionnaire.py
└────────────────────┘
          │
          ▼
┌────────────────────┐
│      Factory       │  factory.py - Provider instantiation
└────────────────────┘
          │
          ▼
┌────────────────────┐
│    Interface       │  interface.py - ChatProviderInterface ABC
└────────────────────┘
          │
     ┌────┼────────────┐
     ▼    ▼            ▼
┌──────┐ ┌──────────┐ ┌──────────┐
│Slack │ │  Fides   │ │  Teams   │  Provider implementations
│      │ │  Chat    │ │ (future) │
└──────┘ └──────────┘ └──────────┘
```

## Files

| File | Description |
|------|-------------|
| `interface.py` | Abstract base class defining the chat provider contract |
| `models.py` | Provider-agnostic data models (ChatMessage, ChatUser, ChatChannel) |
| `slack_provider.py` | Slack implementation of ChatProviderInterface |
| `fides_chat_provider.py` | In-memory implementation for browser-based questionnaire chat |
| `factory.py` | Factory function to instantiate the correct provider |
| `README.md` | This documentation file |

## Concept Mappings: Slack vs Microsoft Teams

When implementing a new provider, use this reference to understand how concepts map between platforms:

| Concept | Slack | Microsoft Teams |
|---------|-------|-----------------|
| **Organization** | Workspace | Tenant (Azure AD) |
| **Channel/Group** | Channel ID (e.g., `C0A7T97J66R`) | Team ID + Channel ID |
| **Thread/Reply** | `thread_ts` timestamp | `replyToId` (activity reference) |
| **Message ID** | `ts` timestamp (e.g., `1768422423.695969`) | Activity ID (GUID) |
| **User ID** | Slack User ID (e.g., `U07QDTMQ805`) | Azure AD Object ID (GUID) |
| **Bot Auth** | OAuth2 Bot Token | Azure AD + Bot Framework Token |
| **Webhooks** | Events API + HMAC-SHA256 | Bot Framework Activity Handler |
| **Typing Indicator** | `assistant.threads.setStatus` | `typing` activity |
| **Message Color/Styling** | Attachments with `color` field | Adaptive Cards |
| **Direct Messages** | DM channels | 1:1 chat with `conversation.id` |

## Interface Methods

### Core Messaging

- `send_message(channel_id, text, color)` - Send a message to a channel
- `send_thread_reply(channel_id, thread_id, text)` - Reply in a thread
- `update_message(channel_id, message_id, text, color)` - Edit an existing message

### User & Channel Info

- `get_channels()` - List available channels
- `get_user_info(user_id)` - Get user details including email

### Status Indicators

- `set_typing_indicator(channel_id, thread_id, status)` - Show "thinking" indicator
- `clear_typing_indicator(channel_id, thread_id)` - Clear the indicator

### Security

- `verify_webhook_signature(timestamp, body, signature)` - Verify incoming webhook

### Channel Management

- `join_channel(channel_id)` - Join a channel (if required by provider)

## Adding a New Provider

To add support for a new chat platform (e.g., Microsoft Teams):

1. **Create the provider implementation** in `teams_provider.py`:
   ```python
   from fidesplus.service.chat.provider.interface import ChatProviderInterface
   from fidesplus.service.chat.entities import ChatMessage, ChatUser, ChatChannel
   
   class TeamsChatProvider(ChatProviderInterface):
       def __init__(self, config: ChatProviderConfig):
           self._config = config
           # Initialize Teams SDK/client
       
       def send_message(self, channel_id, text, color=None):
           # Convert color to Adaptive Card if needed
           # Call Teams API
           return ChatMessage(id=activity_id, ...)
   ```

2. **Register in the factory** (`factory.py`):
   ```python
   def get_chat_provider(config: ChatProviderConfig) -> ChatProviderInterface:
       if config.provider_type == "slack":
           return SlackChatProvider(config)
       elif config.provider_type == "teams":
           from .teams_provider import TeamsChatProvider
           return TeamsChatProvider(config)
       raise UnsupportedProviderError(...)
   ```

3. **Update database model** to support Teams credentials:
   - Add `provider_type` column (if not exists)
   - Add Teams-specific fields (tenant_id, etc.)

4. **Create Teams OAuth flow** (if using OAuth):
   - Similar to `slack_oauth.py` but for Azure AD

## Provider-Specific Notes

### Slack

- Channel IDs start with `C` (public), `D` (DM), `G` (private)
- Thread timestamps are unique message identifiers
- Bot must join channels before posting (handled automatically)
- Colored sidebars use the `attachments.color` field

### Fides Chat Provider

- In-memory message store, no external service needed
- Returns a single virtual channel (`fides_channel` / `fides-questionnaire`)
- Message IDs are sequential (`fides_msg_1`, `fides_msg_2`, ...)
- User info is set at construction time (email, display name, user ID)
- All auth/webhook methods are no-ops (return True)
- Browser polls for new messages via the questionnaire chat API

### Microsoft Teams (Future)

- Requires Azure AD app registration
- Bot Framework SDK for messaging
- Adaptive Cards for rich formatting
- `conversation.id` identifies chat context
- Activity IDs are GUIDs, not timestamps
- No explicit "join channel" - bot is added to team

