# ConverseDriver Integration with WhatsappService

## Overview

The `ConverseDriver` has been updated to work seamlessly with the `WhatsappService` for handling WhatsApp chatbot interactions. This integration allows the driver to be deployed on a separate server while maintaining full compatibility with the main application's WhatsApp messaging infrastructure.

## Key Changes

### 1. **Direct WhatsappService Integration**
- Removed dependency on external HTTP API calls
- Now directly uses `WhatsappService` for all message operations
- Maintains database consistency with the main application

### 2. **Enhanced Error Handling**
- Comprehensive logging using Laravel's `Log` facade
- Proper exception handling for all operations
- Detailed error messages for debugging

### 3. **Organization-Based Configuration**
- Automatically initializes WhatsApp service based on organization ID
- Fetches WhatsApp credentials from organization metadata
- Validates configuration before processing messages

### 4. **Contact Management**
- Automatically looks up contacts by phone number
- Uses contact UUIDs for message sending
- Maintains contact relationships with the organization

## Architecture

```
Incoming WhatsApp Message
    ↓
ConverseDriver::buildPayload()
    ↓
Extract organization_id
    ↓
Initialize WhatsappService
    ↓
ConverseDriver::matchesRequest()
    ↓
Process message (text/media/interactive)
    ↓
BotMan processes with your bot logic
    ↓
ConverseDriver::buildServicePayload()
    ↓
Lookup Contact by phone
    ↓
ConverseDriver::sendPayload()
    ↓
WhatsappService::sendMessage/sendMedia()
    ↓
Facebook Graph API
```

## Configuration Requirements

### 1. **Payload Structure**

The incoming webhook payload must include the `organization_id`:

```json
{
  "event": "message.received",
  "organization_id": 1,
  "data": {
    "value": {
      "messaging_product": "whatsapp",
      "metadata": {
        "display_phone_number": "1234567890",
        "phone_number_id": "123456789"
      },
      "contacts": [
        {
          "profile": {
            "name": "John Doe"
          },
          "wa_id": "1234567890"
        }
      ],
      "messages": [
        {
          "from": "1234567890",
          "id": "wamid.xxx",
          "timestamp": "1234567890",
          "type": "text",
          "text": {
            "body": "Hello"
          }
        }
      ]
    }
  }
}
```

### 2. **Organization Metadata**

The organization record must have WhatsApp configuration in its metadata:

```json
{
  "whatsapp": {
    "access_token": "your_facebook_access_token",
    "app_id": "your_facebook_app_id",
    "phone_number_id": "your_whatsapp_phone_number_id",
    "waba_id": "your_whatsapp_business_account_id"
  }
}
```

### 3. **Database Access**

The driver requires access to the following tables:
- `organizations` - For WhatsApp configuration
- `contacts` - For contact lookup and management
- `chats` - For message history (via WhatsappService)
- `chat_logs` - For chat logging (via WhatsappService)
- `chat_media` - For media attachments (via WhatsappService)

### 4. **Redis Configuration**

Redis is used for duplicate message detection:
- Messages are cached for 24 hours
- Key format: `message_id:{wamid}`

## Supported Message Types

### 1. **Text Messages**
```php
// Incoming: Plain text from user
// Outgoing: Plain text response
$bot->reply('Hello! How can I help you?');
```

### 2. **Media Messages**
```php
// Incoming: Image, Video, Document
// Outgoing: Send media with caption
$bot->reply(OutgoingMessage::create('Caption text')
    ->withAttachment(new Image('https://example.com/image.jpg')));
```

### 3. **Interactive Buttons (1-3 options)**
```php
$question = Question::create('Choose an option:')
    ->addButton(Button::create('Option 1')->value('opt1'))
    ->addButton(Button::create('Option 2')->value('opt2'))
    ->addButton(Button::create('Option 3')->value('opt3'));

$bot->ask($question, function (Answer $answer) {
    // Handle response
});
```

### 4. **Interactive Lists (4+ options)**
```php
$question = Question::create('Select from menu:')
    ->addButton(Button::create('Item 1')->value('item1'))
    ->addButton(Button::create('Item 2')->value('item2'))
    ->addButton(Button::create('Item 3')->value('item3'))
    ->addButton(Button::create('Item 4')->value('item4'));

$bot->ask($question, function (Answer $answer) {
    // Handle response
});
```

## Deployment Options

### Option 1: Same Server (Monolithic)
Deploy the driver alongside the main application. No additional configuration needed.

### Option 2: Separate Server (Microservice)
Deploy the driver on a separate server for chatbot logic:

1. **Setup Database Connection**
   - Configure `.env` to connect to the main application's database
   - Ensure network connectivity between servers

2. **Setup Redis Connection**
   - Configure Redis connection to the same instance or cluster
   - Required for duplicate message detection

3. **Configure BotMan**
   ```php
   // config/botman/config.php
   return [
       'conversation_cache_time' => 40,
       'user_cache_time' => 30,
   ];
   ```

4. **Register the Driver**
   ```php
   // In your BotMan service provider or bootstrap
   DriverManager::loadDriver(\App\Drivers\WhatsApp\ConverseDriver::class);
   ```

5. **Setup Webhook Endpoint**
   ```php
   // routes/api.php or routes/web.php
   Route::match(['get', 'post'], '/botman/webhook', 'BotManController@handle');
   ```

