### Dokumentasi Integrasi RabbitMQ di Laravel

### **1. File Konfigurasi: `config/rabbitmq.php`**

File konfigurasi ini digunakan untuk mengatur koneksi ke server RabbitMQ.

```php
return [
    'host' => env('RABBITMQ_HOST', '127.0.0.1'),
    'port' => env('RABBITMQ_PORT', 5672),
    'user' => env('RABBITMQ_USER', 'guest'),
    'password' => env('RABBITMQ_PASSWORD', 'guest'),
    'queue' => env('RABBITMQ_QUEUE', 'default_queue'),
];
```

- **host**: Menentukan hostname untuk server RabbitMQ (default: `127.0.0.1`).
- **port**: Menentukan port untuk menghubungkan ke RabbitMQ (default: `5672`).
- **user**: Nama pengguna yang digunakan untuk otentikasi (default: `guest`).
- **password**: Kata sandi yang digunakan untuk otentikasi (default: `guest`).
- **queue**: Menentukan nama antrian untuk komunikasi (default: `default_queue`).

---

### **2. Kelas Service: `app/Services/RabbitmqService.php`**

Kelas ini menangani interaksi dengan RabbitMQ. Kelas ini menghubungkan ke server RabbitMQ, menerbitkan pesan ke antrian, dan mengkonsumsi pesan dari antrian.

#### **Properti**:
- **$connection**: Menyimpan objek koneksi ke RabbitMQ.
- **$channel**: Menyimpan objek saluran untuk menerbitkan dan mengkonsumsi pesan.

```PHP
/**
 * Publish message to RabbitMQ queue
 *
 * @param string $messageContent The content of the message to be sent
 * @param string $routingKey The routing key for the message (default: 'whatsapp')
 */
public function publish(string $messageContent, string $routingKey = 'whatsapp')
{
    try {
        $messageArray = json_decode($messageContent, true);

        if ($messageArray === null) {
            throw new \Exception('Invalid JSON format');
        }

        $jsonMessage = json_encode($messageArray);
        $message = new AMQPMessage($jsonMessage);

        $this->channel->basic_publish($message, 'notification', $routingKey);
    } catch (\Exception $e) {
        echo "Terjadi kesalahan saat mengirim pesan: " . $e->getMessage() . PHP_EOL;
    }
}

/**
 * Consume messages from RabbitMQ queue
 */
public function consume(callable $callback)
{
    try {
        $this->channel->basic_consume('whatsapp', '', false, true, false, false, function (AMQPMessage $message) use ($callback) {
            echo "Routing Key: " . $message->getRoutingKey() . PHP_EOL;
            echo "Isi Pesan: " . $message->getBody() . PHP_EOL;
            $callback($message);  // Call the closure passed from the command
        });
        $this->channel->consume();
    } catch (\Exception $e) {
        echo "Terjadi kesalahan saat menerima pesan: " . $e->getMessage() . PHP_EOL;
    }
}

/**
 * Close the connection and channel when the object is destructed
 */
public function __destruct()
{
    $this->channel->close();
    $this->connection->close();
}
```

#### **Konstruktor**:
- Membuat koneksi ke server RabbitMQ menggunakan nilai konfigurasi dari `config/rabbitmq.php`.
- Mendeklarasikan exchange dengan nama `notification` (tipe `direct`) dan antrian dengan nama `whatsapp` (dikonfigurasi untuk menggunakan quorum).
- Mengikat antrian `whatsapp` ke exchange `notification` dengan routing key `whatsapp`.

#### **Metode**:

- **publish**:
    - Mengirim pesan ke antrian RabbitMQ.
    - Parameter:
        - `$messageContent`: Isi pesan yang akan dikirim.
        - `$routingKey`: Routing key untuk pesan (default: `whatsapp`).
    - Mengirim pesan menggunakan metode `basic_publish`.

- **consume**:
    - Mendengarkan pesan dari antrian `whatsapp`.
    - Setelah pesan diterima, callback yang diberikan akan dipanggil untuk memproses pesan.

- **__destruct**:
    - Menutup koneksi dan saluran ketika objek dihancurkan.

---

### **3. Perintah Console: `app/Console/Commands/RabbitMQConsumer.php`**

Ini adalah perintah Artisan Laravel yang mengkonsumsi pesan dari RabbitMQ dan mengirim pemberitahuan.

#### **Properti**:
- **$signature**: Nama perintah (`app:rabbitmq-consume`).
- **$description**: Deskripsi perintah (`Consume messages from RabbitMQ and send notifications`).
- **$notification**: Instansi dari `NotificationService` yang digunakan untuk mengirim pemberitahuan.

```PHP
/**
 * Execute the console command.
 */
public function handle(RabbitmqService $rabbit)
{
    $this->info('Waiting for messages...');
    $rabbit->consume(function ($message) {
        $body = $message->getBody();
        $data = json_decode($body, true);
        if ($data === null) {
            $this->info('Received invalid JSON message.');
            return;
        }

        $this->info('Received message: ' . print_r($data, true));

        $startTime = microtime(true);

        $responseWhatsapp = $this->notification->sendNotification('WhatsApp', $data['number'], $data['message']);
        $responseTelegram = $this->notification->sendNotification('Telegram', '-974886024', $data['message']);

        $endTime = microtime(true);
        $executionTime = $endTime - $startTime;
        $this->info("Time taken to send WhatsApp or Telegram notification: " . round($executionTime, 2) . " seconds.");

        if ($responseWhatsapp->getStatusCode() === 200) {
            $this->info("WhatsApp notification sent successfully." . $responseWhatsapp->getContent());
        } else {
            $this->error("Failed to send WhatsApp notification: " . $responseWhatsapp->getContent());
        }

        if ($responseTelegram->getStatusCode() === 200) {
            $this->info("Telegram notification sent successfully.". $responseTelegram->getContent());
        } else {
            $this->error("Failed to send Telegram notification: " . $responseTelegram->getContent());
        }
    });
}
```

