<?php

declare(strict_types=1);

require_once __DIR__ . '/../vendor/autoload.php';

use App\Framework\Notification\Notification;
use App\Framework\Notification\NotificationDispatcher;
use App\Framework\Notification\Dispatcher\DispatchStrategy;
use App\Framework\Notification\ValueObjects\NotificationChannel;
use App\Framework\Notification\ValueObjects\NotificationPriority;
use App\Framework\Notification\ValueObjects\SystemNotificationType;

/**
 * Multi-Channel Notification Dispatch Example
 *
 * Demonstrates the four dispatch strategies:
 * - ALL: Send to all channels regardless of failures
 * - FIRST_SUCCESS: Stop after first successful delivery
 * - FALLBACK: Try next only if previous failed
 * - ALL_OR_NONE: All must succeed or entire dispatch fails
 */

echo "=== Multi-Channel Notification Dispatch Examples ===\n\n";

// Setup (in real app, get from DI container)
$dispatcher = $container->get(NotificationDispatcher::class);

// Example 1: ALL Strategy - Send to all channels
echo "1. ALL Strategy - Send to all channels\n";
echo str_repeat("-", 50) . "\n";

$notification = Notification::create(
    recipientId: 'user_123',
    type: new SystemNotificationType('system.update'),
    title: 'System Update Available',
    body: 'A new system update is available. Please review and install.',
    NotificationChannel::TELEGRAM,
    NotificationChannel::EMAIL,
    NotificationChannel::SMS
)->withPriority(NotificationPriority::NORMAL);

$result = $dispatcher->sendNow($notification, DispatchStrategy::ALL);

echo "Status: " . ($result->isSuccess() ? "✅ SUCCESS" : "❌ FAILURE") . "\n";
echo "Successful channels: " . count($result->getSuccessful()) . "\n";
echo "Failed channels: " . count($result->getFailed()) . "\n";

foreach ($result->getSuccessful() as $channelResult) {
    echo "  ✅ {$channelResult->channel->value}: " . json_encode($channelResult->metadata) . "\n";
}

foreach ($result->getFailed() as $channelResult) {
    echo "  ❌ {$channelResult->channel->value}: {$channelResult->errorMessage}\n";
}

echo "\n";

// Example 2: FIRST_SUCCESS Strategy - Stop after first success
echo "2. FIRST_SUCCESS Strategy - Quick delivery\n";
echo str_repeat("-", 50) . "\n";

$notification = Notification::create(
    recipientId: 'user_456',
    type: new SystemNotificationType('order.shipped'),
    title: 'Your Order Has Shipped',
    body: 'Your order #12345 has been shipped and is on its way!',
    NotificationChannel::TELEGRAM,  // Try Telegram first
    NotificationChannel::EMAIL,     // Then Email if Telegram fails
    NotificationChannel::SMS        // Then SMS if Email fails
)->withPriority(NotificationPriority::HIGH);

$result = $dispatcher->sendNow($notification, DispatchStrategy::FIRST_SUCCESS);

echo "Status: " . ($result->isSuccess() ? "✅ SUCCESS" : "❌ FAILURE") . "\n";
echo "Delivery stopped after first success\n";
echo "Channels attempted: " . (count($result->getSuccessful()) + count($result->getFailed())) . "\n";

foreach ($result->getSuccessful() as $channelResult) {
    echo "  ✅ {$channelResult->channel->value}: Delivered successfully\n";
}

foreach ($result->getFailed() as $channelResult) {
    echo "  ❌ {$channelResult->channel->value}: {$channelResult->errorMessage}\n";
}

echo "\n";

// Example 3: FALLBACK Strategy - Telegram -> Email -> SMS chain
echo "3. FALLBACK Strategy - Graceful degradation\n";
echo str_repeat("-", 50) . "\n";

$notification = Notification::create(
    recipientId: 'user_789',
    type: new SystemNotificationType('security.alert'),
    title: 'Security Alert',
    body: 'Unusual login activity detected on your account.',
    NotificationChannel::TELEGRAM,  // Primary: Telegram (instant)
    NotificationChannel::EMAIL,     // Fallback 1: Email (reliable)
    NotificationChannel::SMS        // Fallback 2: SMS (last resort)
)->withPriority(NotificationPriority::URGENT);

$result = $dispatcher->sendNow($notification, DispatchStrategy::FALLBACK);

echo "Status: " . ($result->isSuccess() ? "✅ SUCCESS" : "❌ FAILURE") . "\n";
echo "Fallback chain executed\n";