## Usage Example

### Basic Bot Setup

```php
<?php

namespace App\Http\Controllers;

use BotMan\BotMan\BotMan;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Outgoing\Question;
use BotMan\BotMan\Messages\Outgoing\Actions\Button;

class BotManController extends Controller
{
    public function handle()
    {
        $botman = app('botman');

        // Listen for specific keywords
        $botman->hears('hello|hi|hey', function (BotMan $bot) {
            $bot->reply('Hello! Welcome to our service. How can I help you today?');
        });

        // Ask questions
        $botman->hears('help', function (BotMan $bot) {
            $question = Question::create('What do you need help with?')
                ->addButton(Button::create('Products')->value('products'))
                ->addButton(Button::create('Orders')->value('orders'))
                ->addButton(Button::create('Support')->value('support'));

            $bot->ask($question, function (Answer $answer) use ($bot) {
                if ($answer->isInteractiveMessageReply()) {
                    $value = $answer->getValue();
                    $bot->reply("You selected: $value");
                    // Handle specific option
                }
            });
        });

        // Fallback for unmatched messages
        $botman->fallback(function (BotMan $bot) {
            $bot->reply('Sorry, I didn\'t understand that. Type "help" for options.');
        });

        $botman->listen();
    }
}
```

## Logging and Debugging

The driver provides comprehensive logging at various stages:

### Log Levels

1. **Info**: Normal operation flow
   - Request received
   - Message processing
   - Service initialization
   - Message sent successfully

2. **Warning**: Non-critical issues
   - Contact not found (will be handled)
   - Duplicate message detected
   - Missing optional data

3. **Error**: Critical issues requiring attention
   - WhatsApp service not initialized
   - Missing organization configuration
   - Failed to send message
   - Exception during processing

### Log Examples

```
[INFO] ConverseDriver_Request: {"event":"message.received",...}
[INFO] ConverseDriver: WhatsApp service initialized successfully for organization: 1
[INFO] ConverseDriver: Building service payload for message: Hello
[INFO] ConverseDriver: Message sent successfully
```

## Error Handling

### Common Issues and Solutions

1. **"WhatsApp service not initialized"**
   - Ensure `organization_id` is included in the payload
   - Verify organization exists in database
   - Check WhatsApp configuration in organization metadata

2. **"Contact not found"**
   - Contact will be auto-created on first message from main app
   - Ensure contact exists before bot sends first message
   - Check phone number format (E.164 format required)

3. **"Missing required WhatsApp configuration"**
   - Verify all required fields in organization metadata:
     - access_token
     - phone_number_id
     - waba_id

4. **"Duplicate message detected"**
   - This is normal behavior (prevents duplicate processing)
   - Check Redis connection if messages aren't being processed

## Performance Considerations

1. **Redis Caching**
   - Messages are cached for 24 hours
   - Prevents duplicate processing
   - Minimal memory footprint

2. **Database Queries**
   - Contact lookup is optimized with indexes
   - Organization config is cached per request
   - Consider implementing query caching for high volume

3. **Media Handling**
   - Media URLs are fetched on-demand
   - Consider implementing CDN for media files
   - Large files may impact response time

## Security Considerations

1. **Webhook Verification**
   - Implement webhook signature verification
   - Validate organization_id against allowed values
   - Use HTTPS for all webhook endpoints

2. **Access Control**
   - Ensure database user has minimal required permissions
   - Restrict access to organization metadata
   - Implement rate limiting on webhook endpoint

3. **Data Privacy**
   - Log messages comply with data privacy regulations
   - Consider implementing message encryption
   - Regularly rotate access tokens

## Testing

### Unit Testing

```php
// tests/Unit/ConverseDriverTest.php
public function test_driver_initializes_whatsapp_service()
{
    $driver = new ConverseDriver([]);
    $request = Request::create('/webhook', 'POST', [
        'event' => 'message.received',
        'organization_id' => 1,
        'data' => [/* ... */]
    ]);
    
    $driver->buildPayload($request);
    
    $this->assertTrue($driver->isConfigured());
}
```

### Integration Testing

```php
// tests/Feature/BotManTest.php
public function test_bot_responds_to_hello()
{
    $response = $this->postJson('/botman/webhook', [
        'event' => 'message.received',
        'organization_id' => 1,
        'data' => [
            'value' => [
                'messages' => [
                    ['type' => 'text', 'text' => ['body' => 'hello']]
                ]
            ]
        ]
    ]);
    
    $response->assertStatus(200);
}
```

## Migration from Old Driver

If you're migrating from the old HTTP-based driver:

1. **Update payload structure** to include `organization_id`
2. **Remove external API endpoints** (no longer needed)
3. **Update bot logic** to use new message format
4. **Test thoroughly** with all message types
5. **Monitor logs** for any issues during transition

## Support and Troubleshooting

For issues or questions:
1. Check logs in `storage/logs/laravel.log`
2. Verify database connectivity
3. Confirm Redis is accessible
4. Validate organization configuration
5. Test with simple text messages first

## Future Enhancements

Potential improvements for future versions:
- [ ] Webhook signature verification
- [ ] Message queue for high volume
- [ ] Advanced media handling (compression, thumbnails)
- [ ] Multi-language support
- [ ] Analytics and metrics
- [ ] Conversation state management
- [ ] AI/NLP integration hooks