#### **Metode**:

- **__construct**:
    - Menyuntikkan dependensi `NotificationService`.

- **handle**:
    - Mengkonsumsi pesan dari antrian `whatsapp` menggunakan `RabbitmqService`.
    - Setelah menerima pesan, perintah ini memanggil metode `sendNotification` dari `NotificationService` untuk mengirim pemberitahuan melalui WhatsApp dan Telegram.
    - Mengukur waktu yang dibutuhkan untuk mengirim pemberitahuan dan mencatat hasilnya.
    - Mencatat keberhasilan atau kegagalan proses pengiriman pemberitahuan untuk WhatsApp dan Telegram.

---

### **4. Contoh Controller: Metode `sendTestMessage`**

Metode controller contoh ini menunjukkan bagaimana cara menerbitkan pesan ke antrian RabbitMQ.

```php
public function sendTestMessage(RabbitmqService $rabbitmqService)
{
    $data = [
        'code' => '', // Bisa diisi jika perlu
        'number' => '628991061911', // Nomor yang diterima (required jika digunakan untuk WhatsApp)
        'message' => 'Test RabbitMQ message' // Pesan yang dikirim
    ];

    $jsonMessage = json_encode($data);

    try {
        $rabbitmqService->publish($jsonMessage);
        return response()->json(['status' => 'success', 'message' => 'Notification sent', 'data' => $jsonMessage]);
    } catch (\Exception $e) {
        return response()->json(['status' => 'error', 'message' => 'Failed to send notification', 'error' => $e->getMessage()]);
    }
}
```

- **publish**: Memanggil metode `publish` dari `RabbitmqService` untuk mengirim pesan ke antrian RabbitMQ dengan isi `'Test RabbitMQ message'`.

---

### **5. Layanan Pemberitahuan (`NotificationService`)**

Meskipun tidak disertakan dalam kode yang diberikan, kelas `NotificationService` bertanggung jawab untuk mengirim pemberitahuan. Kelas ini diasumsikan memiliki metode seperti `sendNotification` yang menangani pengiriman pesan ke berbagai platform seperti WhatsApp dan Telegram.

#### **sendNotification**:
- **Parameter**:
    - `platform`: Platform yang akan digunakan untuk mengirim pemberitahuan (misalnya, `'WhatsApp'` atau `'Telegram'`).
    - `recipient`: ID penerima (misalnya, nomor telepon atau ID Telegram).
    - `message`: Isi pesan yang akan dikirim.
- **Return**: Objek respons (misalnya, status dari permintaan HTTP ke layanan pemberitahuan).

---

### **6. Alur Kerja Secara Umum**

1. **Penerbitan Pesan**:
   - Metode `sendTestMessage` (dari controller) mengirim pesan ke antrian RabbitMQ menggunakan `RabbitmqService`.
   
2. **Konsumsi Pesan**:
   - Perintah `RabbitMQConsumer` mengkonsumsi pesan dari antrian `whatsapp`.
   
3. **Pengiriman Pemberitahuan**:
   - Setelah menerima pesan, perintah `RabbitMQConsumer` mengirim pemberitahuan melalui WhatsApp dan Telegram menggunakan `NotificationService`.
   
4. **Pencatatan**:
   - Perintah `RabbitMQConsumer` mencatat status dari setiap pemberitahuan (sukses atau gagal), serta waktu yang diperlukan untuk mengirim pemberitahuan.

---

### **7. Cara Menggunakan**

#### **Menerbitkan Pesan**:
Anda dapat memicu pengiriman pesan uji ke antrian RabbitMQ dengan memanggil metode `sendTestMessage` dalam controller:
```php
// Contoh URL: /send-test-message
public function sendTestMessage(RabbitmqService $rabbitmqService)
{
    $data = [
        'code' => '', // Bisa diisi jika perlu
        'number' => '628991061911', // Nomor yang diterima (required jika digunakan untuk WhatsApp)
        'message' => 'Test RabbitMQ message' // Pesan yang dikirim
    ];

    $jsonMessage = json_encode($data);

    try {
        $rabbitmqService->publish($jsonMessage);
        return response()->json(['status' => 'success', 'message' => 'Notification sent', 'data' => $jsonMessage]);
    } catch (\Exception $e) {
        return response()->json(['status' => 'error', 'message' => 'Failed to send notification', 'error' => $e->getMessage()]);
    }
}
```

#### **Mengkonsumsi Pesan**:
Untuk mulai mengkonsumsi pesan dari RabbitMQ dan mengirim pemberitahuan, jalankan perintah Artisan berikut:
```bash
php artisan app:rabbitmq-consume
```

Ini akan terus-menerus mendengarkan pesan baru di antrian `whatsapp` dan mencoba mengirim pemberitahuan melalui WhatsApp dan Telegram.

---

### **8. Peningkatan Potensial**

- **Penanganan Kesalahan**: Meningkatkan penanganan kesalahan untuk mencoba kembali pesan yang gagal dikonsumsi atau pengiriman pemberitahuan yang gagal.
- **Skalabilitas Antrian**: Pertimbangkan untuk menambahkan lebih banyak antrian untuk jenis pemberitahuan yang berbeda (misalnya, `telegram`, `email`) dan menghubungkannya dengan routing key yang relevan.
- **Pengakuan Pesan**: Menambahkan pengakuan pesan (yaitu, mengonfirmasi bahwa pesan telah berhasil dikonsumsi) ke RabbitMQ.