foreach ($result->getSuccessful() as $channelResult) {
    echo "  ✅ {$channelResult->channel->value}: Delivered (fallback stopped here)\n";
}

foreach ($result->getFailed() as $channelResult) {
    echo "  ❌ {$channelResult->channel->value}: Failed, tried next channel\n";
}

echo "\n";

// Example 4: ALL_OR_NONE Strategy - Critical notifications
echo "4. ALL_OR_NONE Strategy - All must succeed\n";
echo str_repeat("-", 50) . "\n";

$notification = Notification::create(
    recipientId: 'user_101',
    type: new SystemNotificationType('account.deleted'),
    title: 'Account Deletion Confirmation',
    body: 'Your account has been permanently deleted as requested.',
    NotificationChannel::EMAIL,
    NotificationChannel::SMS
)->withPriority(NotificationPriority::URGENT);

$result = $dispatcher->sendNow($notification, DispatchStrategy::ALL_OR_NONE);

echo "Status: " . ($result->isSuccess() ? "✅ ALL SUCCEEDED" : "❌ STOPPED ON FIRST FAILURE") . "\n";
echo "Successful channels: " . count($result->getSuccessful()) . "\n";
echo "Failed channels: " . count($result->getFailed()) . "\n";

if ($result->isFailure()) {
    echo "⚠️  Critical notification failed - some channels did not receive the message\n";
}

foreach ($result->getSuccessful() as $channelResult) {
    echo "  ✅ {$channelResult->channel->value}: Delivered\n";
}

foreach ($result->getFailed() as $channelResult) {
    echo "  ❌ {$channelResult->channel->value}: {$channelResult->errorMessage}\n";
}

echo "\n";

// Example 5: Async Multi-Channel with Strategy
echo "5. Async Multi-Channel Dispatch\n";
echo str_repeat("-", 50) . "\n";

$notification = Notification::create(
    recipientId: 'user_202',
    type: new SystemNotificationType('newsletter.weekly'),
    title: 'Your Weekly Newsletter',
    body: 'Check out this week\'s highlights and updates.',
    NotificationChannel::EMAIL,
    NotificationChannel::TELEGRAM
)->withPriority(NotificationPriority::LOW);

// Async dispatch - queued with priority mapping
$dispatcher->send($notification, async: true, strategy: DispatchStrategy::ALL);

echo "✅ Notification queued for async dispatch\n";
echo "Strategy: ALL (will attempt all channels in background)\n";
echo "Priority: LOW (mapped to queue priority)\n";

echo "\n";

// Example 6: Strategy Selection Based on Priority
echo "6. Dynamic Strategy Selection\n";
echo str_repeat("-", 50) . "\n";

function selectStrategy(NotificationPriority $priority): DispatchStrategy
{
    return match ($priority) {
        NotificationPriority::URGENT => DispatchStrategy::ALL_OR_NONE,  // Critical: all must succeed
        NotificationPriority::HIGH => DispatchStrategy::FIRST_SUCCESS,  // Quick delivery
        NotificationPriority::NORMAL => DispatchStrategy::FALLBACK,     // Graceful degradation
        NotificationPriority::LOW => DispatchStrategy::ALL,             // Best effort
    };
}

$urgentNotification = Notification::create(
    recipientId: 'user_303',
    type: new SystemNotificationType('payment.failed'),
    title: 'Payment Failed',
    body: 'Your payment could not be processed.',
    NotificationChannel::EMAIL,
    NotificationChannel::SMS
)->withPriority(NotificationPriority::URGENT);

$strategy = selectStrategy($urgentNotification->priority);
echo "Priority: {$urgentNotification->priority->value}\n";
echo "Selected Strategy: {$strategy->value}\n";

$result = $dispatcher->sendNow($urgentNotification, $strategy);
echo "Result: " . ($result->isSuccess() ? "✅ SUCCESS" : "❌ FAILURE") . "\n";

echo "\n";

// Summary
echo "=== Strategy Summary ===\n";
echo "ALL: Send to all channels, continue even if some fail\n";
echo "  Use case: Non-critical updates, newsletters, marketing\n\n";

echo "FIRST_SUCCESS: Stop after first successful delivery\n";
echo "  Use case: Time-sensitive notifications, quick delivery needed\n\n";

echo "FALLBACK: Try next only if previous failed\n";
echo "  Use case: Graceful degradation, Telegram -> Email -> SMS chain\n\n";

echo "ALL_OR_NONE: All must succeed or entire dispatch fails\n";
echo "  Use case: Critical notifications, legal compliance, account actions\n\n";

echo "✅ Multi-channel dispatch examples completed\n";
